Middleware لاگینگ درخواست (داخلی) 🌐
using Microsoft.AspNetCore.HttpLogging;
builder.Services.AddHttpLogging(o =>
{
o.LoggingFields = HttpLoggingFields.RequestMethod
| HttpLoggingFields.RequestPath
| HttpLoggingFields.ResponseStatusCode
| HttpLoggingFields.Duration;
});
var app = builder.Build();
app.UseHttpLogging();
این متد، مسیر، وضعیت و مدت زمان را ثبت میکند. از لاگ کردن bodyها خودداری کنید مگر اینکه دلیل محکمی داشته باشید.
مسیرهای پرترافیک: LoggerMessage.Define ⚡️
با پیشکامپایل کردن قالبهای پیام، از تخصیص حافظه برای فرمتدهی رشته جلوگیری کنید. سورس جنریتور کد لاگینگ بهینهای ایجاد میکند.
static class Logs
{
private static readonly Action<ILogger, string, Exception?> _cacheMiss =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(1001, "CacheMiss"),
"Cache miss for key {Key}");
public static void CacheMiss(this ILogger log, string key) => _cacheMiss(log, key, null);
}
// استفاده
log.CacheMiss(key);
لاگهای فایلی (اختیاری، با Serilog) 📂
ارائهدهندگان داخلی در فایل نمینویسند. اگر میخواهید فایلهای چرخشی (rolling files) به صورت محلی داشته باشید، Serilog را اضافه کنید:
dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.File
در برنامه:
using Serilog;
var logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("logs/app-.log", rollingInterval: RollingInterval.Day)
.CreateLogger();
builder.Host.UseSerilog(logger);
✅️چه چیزی را لاگ کنیم (و چه چیزی را نه)❌️
👍 لاگ کنید: رویدادهای شروع/پایان، فراخوانیهای خارجی (هدف + مدت زمان)، رویدادهای بیزینسی، هشدارها با زمینه، خطاهای مدیریت شده با stack traces.
👎 لاگ نکنید: اسرار (secrets)، body کامل درخواست/پاسخ با اطلاعات شخصی، حلقههای پرحرف، اسپم heartbeat.
اشتباهات رایج 🤦♂️
استفاده از درونیابی رشته در پیامهای لاگ. از قالبها با placeholderهای نامدار استفاده کنید.
• لاگ کردن استثناها بدون پاس دادن خود آبجکت exception.
• نداشتن ارتباط (correlation) بین لاگهای یک درخواست.
• تبدیل همه چیز به Information یا Debug و هرگز کوتاه نکردن آن.
• نوشتن تصادفی اسرار در لاگها (توکنها، پسوردها).
🔖 هشتگها:
#CSharp #DotNet #ASPNETCore #Logging #StructuredLogging #Observability #Serilog #Debugging
4️⃣ رویدادهای مهم اپلیکیشن را لاگ کنید 📌
به طور کلی، من سعی میکنم رویدادهای مهم را در اپلیکیشن خود لاگ کنم. این شامل اطلاعات درخواست فعلی، خطاها، شکستها، مقادیر غیرمنتظره، نقاط انشعاب و غیره است.
اگر از الگوی CQRS با MediatR استفاده میکنید، میتوانید به راحتی لاگینگ را برای تمام درخواستهای اپلیکیشن اضافه کنید.
در RequestLoggingPipelineBehavior من پراپرتی Error را به LogContext پوش میکنم.
internal sealed class RequestLoggingPipelineBehavior<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>
where TRequest : class
where TResponse : Result
{
// ...
public async Task<TResponse> Handle(...)
{
// ...
TResponse result = await next();
if (result.IsSuccess) { /* ... */ }
else
{
using (LogContext.PushProperty("Error", result.Error, true))
{
_logger.LogError(
"Completed request {RequestName} with error", requestName);
}
}
return result;
}
}
5️⃣ از Seq برای توسعه محلی استفاده کنید 🔍
Seq
یک سرور جستجو، تحلیل و هشدار self-hosted است که برای دادههای لاگ ساختاریافته ساخته شده است. استفاده از آن برای توسعه محلی رایگان است. این ابزار قابلیتهای جستجو و فیلترینگ پیشرفتهای را روی دادههای لاگ ساختاریافته ارائه میدهد.
میتوانید یک نمونه Seq را در یک کانتینر Docker بالا بیاورید:
version: '3.4'
services:
seq:
image: datalust/seq:latest
container_name: seq
environment:
- ACCEPT_EULA=Y
ports:
- 5341:5341
- 8081:80
`
خلاصه ✅
لاگهای ساختاریافته از یک ساختار یکسان پیروی میکنند و چون قابل خواندن توسط ماشین هستند، میتوانید آنها را برای اطلاعات خاص جستجو کنید. آنها زمینه و جزئیات بیشتری در مورد خطاهای اپلیکیشن ارائه میدهند و شناسایی و رفع مشکلات را آسانتر میکنند.
شما میتوانید از LogContext قدرتمند Serilog برای غنیسازی لاگهای خود با یک CorrelationId استفاده کنید.
🔖 هشتگها:
#CSharp #DotNet #Logging #StructuredLogging #Observability #Serilog