ASP.NET Core 6/Loglama Servisinin Kullanımı
Web geliştirmede loglama önemli bir konudur. Uygulamanın durumunu, uygulama üzerinde yapılan işlemleri izlemek için loglama kullanılabilir. Log mesajları uygulama tarafında log sağlayıcılara gönderilir. Log sağlayıcıları ise görülebileceği, depolanabileceği ve işlenebileceği yerlere gönderir. ASP.NET Core'un sağladığı dahili log sağlayıcıları olduğu gibi mesajları logging framework'lara gönderen üçüncü parti sağlayıcılar da vardır. Bu framework'lar mesajları toplama ve analiz etme gibi karmaşık görevlere sahip olabilirler.
Log mesajlarının üretilmesi
değiştirASP.NET Core tarafından sağlanan üç log sağlayıcı bulunmaktadır. Bunlar konsol, debug ve EventSource'tur. Debug sağlayıcısı tarafından gönderilen mesajlar System.Diagnostics.Debug sınıfı tarafından işlenebilir. EventSource sağlayıcısı mesajları PerfView gibi olay izleme araçlarına gönderir. Bu bölümde konsol sağlayıcısı kullanılacaktır. Diğer bir deyişle log kayıtları direkt konsol ekranına verilecektir. Örnek:
public class EndpointSinifi
{
public static async Task Endpoint(HttpContext context, ILogger<EndpointSinifi> logger)
{
logger.LogDebug("EndpointSinifi sınıfı içindeki Endpoint metodu");
}
}
Bu adı üstünde bir endpoint sınıfıdır. Sadelik olması açısından bu sınıfın Program.cs dosyasında rota belirtiminde kullanılması gösterilmeyecektir. Loglama yapabilmemiz için mesajın hangi kategoride olduğunu belirtmemiz gerekir. Mesajın hangi kategoriye ait olduğu ILogger servisine verilen tip parametresiyle belirtilir. Geleneksel olarak log mesajını hangi sınıf üretiyorsa o kategoriye konulması tavsiye edilir. LogDebug() benzeri log mesajlarının önem seviyesini ve amacını gösteren başka metotlar da vardır. Bunlar aşağıda gösterilmiştir:
LogTrace(): Trace seviyesinde bir mesaj üretir, geliştirme sürecinde düşük seviye hata tespiti için kullanılır. Önem seviyesi: düşük
LogDebug(): Debug seviyesinde mesaj üretir, geliştirme sürecinde düşük seviye hata tespiti için ve production sürecinde oluşan sorunların sebebini tespit etmek için kullanılır. Önem seviyesi: orta
LogInformation(): Uygulamanın durumu hakkında bilgi üretir. Önem seviyesi: orta
LogError(): Uygulama tarafından yakalanmayan hataları ve istisnaları kaydetmeye yarar Önem seviyesi: yüksek
LogCritical(): Uygulama tarafından yakalanmayan kritik hataları ve istisnaları kaydetmeye yarar. Önem seviyesi: yüksek
Bu metotların önem seviyesi azaldıkça detay miktarı artar. Bu metotlar string parametre yanında Exception tipinde de parametre alabilir. Bu metotların verdiği çıktılar sunucunun konsol ekranında gözükür. Eğer gözükmüyorsa appsettings.Development.json dosyasının şöyle değiştirmeniz gerekir:
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft.AspNetCore": "Warning"
}
}
}
Benim sistemimde varsayılan olarak loglama seviyesi Default için Information'dı. Dolayısıyla gönderdiğim log mesajı konsol ekranında gözükmüyordu. Burada Default için log seviyesini en önemsiz seviye olan Trace'e çektim. Bu sayede ürettiğim log mesajları konsol ekranında gözüküyor. Burada Default, diğer kategorilerdeki log mesajlarını belirtirken Microsoft.AspNetCore ilgili kategorideki log mesajlarını belirtir. Ekrana log mesajları basan örnek bir konsol çıktısı aşağıdaki gibidir:
dbug: Microsoft.Extensions.Hosting.Internal.Host[1] Hosting starting info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5271 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: C:\Users\bekir\OneDrive\Masaüstü\kitap\Loglama\Loglama\ dbug: Microsoft.Extensions.Hosting.Internal.Host[2] Hosting started dbug: Loglama.EndpointSinifi[0] EndpointSinifi sınıfı içindeki Endpoint metodu
Burada her bir mesajın log tipi, kategorisi ve içeriği gözükmektedir.
Program.cs dosyasında loglama yapılması
değiştirProgram.cs dosyasında loglama yapabilmemiz için bir şekilde loglama servisine ulaşılması gerekir. Bunun için WebApplication sınıfı üzerindeki Logger özelliğini kullanabiliriz. Örnek:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Logger.LogDebug("Log mesajı");
app.Run();
Bu şekilde loglama yapıldığı zaman log mesajının kategorisi uygulama adı olur. Belirli bir kategori de log mesajı üretmek içinse ILoggerFactory servisini kullanırız. Örnek:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var logger = app.Services.GetRequiredService<ILoggerFactory>().CreateLogger("Kategori");
logger.LogDebug("Log mesajı");
app.Run();
Attribute kullanarak log mesajları üretme
değiştirLogDebug() ve benzeri metotların bir alternatifi attribute kullanmaktadır. Örnek:
public partial class EndpointSinifi
{
public static async Task Endpoint(HttpContext context, ILogger<EndpointSinifi> logger)
{
logger.LogDebug("EndpointSinifi sınıfı içindeki Endpoint metodu");
LogOlustur(logger, "metin");
}
[LoggerMessage(0, LogLevel.Debug, "{mesaj} mesajı üretildi")]
public static partial void LogOlustur(ILogger logger, string mesaj);
}
Attribute yoluyla log mesajı üretme daha ziyade birden fazla yerde belirli bir şablona göre log mesajı üretmemiz gerekiyorsa faydalıdır.
Minimum loglama seviyesini gösterme
değiştirAslında bu kısmı bölümün başında daha önce görmüştük. Burada bazı tamamlayıcı bilgiler verilecektir. Mevcut durumda appsettings.Development.json dosyasının içeriği şöyledir:
{
"Logging": {
"LogLevel": {
"Default": "Trace",
"Microsoft.AspNetCore": "Warning"
}
}
}
Burada her bir kategorinin önem seviyesi belirtilmiştir. Bir kategori olarak sınıf kullanılmışsa isim alanıyla beraber belirtilmelidir. Belirli bir isim alanının altındaki bütün sınıflar için bir önem seviyesi de belirtebiliriz. Kategori olarak bir isim alanı belrttiğimiz zaman bu isim alanının altındaki alt isim alanları da aynı loglama seviyesine sahip olacaktır. Ancak elbetteki istersek daha alt isim alanlarının (veya direkt sınıfların) önem seviyesini üst isim alanından farklı bir önem seviyesine çekerek üst isim alanının belirttiği değerin geçersiz kılınmasını sağlayabiliriz. Yani burada da kategori/alt kategori mantığı vardır.
Örneğimizde Microsoft.AspNetCore isim alanının altındaki bütün sınıf kategorilerinin önem seviyesi Warning'dir. Belirtilen kategoriler dışında kalan tüm kategorilerin önem seviyesi Default girdisi ile belirtilir. ASP.NET Core'da kullanılabilecek farklı log seviyeleri ve bu log seviyelerinde log üretmek için kullanılacak metotlar önemsizden önemliye doğru aşağıdaki tabloda gösterilmiştir:
Önem | Seviye | Metot |
---|---|---|
0 | Trace | LogTrace() |
1 | Debug | LogDebug() |
2 | Information | LogInformation() |
3 | Warning | LogWarning() |
4 | Error | LogError() |
5 | Critical | LogCritical() |
6 | None |
6. seviyede log mesajı üretilemez. Bu seviye, yapılandırma dosyasında "hiçbir log mesajını gösterme" anlamında kullanılır.
Request ve response'ların loglanması
değiştirİstersek sunucuya gelen her isteği ve sonucunda döndürülen her cevabı da loglayabiliriz. Örnek (Program.cs dosyası):
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpLogging();
app.Run();
Yukarıdaki kod request pipeline'a UseHttpLogging isimli middleware'i ekler. Bu middleware gelen request'i ve giden response'u inceler ve bu request ve response hakkındaki bilgileri loglar. Bu middleware'in ürettiği loglar Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware kategorisinde ve Information önem seviyesindedir. Bu middleware'in ürettiği logları görmek için direkt bu kategoriyi, ya da üst kategorilerden birini en az Information seviyesine çekmelisiniz.
Request ve response hakkında loglanacak detaylar options pattern'iyle UseHttpLogging middleware'inin konfigure edilmesiyle belirtilebilir. Örnek (Program.cs dosyası):
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(opts => {
opts.LoggingFields = HttpLoggingFields.RequestMethod | HttpLoggingFields.RequestPath | HttpLoggingFields.ResponseStatusCode;
});
var app = builder.Build();
app.UseHttpLogging();
app.MapGet("/", ()=>"Merhaba dünya!");
app.Run();
Bu örneğimizde sadece request'in verb'ünün, path'ının ve response'un durum kodunun loglanmasını sağladık.