C# ve .NET'te günlüğe kaydetme
.NET, uygulama davranışını izlemeye ve sorunları tanılamaya yardımcı olmak için API aracılığıyla ILogger yüksek performanslı, yapılandırılmış günlüğe kaydetmeyi destekler. Günlükler, farklı günlük sağlayıcıları yapılandırılarak farklı hedeflere yazılabilir. Temel günlük sağlayıcıları yerleşiktir ve birçok üçüncü taraf sağlayıcı da mevcuttur.
Kullanmaya başlayın
Bu ilk örnekte temel bilgiler gösterilmektedir, ancak yalnızca önemsiz bir konsol uygulaması için uygundur. Bu örnek konsol uygulaması aşağıdaki NuGet paketlerine dayanır:
Sonraki bölümde, ölçeklendirme, performans, yapılandırma ve tipik programlama desenlerini göz önünde bulundurarak kodun nasıl geliştirilip geliştirilediğini göreceksiniz.
using Microsoft.Extensions.Logging;
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
Yukarıdaki örnek:
- bir ILoggerFactoryoluşturur. ,
ILoggerFactory
günlük iletilerinin nereye gönderileceğini belirleyen tüm yapılandırmayı depolar. Bu durumda, konsol günlüğü sağlayıcısını günlük iletilerinin konsola yazacak şekilde yapılandıracaksınız. - "Program" adlı kategoriye sahip bir ILogger oluşturur. Kategori, nesnesi tarafından
ILogger
günlüğe kaydedilen her iletiyle ilişkili birstring
kategoridir. Günlükleri ararken veya filtrelerken aynı sınıftan (veya kategoriden) gelen günlük iletilerini gruplandırmak için kullanılır. - Bir iletiyi
Information
düzeyinde günlüğe kaydetmek için çağrılarLogInformation. Günlük düzeyi , günlüğe kaydedilen olayın önem derecesini gösterir ve daha az önemli günlük iletilerini filtrelemek için kullanılır. Günlük girdisi ayrıca bir ileti şablonu"Hello World! Logging is {Description}."
ve anahtar-değer çiftiDescription = fun
içerir. Anahtar adı (veya yer tutucu), şablondaki küme ayraçlarının içindeki sözcükten, değer ise kalan yöntem bağımsız değişkeninden gelir.
Bu örnek için bu proje dosyası iki NuGet paketi içerir:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
</ItemGroup>
</Project>
İpucu
Günlük örneği kaynak kodunun tümü, indirilebilmeniz için Samples Browser'da bulunur. Daha fazla bilgi için bkz . Kod örneklerine göz atma: .NET'te günlüğe kaydetme.
Önemsiz olmayan bir uygulamada günlüğe kaydetme
Daha az önemsiz bir senaryoda oturum açarken önceki örnekte yapmayı göz önünde bulundurmanız gereken birkaç değişiklik vardır:
Uygulamanız Bağımlılık Ekleme (DI) veya ASP gibi bir konak kullanıyorsa. NET'in WebApplication veya Genel Ana Bilgisayarı, ve nesnelerini doğrudan oluşturmak yerine ilgili DI kapsayıcılarından kullanmanız
ILoggerFactory
ILogger
gerekir. Daha fazla bilgi için bkz . DI ve Hosts ile tümleştirme.Derleme zamanı kaynak oluşturmanın günlüğe kaydedilmesi genellikle gibi
LogInformation
uzantı yöntemlerineILogger
daha iyi bir alternatiftir. Günlüğe kaydetme kaynağı oluşturma, daha iyi performans ve daha güçlü yazma sunar ve sabitlerin yöntemlerinize yayılmasınıstring
önler. Sonuç olarak, bu tekniğin kullanılması biraz daha fazla kod gerektirir.
using Microsoft.Extensions.Logging;
internal partial class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
LogStartupMessage(logger, "fun");
}
[LoggerMessage(Level = LogLevel.Information, Message = "Hello World! Logging is {Description}.")]
static partial void LogStartupMessage(ILogger logger, string description);
}
- Günlük kategorisi adları için önerilen uygulama, günlük iletisini oluşturan sınıfın tam adını kullanmaktır. Bu, günlük iletilerini oluşturan kodla ilişkilendirmeye yardımcı olur ve günlükleri filtrelerken iyi bir denetim düzeyi sunar. CreateLogger , bu adlandırmanın kolay olmasını sağlamak için bir
Type
kabul eder.
using Microsoft.Extensions.Logging;
internal class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger<Program>();
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
}
}
- Konsol günlüklerini tek üretim izleme çözümünüz olarak kullanmıyorsanız, kullanmayı planladığınız günlük sağlayıcılarını ekleyin. Örneğin, OTLP (OpenTelemetry protokolü) üzerinden günlük göndermek için OpenTelemetry kullanabilirsiniz:
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using ILoggerFactory factory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(logging =>
{
logging.AddOtlpExporter();
});
});
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
Konaklarla tümleştirme ve bağımlılık ekleme
Uygulamanız Bağımlılık Ekleme (DI) veya ASP gibi bir konak kullanıyorsa. NET'in WebApplication veya Genel Ana Bilgisayarı' nı kullanarak ve ILogger
nesnelerini doğrudan oluşturmak yerine DI kapsayıcısından kullanmanız ILoggerFactory
gerekir.
DI'den ILogger alma
Bu örnek, ASP.NET En Az API kullanarak barındırılan bir uygulamada ILogger nesnesi alır:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
var handler = app.Services.GetRequiredService<ExampleHandler>();
app.MapGet("/", handler.HandleRequest);
app.Run();
partial class ExampleHandler(ILogger<ExampleHandler> logger)
{
public string HandleRequest()
{
LogHandleRequest(logger);
return "Hello World";
}
[LoggerMessage(LogLevel.Information, "ExampleHandler.HandleRequest was called")]
public static partial void LogHandleRequest(ILogger logger);
}
Yukarıdaki örnek:
- adlı
ExampleHandler
tekil bir hizmet oluşturdunuz ve işlevi çalıştırmak için gelen web isteklerine eşlendiExampleHandler.HandleRequest
. - 8. satır, C# 12'de eklenen bir özellik olan ExampleHandler için birincil bir oluşturucu tanımlar. Eski stil C# oluşturucusu aynı şekilde iyi çalışır, ancak biraz daha ayrıntılı olur.
- Oluşturucu, türünde
ILogger<ExampleHandler>
bir parametre tanımlar. ILogger<TCategoryName> ve öğesinden ILogger türetilir ve nesnenin hangi kategoriye sahip olduğunuILogger
gösterir. DI kapsayıcısı doğru kategoriye sahip birILogger
bulur ve oluşturucu bağımsız değişkeni olarak sağlar. Henüz bu kategoriye sahip hayırILogger
varsa, DI kapsayıcısı bunu hizmet sağlayıcısından otomatik olarak oluştururILoggerFactory
. logger
Oluşturucuda alınan parametre, işlevdeHandleRequest
günlüğe kaydetmek için kullanıldı.
Konak tarafından sağlanan ILoggerFactory
Konak oluşturucuları varsayılan yapılandırmayı başlatır, ardından konak oluşturulduğunda konağın DI kapsayıcısına yapılandırılmış ILoggerFactory
bir nesne ekler. Konak oluşturulmadan önce, , veya diğer konaklardaki benzer API'ler aracılığıyla HostApplicationBuilder.LoggingWebApplicationBuilder.Logginggünlük yapılandırmasını ayarlayabilirsiniz. Konaklar ayrıca varsayılan yapılandırma kaynaklarından günlük yapılandırmasını appsettings.json ve ortam değişkenleri olarak uygular. Daha fazla bilgi için bkz . .NET'te yapılandırma.
Bu örnek, tarafından WebApplicationBuilder
sağlanan öğesini özelleştirmek için öncekini ILoggerFactory
genişletir. Günlükleri OTLP (OpenTelemetry protokolü) üzerinden aktaran bir günlük sağlayıcısı olarak OpenTelemetry ekler:
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddOpenTelemetry(logging => logging.AddOtlpExporter());
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
DI ile ILoggerFactory oluşturma
Konağı olmayan bir DI kapsayıcısı kullanıyorsanız kapsayıcıyı yapılandırmak ve kapsayıcıya eklemek ILoggerFactory
için kullanınAddLogging.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
// Add services to the container including logging
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole());
services.AddSingleton<ExampleService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
// Get the ExampleService object from the container
ExampleService service = serviceProvider.GetRequiredService<ExampleService>();
// Do some pretend work
service.DoSomeWork(10, 20);
class ExampleService(ILogger<ExampleService> logger)
{
public void DoSomeWork(int x, int y)
{
logger.LogInformation("DoSomeWork was called. x={X}, y={Y}", x, y);
}
}
Yukarıdaki örnek:
- Konsola yazacak şekilde yapılandırılmış bir içeren bir
ILoggerFactory
DI hizmet kapsayıcısı oluşturuldu - Kapsayıcıya tekil
ExampleService
eklendi - AYNı zamanda oluşturucu bağımsız değişkeni olarak kullanılacak bir öğesini de otomatik olarak oluşturan DI kapsayıcısından öğesinin bir örneği
ExampleService
oluşturulduILogger<ExampleService>
. - konsolda
ILogger<ExampleService>
bir iletiyi günlüğe kaydetmek için öğesini kullanan çağrılırExampleService.DoSomeWork
.
Günlük kaydetmeyi yapılandırma
Günlük yapılandırması kodda veya yapılandırma dosyaları ve ortam değişkenleri gibi dış kaynaklar aracılığıyla ayarlanır. Uygulamayı yeniden oluşturmadan değiştirilebildiği için mümkün olduğunda dış yapılandırma kullanmak yararlı olur. Ancak, günlük sağlayıcılarını ayarlama gibi bazı görevler yalnızca koddan yapılandırılabilir.
Kod olmadan günlüğe kaydetmeyi yapılandırma
Konak kullanan uygulamalar için günlük yapılandırması genellikle uygulama ayarları.{Environment}
.json dosyaları bölümünde sağlanır"Logging"
. Konak kullanmayan uygulamalar için dış yapılandırma kaynakları açıkça ayarlanır veya bunun yerine kodda yapılandırılır.
Aşağıdaki uygulama ayarları. Development.json dosyası .NET Çalışanı hizmet şablonları tarafından oluşturulur:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Yukarıdaki JSON kodunda:
"Default"
,"Microsoft"
ve"Microsoft.Hosting.Lifetime"
günlük düzeyi kategorileri belirtilir.- Değer
"Default"
, aksi takdirde belirtilmeyen tüm kategorilere uygulanır ve tüm kategoriler"Information"
için tüm varsayılan değerleri etkili bir şekilde oluşturur. Bir kategori için bir değer belirterek bu davranışı geçersiz kılabilirsiniz. "Microsoft"
kategorisi"Microsoft"
ile başlayan tüm kategorilere uygulanır.- Kategori,
"Microsoft"
ve daha yüksek bir günlük düzeyindeWarning
günlüğe kaydeder. - Kategori
"Microsoft.Hosting.Lifetime"
, kategoriye"Microsoft"
göre daha belirgindir, bu nedenle"Microsoft.Hosting.Lifetime"
kategori günlük düzeyinde ve daha yüksek bir düzeyde"Information"
günlüğe kaydedilir. - Belirli bir günlük sağlayıcısı belirtilmez, dolayısıyla
LogLevel
Windows EventLog dışında tüm etkinleştirilmiş günlük sağlayıcılarına uygulanır.
Logging
özelliğinin LogLevel ve günlük sağlayıcısı özellikleri olabilir. LogLevel
, seçili kategorileri günlüğe kaydetmek için en düşük düzeyi belirtir. Önceki JSON'da Information
ve Warning
günlük düzeyleri belirtilir. LogLevel
günlüğün önem derecesini gösterir ve 0 ile 6 arasında değişir:
Trace
= 0, Debug
= 1, Information
= 2, Warning
= 3, Error
= 4, Critical
= 5 ve None
= 6.
LogLevel
belirtildiğinde, belirtilen ve daha yüksek düzeydeki iletiler için günlük etkinleştirilir. Önceki JSON'da, Default
kategori ve üzeri için Information
günlüğe kaydedilir. Örneğin Information
, Warning
, Error
ve Critical
iletileri günlüğe kaydedilir. LogLevel
belirtilmezse günlüğe kaydetme için varsayılan Information
düzeyi kullanılır. Daha fazla bilgi için bkz. Günlük düzeyleri.
Sağlayıcı özelliği bir LogLevel
özelliği belirtebilir. Sağlayıcının altındaki LogLevel
, söz konusu sağlayıcı için günlüğe alınacak düzeyleri belirtir ve sağlayıcı dışı günlük ayarlarını geçersiz kılar. Aşağıdaki appsettings.json dosyasını göz önünde bulundurun:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting": "Trace"
}
},
"EventSource": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
Logging.{ProviderName}.LogLevel
sınıfındaki ayarlar Logging.LogLevel
ayarlarını geçersiz kılar. Yukarıdaki JSON'da sağlayıcının Debug
varsayılan günlük düzeyi olarak Information
ayarlanır:
Logging:Debug:LogLevel:Default:Information
Yukarıdaki ayar Microsoft.Hosting
dışındaki tüm Logging:Debug:
kategorileri için Information
günlük düzeyini belirtir. Belirli bir kategori listelendiğinde, listelenen kategori varsayılan kategoriyi geçersiz kılar. Yukarıdaki JSON'da,Logging:Debug:LogLevel
"Microsoft.Hosting"
"Default"
Logging:LogLevel
Aşağıdakiler için en düşük günlük düzeyi belirtilebilir:
- Belirli sağlayıcılar: Örneğin
Logging:EventSource:LogLevel:Default:Information
- Belirli kategoriler: Örneğin
Logging:LogLevel:Microsoft:Warning
- Tüm sağlayıcılar ve tüm kategoriler:
Logging:LogLevel:Default:Warning
En düşük düzeyin altındaki günlükler:
- Sağlayıcıya geçirilmez.
- Günlüğe kaydedilmez veya görüntülenmez.
Tüm günlükleri engellemek için LogLevel.None değerini belirtin. LogLevel.None
değeri 6'dır ve bu değer LogLevel.Critical
(5) değerinden yüksektir.
Sağlayıcı günlük kapsamlarını destekliyorsa IncludeScopes
bunların etkinleştirilip etkinleştirilmediğini gösterir. Daha fazla bilgi için bkz. Günlük kapsamları
Aşağıdaki appsettings.json dosyası tüm yerleşik sağlayıcıların ayarlarını içerir:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.Extensions.Hosting": "Warning",
"Default": "Information"
}
},
"EventSource": {
"LogLevel": {
"Microsoft": "Information"
}
},
"EventLog": {
"LogLevel": {
"Microsoft": "Information"
}
},
"AzureAppServicesFile": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Warning"
}
},
"AzureAppServicesBlob": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Information"
}
},
"ApplicationInsights": {
"LogLevel": {
"Default": "Information"
}
}
}
}
Yukarıdaki örnekte:
- Kategoriler ve düzeyler önerilen değerler değildir. Örnek, tüm varsayılan sağlayıcıları göstermek amacıyla sağlanmıştır.
Logging.{ProviderName}.LogLevel
sınıfındaki ayarlarLogging.LogLevel
ayarlarını geçersiz kılar. ÖrneğinDebug.LogLevel.Default
düzeyiLogLevel.Default
düzeyini geçersiz kılar.- Her sağlayıcının diğer adı kullanılır. Her sağlayıcı, yapılandırmada tam tür adı yerine kullanılacak bir diğer ad tanımlar. Yerleşik sağlayıcıların diğer adları şunlardır:
Console
Debug
EventSource
EventLog
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
Komut satırı, ortam değişkenleri ve başka bir yapılandırmayla günlük düzeyini ayarlama
Günlük düzeyi yapılandırma sağlayıcılarının herhangi biri tarafından ayarlanabilir. Örneğin, değerine Information
sahip adlı Logging:LogLevel:Microsoft
kalıcı bir ortam değişkeni oluşturabilirsiniz.
Günlük düzeyi değeri göz önüne alındığında kalıcı ortam değişkeni oluşturun ve atayın.
:: Assigns the env var to the value
setx "Logging__LogLevel__Microsoft" "Information" /M
Komut İstemi'nin yeni bir örneğinde ortam değişkenini okuyun.
:: Prints the env var value
echo %Logging__LogLevel__Microsoft%
Önceki ortam ayarı ortamda kalıcıdır. .NET Çalışanı hizmet şablonlarıyla oluşturulan bir uygulamayı kullanırken ayarları test etmek için, ortam değişkeni atandıktan sonra proje dizinindeki komutunu kullanın dotnet run
.
dotnet run
İpucu
Ortam değişkenini ayarladıktan sonra, yeni eklenen ortam değişkenlerinin kullanılabilir olduğundan emin olmak için tümleşik geliştirme ortamınızı (IDE) yeniden başlatın.
Azure App Service üzerinde Ayarlar >Yapılandırması sayfasında Yeni uygulama ayarını seçin. Azure App Service uygulama ayarları şunlardır:
- Bekleme sırasında şifrelenir ve şifrelenmiş bir kanal üzerinden iletilir.
- Ortam değişkenleri olarak kullanıma sunulur.
Ortam değişkenlerini kullanarak .NET yapılandırma değerlerini ayarlama hakkında daha fazla bilgi için bkz . ortam değişkenleri.
Kodla günlüğe kaydetmeyi yapılandırma
Kodda günlüğe kaydetmeyi yapılandırmak için API'yi ILoggingBuilder kullanın. Buna farklı yerlerden erişilebilir:
- öğesini doğrudan oluştururken
ILoggerFactory
içinde LoggerFactory.Createyapılandırın. - ANA bilgisayar olmadan DI kullanırken, içinde LoggingServiceCollectionExtensions.AddLoggingyapılandırın.
- Bir konak kullanırken, WebApplicationBuilder.Logging ile veya konağa özgü diğer API'lerle HostApplicationBuilder.Loggingyapılandırın.
Bu örnekte konsol günlüğü sağlayıcısının ve çeşitli filtrelerin ayarlanması gösterilmektedir.
using Microsoft.Extensions.Logging;
using var loggerFactory = LoggerFactory.Create(static builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogDebug("Hello {Target}", "Everyone");
Yukarıdaki örnekte AddFilter , çeşitli kategoriler için etkinleştirilen günlük düzeyini ayarlamak için kullanılır. AddConsole konsol günlüğü sağlayıcısını eklemek için kullanılır. Varsayılan olarak, önem derecesine sahip Debug
günlükler etkinleştirilmez, ancak yapılandırma filtreleri ayarladığından konsolda "Herkese Merhaba" hata ayıklama iletisi görüntülenir.
Filtreleme kuralları nasıl uygulanır?
Bir ILogger<TCategoryName> nesnesi oluşturulduğunda ILoggerFactory nesnesi bu günlükçüye uygulamak üzere sağlayıcı başına tek bir kural seçer. ILogger
örneği tarafından yazılan tüm iletiler seçilen kurallar temelinde filtrelenir. Kullanılabilir kurallar arasından her sağlayıcı ve kategori çifti için en belirgin kural seçilir.
Belirli bir kategori için ILogger
oluşturulduğunda her sağlayıcı için aşağıdaki algoritma kullanılır:
- Sağlayıcıyla veya sağlayıcının diğer adıyla eşleşen tüm kuralları seçin. Eşleşme bulunamazsa sağlayıcısı boş olan tüm kurallar seçilir.
- Önceki adımın sonucundan, eşleşen kategori ön eki en uzun olan kuralları seçin. Eşleşme bulunamazsa bir kategori belirtmeyen tüm kuralları seçin.
- Birden çok kural seçildiyse, sonuncusunu alın.
- Hiçbir kural seçilmezse, en düşük günlük düzeyini belirtmek için kullanın LoggingBuilderExtensions.SetMinimumLevel(ILoggingBuilder, LogLevel) .
Günlük kategorisi
ILogger
nesnesi oluşturulduğunda bir kategori belirtilir. Söz konusu kategori bu ILogger
örneğiyle oluşturulan her günlük iletisine eklenir. Kategori dizesi rastgeledir, ancak kural tam sınıf adını kullanmaktır. Örneğin, aşağıdaki nesne gibi tanımlanmış bir hizmete sahip bir uygulamada, kategori şöyle "Example.DefaultService"
olabilir:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger<DefaultService> _logger;
public DefaultService(ILogger<DefaultService> logger) =>
_logger = logger;
// ...
}
}
Daha fazla kategori isteniyorsa, kural tam sınıf adına bir alt kategori ekleyerek hiyerarşik bir ad kullanmak ve kullanarak LoggerFactory.CreateLoggerkategoriyi açıkça belirtmektir:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger _logger;
public DefaultService(ILoggerFactory loggerFactory) =>
_logger = loggerFactory.CreateLogger("Example.DefaultService.CustomCategory");
// ...
}
}
Olayların kategoriye göre düzenlenebilmesi için, sabit bir adla çağırmak CreateLogger
birden çok sınıfta/türde kullanıldığında yararlı olabilir.
ILogger<T>
, T
tam tür adıyla CreateLogger
yöntemini çağırmanın eşdeğeridir.
Günlük düzeyi
Aşağıdaki tabloda LogLevel değerleri, uygun Log{LogLevel}
uzantısı yöntemi ve önerilen kullanım listelenir:
GünlükDüzeyi | Değer | Metot | Açıklama |
---|---|---|---|
İzleme | 0 | LogTrace | En ayrıntılı iletileri içerir. Bu iletiler hassas uygulama verileri içerebilir. Bu iletiler varsayılan olarak devre dışı bırakılmıştır ve üretimde etkinleştirilmemesi gerekir. |
Hata Ayıklama | 1 | LogDebug | Hata ayıklama ve geliştirme için. Yüksek hacim nedeniyle üretimde dikkatli kullanın. |
Bilgi | 2 | LogInformation | Uygulamanın genel akışını izler. Uzun süreli bir değeri olabilir. |
Uyarı | 3 | LogWarning | Anormal veya beklenmeyen olaylar için. Normalde uygulamanın başarısız olmasına neden olmayan hataları veya koşulları içerir. |
Hata | 4 | LogError | İşlenemeyen hatalar ve özel durumlar için. Bu iletiler uygulama genelindeki bir hatayı değil geçerli işlem veya istekteki hatayı gösterir. |
Kritik | 5 | LogCritical | Hemen ilgilenilmesi gereken hatalar için. Örnekler: veri kaybı senaryoları, yetersiz disk alanı. |
Hiçbiri | 6 | Hiçbir iletinin yazılmaması gerektiğini belirtir. |
Yukarıdaki tabloda LogLevel
en düşük önem derecesinden en yükseğe doğru listelenmiştir.
Log yönteminin ilk parametresi olan LogLevel günlüğün önem derecesini gösterir. Geliştiricilerin çoğu Log(LogLevel, ...)
yöntemini çağırmak yerine Log{LogLevel} uzantı yöntemlerini çağırır. Log{LogLevel}
Uzantı yöntemleri yöntemini çağırır Log
ve belirtinLogLevel
. Örneğin aşağıdaki iki günlük çağrısı işlevsel açıdan eşdeğerdir ve aynı günlüğü oluşturur:
public void LogDetails()
{
var logMessage = "Details for log.";
_logger.Log(LogLevel.Information, AppLogEvents.Details, logMessage);
_logger.LogInformation(AppLogEvents.Details, logMessage);
}
AppLogEvents.Details
olay kimliğidir ve örtük olarak sabit Int32 bir değerle temsil edilir. AppLogEvents
çeşitli adlandırılmış tanımlayıcı sabitlerini kullanıma sunan ve Günlük olay kimliği bölümünde görüntülenen bir sınıftır.
Aşağıdaki kod Information
ve Warning
günlüklerini oluşturur:
public async Task<T> GetAsync<T>(string id)
{
_logger.LogInformation(AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
return result;
}
Yukarıdaki kodda, ilk Log{LogLevel}
parametre olan AppLogEvents.Read
Log olay kimliğidir. İkinci parametre, kalan yöntem parametreleri tarafından sağlanan bağımsız değişken değerleri için yer tutucular içeren bir ileti şablonudur. Yöntem parametreleri, bu makalenin devamında ileti şablonu bölümünde açıklanmıştır.
Belirli bir depolama ortamına ne kadar günlük çıkışı yazıldığından emin olmak için uygun günlük düzeyini yapılandırın ve doğru Log{LogLevel}
yöntemleri çağırın. Örneğin:
- Üretimde:
Trace
veyaDebug
düzeylerinde günlüğe kaydetme, yüksek hacimli ve ayrıntılı günlük iletileri oluşturur. Maliyetleri denetlemek ve veri depolama sınırlarını aşmamak içinTrace
veDebug
düzeyindeki iletileri yüksek hacimli ve düşük maliyetli bir veri deposunda günlüğe kaydedin.Trace
veDebug
düzeylerini belirli kategorilerle sınırlamayı göz önünde bulundurun.Warning
ileCritical
düzeyleri arasını günlüğe kaydetmek az sayıda günlük iletisi oluşturmalıdır.- Maliyetler ve depolama sınırları genellikle sorun değildir.
- Az sayıda günlük veri deposu seçimlerine daha fazla esneklik getirir.
- Geliştirme aşamasında:
Warning
olarak ayarlayın.- Sorun giderme sırasında
Trace
veyaDebug
iletilerini ekleyin. Çıkışı sınırlamak içinTrace
veyaDebug
düzeyini yalnızca araştırma kapsamındaki kategoriler için ayarlayın.
Aşağıdaki JSON kümeleri Logging:Console:LogLevel:Microsoft:Information
:
{
"Logging": {
"LogLevel": {
"Microsoft": "Warning"
},
"Console": {
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
Günlük olayı kimliği
Her günlük bir olay tanımlayıcısı belirtebilir; EventId ve isteğe bağlı Name
salt okunur özelliklere sahip bir Id
yapıdır. Örnek kaynak kodu, olay kimliklerini tanımlamak için sınıfını AppLogEvents
kullanır:
using Microsoft.Extensions.Logging;
internal static class AppLogEvents
{
internal static EventId Create = new(1000, "Created");
internal static EventId Read = new(1001, "Read");
internal static EventId Update = new(1002, "Updated");
internal static EventId Delete = new(1003, "Deleted");
// These are also valid EventId instances, as there's
// an implicit conversion from int to an EventId
internal const int Details = 3000;
internal const int Error = 3001;
internal static EventId ReadNotFound = 4000;
internal static EventId UpdateNotFound = 4001;
// ...
}
İpucu
' int
yi öğesine dönüştürme hakkında daha fazla bilgi için EventId
bkz . EventId.Implicit(Int32 to EventId) İşleci.
Olay kimliği bir dizi olayı ilişkilendirir. Örneğin, bir depodan değerleri okumayla ilgili tüm günlükler olabilir 1001
.
Günlük sağlayıcısı olay kimliğini bir kimlik alanında, günlük iletisinde günlüğe kaydedebilir veya hiç günlüğe kaydetmeyebilir. Hata ayıklama sağlayıcıları olay kimliklerini göstermez. Konsol sağlayıcısı olay kimliklerini kategorinin arkasında köşeli ayraç içinde gösterir:
info: Example.DefaultService.GetAsync[1001]
Reading value for a1b2c3
warn: Example.DefaultService.GetAsync[4000]
GetAsync(a1b2c3) not found
Bazı günlük sağlayıcıları olay kimliğini bir alanda depolar ve bu sayede kimliğe göre filtre uygulanabilir.
Günlük iletisi şablonu
Her günlük API'si bir ileti şablonu kullanır. İleti şablonu bağımsız değişkenlerin sağlandığı yer tutucular içerebilir. Yer tutucular için sayı değil ad kullanın. Yer tutucuların adları değil sırası, değerlerini sağlamak için hangi parametrelerin kullanılacağını belirler. Aşağıdaki kodda, ileti şablonunda parametre adları sıra dışıdır:
string p1 = "param1";
string p2 = "param2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
Yukarıdaki kod, parametre değerlerini sırayla içeren bir günlük iletisi oluşturur:
Parameter values: param1, param2
Not
Tek bir ileti şablonunda birden çok yer tutucu kullanırken, sıra tabanlı oldukları için dikkatli olun. Adlar, bağımsız değişkenleri yer tutucularla hizalamak için kullanılmaz .
Bu yaklaşım günlük sağlayıcılarının anlamsal veya yapılandırılmış günlük uygulamalarına olanak tanır. Bağımsız değişkenlerin kendileri yalnızca biçimlendirilmiş ileti şablonuna değil günlük sistemine geçirilir. Bu sayede günlük sağlayıcıları parametre değerlerini alanlar olarak depolayabilir. Aşağıdaki günlükçü yöntemini göz önünde bulundurun:
_logger.LogInformation("Getting item {Id} at {RunTime}", id, DateTime.Now);
Örneğin Azure Tablo Depolama'da oturum açarken:
- Her Azure Tablo varlığının
ID
veRunTime
özellikleri olabilir. - Özellikleri olan tablolar, günlüğe kaydedilmiş veriler üzerinde çalıştırılan sorguları basitleştirir. Örneğin bir sorgu, metin iletisinden zamanı ayıklamak zorunda kalmadan belirli bir
RunTime
aralığındaki tüm günlükleri bulabilir.
Günlük iletisi şablonu biçimlendirmesi
Günlük iletisi şablonları yer tutucu biçimlendirmeyi destekler. Şablonlar, verilen tür bağımsız değişkeni için geçerli bir biçim belirtmekte serbesttir. Örneğin, aşağıdaki Information
günlükçü ileti şablonunu göz önünde bulundurun:
_logger.LogInformation("Logged on {PlaceHolderName:MMMM dd, yyyy}", DateTimeOffset.UtcNow);
// Logged on January 06, 2022
Yukarıdaki örnekte örnek, DateTimeOffset
günlükçü ileti şablonundaki öğesine PlaceHolderName
karşılık gelen türdür. Değerler sıra tabanlı olduğundan bu ad herhangi bir şey olabilir. Biçim MMMM dd, yyyy
türü için DateTimeOffset
geçerlidir.
Ve biçimlendirme hakkında DateTime
daha fazla bilgi için bkz. Özel tarih ve saat biçimi dizeleri.DateTimeOffset
Örnekler
Aşağıdaki örneklerde, yer tutucu söz dizimini kullanarak ileti şablonunu biçimlendirme gösterilmektedir {}
. Ayrıca, yer tutucu söz diziminin {}
çıkışıyla birlikte bir kaçış örneği gösterilir. Son olarak, şablon oluşturma yer tutucularıyla dize ilişkilendirmesi de gösterilir:
logger.LogInformation("Number: {Number}", 1); // Number: 1
logger.LogInformation("{{Number}}: {Number}", 3); // {Number}: 3
logger.LogInformation($"{{{{Number}}}}: {{Number}}", 5); // {Number}: 5
İpucu
- Çoğu durumda, günlüğe kaydederken günlük iletisi şablonu biçimlendirmesini kullanmanız gerekir. Dize ilişkilendirmesinin kullanılması performans sorunlarına neden olabilir.
- Kod çözümleme kuralı CA2254: Şablon statik bir ifade olmalıdır, günlük iletilerinizin düzgün biçimlendirme kullanmadığı yerler konusunda sizi uyarmaya yardımcı olur.
Günlük özel durumları
Günlükçü yöntemlerinde özel durum parametresi alan aşırı yüklemeler vardır:
public void Test(string id)
{
try
{
if (id is "none")
{
throw new Exception("Default Id detected.");
}
}
catch (Exception ex)
{
_logger.LogWarning(
AppLogEvents.Error, ex,
"Failed to process iteration: {Id}", id);
}
}
Özel durum günlüğü sağlayıcıya özgüdür.
Varsayılan günlük düzeyi
Varsayılan günlük düzeyi ayarlanmazsa, varsayılan günlük değeri Information
olur.
Örneğin, aşağıdaki çalışan hizmeti uygulamasını göz önünde bulundurun:
- .NET Çalışanı şablonlarıyla oluşturulur.
- appsettings.json ve uygulama ayarları. Development.json silindi veya yeniden adlandırıldı.
Yukarıdaki kurulumda gizlilik veya giriş sayfasına gitmek, kategori adında Microsoft
içeren birçok Trace
, Debug
ve Information
iletisi oluşturur.
Varsayılan günlük düzeyi yapılandırmada ayarlanmadığında, aşağıdaki kod varsayılan günlük düzeyini ayarlar:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.SetMinimumLevel(LogLevel.Warning);
using IHost host = builder.Build();
await host.RunAsync();
Filter işlevi
Yapılandırma veya kod tarafından kendilerine atanmış kuralları olmayan tüm sağlayıcılar ve kategoriler için filtre işlevi çağrılır:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddFilter((provider, category, logLevel) =>
{
return provider.Contains("ConsoleLoggerProvider")
&& (category.Contains("Example") || category.Contains("Microsoft"))
&& logLevel >= LogLevel.Information;
});
using IHost host = builder.Build();
await host.RunAsync();
Yukarıdaki kod, kategori Example
veya Microsoft
içerdiğinde ve günlük düzeyi Information
veya daha yüksek olduğunda konsol günlüklerini görüntüler.
Günlük kapsamları
Kapsam, bir dizi mantıksal işlemi gruplandırr. Bu gruplandırma bir kümenin parçası olarak oluşturulan her günlüğe aynı verileri eklemek için kullanılabilir. Örneğin bir işlemi gerçekleştirmenin parçası olarak oluşturulan her günlük işlem kimliğini içerebilir.
Kapsam:
- BeginScope yöntemi tarafından döndürülen bir IDisposable türüdür.
- Atılana kadar devam eder.
Aşağıdaki sağlayıcılar kapsamları destekler:
Bir kapsamı, günlükçü çağrılarını using
bloğunda sarmalayarak kullanın:
public async Task<T> GetAsync<T>(string id)
{
T result;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(
AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(
AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
}
return result;
}
Aşağıdaki JSON, konsol sağlayıcısı için kapsamları etkinleştirir:
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Warning",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
Aşağıdaki kod, konsol sağlayıcısı için kapsamları etkinleştirir:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole(options => options.IncludeScopes = true);
using IHost host = builder.Build();
await host.RunAsync();
Main'de günlük oluşturma
Aşağıdaki kod, konağı oluşturduktan sonra DI'den bir ILogger
örneği alarak Main
'de günlükleri yazar:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHost host = Host.CreateApplicationBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Host created.");
await host.RunAsync();
Yukarıdaki kod iki NuGet paketine dayanır:
Proje dosyası aşağıdakine benzer olacaktır:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
</ItemGroup>
</Project>
Zaman uyumsuz günlükçü yöntemleri yok
Günlüğe kaydetme işleminin çok hızlı gerçekleşmesi gerektiğinden zaman uyumsuz kodun performans maliyetine değmez. Günlük veri deposu yavaşsa, doğrudan veri deposuna yazmayın. Günlük iletilerini ilk olarak hızlı bir depoya yazmayı, daha sonra da yavaş depoya taşımayı göz önünde bulundurun. Örneğin SQL Server'da günlüğe kaydederken, bu işlemi doğrudan Log
yöntemiyle yapmayın çünkü Log
yöntemleri zaman uyumsuzdur. Bunun yerine günlük iletilerini zaman uyumlu olarak bir bellek içi kuyruğuna ekleyin ve bir arka plan çalışanının zaman uyumsuz çalışmayı yapıp verileri SQL Server'a göndermek için iletileri kuyruktan çekmesini sağlayın.
Çalışan uygulamada günlük düzeylerini değiştirme
Günlük API'si uygulama çalışırken günlük düzeylerini değiştirmeye yönelik bir senaryo içermez. Bununla birlikte bazı yapılandırma sağlayıcıları yapılandırmayı yeniden yükleyebilir ve bu işlem günlük yapılandırmasını hemen etkiler. Örneğin, Dosya Yapılandırma Sağlayıcısı günlük yapılandırmasını varsayılan olarak yeniden yükler. Uygulama çalışırken kodda yapılandırma değiştirilirse, uygulama IConfigurationRoot.Reload'ı çağırarak uygulamanın günlük yapılandırmasını güncelleştirebilir.
NuGet paketleri
ILogger<TCategoryName> ve ILoggerFactory arabirimleri ve uygulamaları örtük paket başvurusu olarak çoğu .NET SDK'sında yer alır. Bunlar, örtük olarak başvurulmuyorsa aşağıdaki NuGet paketlerinde de açıkça kullanılabilir:
- Arabirimler Microsoft.Extensions.Logging.Abstractions içindedir.
- Varsayılan uygulamalar Microsoft.Extensions.Logging içindedir.
Hangi .NET SDK'sı örtük paket başvuruları içerdiği hakkında daha fazla bilgi için bkz . .NET SDK: örtük ad alanına tablo.