Aracılığıyla paylaş


C# ve .NET'te loglama

.NET, uygulama davranışını izleme ve sorunları tanılamaya yardımcı olmak için ILogger API'si aracılığıyla yüksek performanslı, yapılandırılmış günlüğe kaydetmeyi destekler. Farklı hedeflere günlük yazmak için farklı günlük sağlayıcıları yapılandırın. Temel günlük sağlayıcıları yerleşiktir ve birçok üçüncü taraf sağlayıcı kullanılabilir.

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, günlük iletilerinin konsola yazılması için konsol günlüğü sağlayıcısını yapılandırın.
  • "Program" adlı kategoriye sahip bir ILogger oluşturur. Kategori, nesne tarafından string günlüğe kaydedilen her iletiyle ilişkili bir ILogger kategoridir. Günlükleri ararken veya filtrelerken aynı sınıftan (veya kategoriden) gelen günlük iletilerini gruplandırıyor.
  • LogInformation'yı Information seviyesinde bir mesaj kaydetmek için çağırır. Günlük düzeyi, günlüğe kaydedilen olayın önem derecesini gösterir ve daha az önemli günlük iletilerini filtreler. Günlük girdisi ayrıca bir ileti şablonu"Hello World! Logging is {Description}." ve anahtar-değer çifti Description = funiçerir. Anahtar adı (veya yer tutucu), şablondaki küme ayraçlarının içindeki sözcükten gelir ve değer de geri kalan yöntem bağımsız değişkeninden elde edilir.

Bu örnek için bu proje dosyası iki NuGet paketi içerir:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.1" />
  </ItemGroup>

</Project>

İpucu

Günlük tutma örnek kaynak kodunun tamamı, indirilmek üzere Samples Browser'da bulunur. Daha fazla bilgi için Kod örneklerine göz atma: .NET'te günlük kaydı bölümüne bakın.

Karmaşık bir uygulamada kayıt tutma

Daha az basit bir senaryoda oturum açarken, önceki örnekte bu değişiklikleri yapmayı düşünün.

  • Uygulamanız Bağımlılık Ekleme (DI) veya ASP.NET'in WebApplication veya Genel Konak gibi bir konak kullanıyorsa, ILoggerFactory ve ILogger nesnelerini doğrudan oluşturmak yerine ilgili DI kapsayıcılarından kullanın. Daha fazla bilgi için DI ve Ana Bilgisayarlarla Tümleştirme bölümüne bakın.

  • Derleme zamanı kaynak oluşturmanın günlüğe kaydedilmesi genellikle gibi genişletme yöntemlerine daha iyi bir alternatiftir. Günlük kaydı kaynağı oluşturma, daha iyi performans, daha güçlü türleme sunar ve string sabitlerin yöntemlerinize yayılmasını ö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 en iyi uygulama, günlük iletisini oluşturan sınıfın tam nitelikli 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");
    }
}
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");

Ev sahipleriyle tümleştirme ve bağımlılık enjeksiyonu

Uygulamanız Bağımlılık Ekleme (DI) veya ASP.NET'in WebApplication veya Genel Ana Bilgisayar gibi bir konak kullanıyorsa, nesneleri doğrudan oluşturmak yerine DI kapsayıcısından ILoggerFactory ve ILogger nesnelerini kullanın.

DI'dan ILogger al

Barındırılan bir uygulamada ASP.NET Minimal API kullanarak ILogger nesnesi alan bu örnek:

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 tekton hizmet oluşturuldu ve gelen web istekleri ExampleHandler.HandleRequest işlevini çalıştıracak şekilde eşlendi.
  • 12. Satır, C# 12'de eklenen bir özellik olan ExampleHandler için birincil oluşturucu tanımlar. Eski stil C# oluşturucusu aynı şekilde iyi çalışır, ancak biraz daha ayrıntılıdır.
  • Oluşturucu, türünde ILogger<ExampleHandler>bir parametre tanımlar. ILogger<TCategoryName>, ILogger öğesinden türetilir ve ILogger nesnesinin hangi kategoriye sahip olduğunu gösterir. DI kapsayıcısı doğru kategoriye sahip bir ILogger bulur ve bunu oluşturucu bağımsız değişkeni olarak sağlar. Henüz bu kategoriye sahip ILogger yoksa, DI kapsayıcısı bunu hizmet sağlayıcısındaki ILoggerFactory'den otomatik olarak oluşturur.
  • logger Oluşturucuya alınan parametre, HandleRequest fonksiyonunda günlüğe kaydetmek için kullanılır.

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, günlük yapılandırmasını HostApplicationBuilder.Logging veya WebApplicationBuilder.Logging gibi diğer konaklardaki benzer API'ler aracılığıyla ayarlayın. Sunucular ayrıca appsettings.json ve ortam değişkenleri gibi varsayılan yapılandırma kaynaklarından günlük kaydı yapılandırmasını uygular. Daha fazla bilgi için bkz . .NET'te yapılandırma.

Bu örnek, ILoggerFactory tarafından sağlanan WebApplicationBuilder öğesini özelleştirmek için öncekini genişletir. OpenTelemetry'yi, günlükleri OTLP (OpenTelemetry protokolü) üzerinden ileten bir günlük sağlayıcısı olarak 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 için AddLogging ve kapsayıcıya eklemek için ILoggerFactory kullanın.

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ış ILoggerFactory içeren bir DI hizmet kapsayıcısı oluşturuldu.
  • Kapsayıcıya bir singleton ExampleService eklendi
  • DI kapsayıcısından ExampleService'ın bir örneğini oluşturdunuz. Bu, oluşturucu bağımsız değişkeni olarak kullanılacak bir ILogger<ExampleService> öğesini de otomatik olarak oluşturdu.
  • çağrılır ExampleService.DoSomeWorkve konsolda bir iletiyi günlüğe kaydetmek için kullanılır ILogger<ExampleService> .

Günlük tutmayı yapılandırmak

Loglama yapılandırmasını, kod üzerinde veya yapılandırma dosyaları ve ortam değişkenleri gibi dış kaynaklar aracılığıyla ayarlayın. Uygulamayı yeniden derlemeden değiştirebildiğiniz için mümkün olduğunda dış yapılandırmanın kullanılması yararlı olur. Ancak, günlük sağlayıcılarını ayarlamak gibi bazı görevler yalnızca kod ile yapılandırılabilir.

Kod yazmadan günlük kaydını yapılandırma

Konak kullanan uygulamalar için "Logging".{Environment}.json dosyalarının bölümü genellikle günlük yapılandırması sağlar. Konak kullanmayan uygulamalar için, dış yapılandırma kaynaklarını açıkça ayarlayın veya bunları kodda yapılandırın .

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" log düzeyi kategorileri belirtilir.
  • Değer, "Default" aksi belirtilmediği halde tüm kategoriler için geçerli olur ve tüm kategoriler "Information"için tüm varsayılan değerleri etkili bir şekilde oluşturur. Kategori için bir değer belirterek bu davranışı geçersiz kılın.
  • "Microsoft" kategorisi "Microsoft" ile başlayan tüm kategorilere uygulanır.
  • "Microsoft" kategorisi, Warning ve daha yüksek bir seviyede günlüğe kaydeder.
  • "Microsoft.Hosting.Lifetime" kategorisi, "Microsoft" kategorisinden daha belirgindir, bu nedenle "Microsoft.Hosting.Lifetime" kategorisi günlüğe "Information" ve üzeri bir günlüğe kaydedilir.
  • Belirli bir günlük sağlayıcısı belirtilmediğinden, LogLevelWindows EventLog dışındaki tüm etkin günlük sağlayıcıları için geçerlidir.

Logging özelliği, LogLevel ve günlük sağlayıcı özelliklerine sahip olabilir. LogLevel, belirli kategoriler için kaydedilecek en düşük düzeyi belirtir. Önceki JSON'da Information ve Warning günlük düzeyleri belirtilmiştir. LogLevel logun önem derecesini gösterir ve 0 ile 6 arasında seviyeler içerir:

Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5 ve None = 6.

LogLevel belirtildiğinde, belirtilen düzeyde ve daha yüksek düzeydeki iletiler için kayıtlar etkinleştirilir. Önceki JSON'da, Default kategorisi, Information ve daha yüksek değerler için günlüğe kaydedilir. Örneğin Information, Warning, Error ve Critical iletileri günlüğe kaydedilir. LogLevel belirtilmediği takdirde, günlük kaydı varsayılan olarak Information düzeyine ayarlanır. Daha fazla bilgi için aşağıdaki Günlük Düzeyleri kısmına bakınız.

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 varsayılan günlük düzeyi Debug olarak ayarlanmıştır:

Logging:Debug:LogLevel:Default:Information

Önceki ayar, Information hariç, her Logging:Debug: kategorisi için Microsoft.Hosting günlük düzeyini belirtir. Belirli bir kategori listelendiğinde, listelenen kategori varsayılan kategoriyi geçersiz kılar. Önceki JSON'da, Logging:Debug:LogLevel içindeki ayarları "Microsoft.Hosting"kategoriler "Default" ve Logging:LogLevel geçersiz kılar.

Şunlardan herhangi biri için en düşük log düzeyini belirtin:

  • 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 kaydedilmez:

  • Sağlayıcıya iletildi.
  • Günlüğe kaydedilir veya görüntülenir.

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 günlük kapsamlarınıgörün.

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. Örnekte tüm varsayılan sağlayıcılar gösterilir.
  • Logging.{ProviderName}.LogLevel sınıfındaki ayarlar Logging.LogLevel ayarlarını geçersiz kılar. Örneğin Debug.LogLevel.Default düzeyi LogLevel.Default düzeyini geçersiz kılar.
  • Her sağlayıcının diğer adı kullanılır. Her sağlayıcı, tam tür adının yerine yapılandırmada kullanabileceğiniz bir takma 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 diğer yapılandırmalarla günlük düzeyini ayarlayın.

Günlük seviyesini, yapılandırma sağlayıcılarından herhangi birini kullanarak ayarlayın. Örneğin, Information değerine sahip Logging:LogLevel:Microsoft adlı kalıcı bir ortam değişkeni oluşturun.

Günlük düzeyi değeri göz önüne alındığında kalıcı hale getirilmiş 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ı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, sayfasında > 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 açığa çıkarılır.

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ük kayıt yapılandırma

Kod içinde loglamayı yapılandırmak için API'yi ILoggingBuilder kullanın. Farklı yerlerden erişebilirsiniz:

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 ayarlar. AddConsole konsol günlüğü sağlayıcısını ekler. Varsayılan olarak, Debug önem derecesindeki günlükler etkinleştirilmez, ancak yapılandırma filtreleri ayarlandığında konsolda "Herkese Merhaba" hata ayıklama mesajı 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. Örnek, ILogger yazdığı tüm iletileri seçilen kurallara göre filtreler. 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, LoggingBuilderExtensions.SetMinimumLevel(ILoggingBuilder, LogLevel) ögesini en düşük günlük düzeyini belirtmek için kullanın.

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 LoggerFactory.CreateLogger kullanarak kategoriyi 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 birden çok sınıfta/türde kullanıldığında sabit bir adla çağırmak CreateLogger yararlı olur.

ILogger<T>, CreateLogger tam nitelikli tür adıyla T yöntemini çağırmanın eşdeğeridir.

Kayıt seviyesi

Aşağıdaki tabloda LogLevel değerleri, uygun Log{LogLevel} uzantısı yöntemi ve önerilen kullanım listelenir:

Log Seviyesi 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 vadeli bir değere sahip 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 Ele alınamayan hatalar ve istisnalar için. Bu iletiler uygulama genelindeki bir hatayı değil geçerli işlem veya istekteki hatayı gösterir.
Kritik 5 LogCritical Hemen dikkat edilmesi 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 LogLevel, günlüğün önem derecesini belirtir. Geliştiricilerin çoğu Log(LogLevel, ...) yöntemini çağırmak yerine Log{LogLevel} uzantı yöntemlerini çağırır. Log{LogLevel} uzantı yöntemleri Log yöntemini çağırır ve LogLevel'yi belirtir. Örneğin, aşağıdaki iki log çağrısı işlevsel olarak eşdeğerdir ve aynı logu 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, 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.

Uygun günlük düzeyini yapılandırın ve belirli bir depolama ortamına ne kadar log çıktısı yazılacağını kontrol etmek için doğru Log{LogLevel} yöntemleri çağırın. Örneğin:

  • Üretimde:
    • Trace veya Debug düzeylerinde loglama, ayrıntılı ve yüksek hacimli günlük iletileri oluşturur. Veri depolama sınırlarını aşmamak ve maliyetleri kontrol altında tutmak için Trace ve Debug düzeyindeki iletileri, yüksek hacimli ve düşük maliyetli bir veri deposuna kaydedin. Trace ve Debug düzeylerini belirli kategorilerle sınırlamayı göz önünde bulundurun.
    • Warning ile Critical düzeyleri aralarında kayıt tutmak az sayıda kayıt iletisi üretmelidir.
      • Maliyetler ve depolama sınırları genellikle sorun değildir.
      • Daha az sayıda günlük, veri deposu seçimlerinde daha fazla esneklik sağlar.
  • Geliştirme aşamasında:
    • Warning olarak ayarlayın.
    • Sorun giderme sırasında Trace veya Debug iletilerini ekleyin. Çıkışı sınırlamak için Trace veya Debug 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"
            }
        }
    }
}

Kayıt olay kimliği

Her bir günlük kayıt bir olay tanımlayıcısı belirtebilir; bir EventId yapıdır ve isteğe bağlı Id salt okunur özelliklere sahiptir. Ö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 öğesinin EventId öğesine dönüştürülmesi hakkında daha fazla bilgi için 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 loglar 1001 olabilir.

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ısı olay kimliklerini göstermez. Konsol sağlayıcısı olay kimliklerini kategori adından sonra köşeli parantez 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, bu da kimliğe göre filtrelemeye imkan verir.

Günlük iletisi şablonu

Her bir günlük API, bir mesaj ş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, argümanları 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 kaydı uygulamasına olanak tanır. Bağımsız değişkenler, yalnızca biçimlendirilmiş ileti şablonuna değil, doğrudan günlük sistemine iletilir. Bu sayede kayıt sağlayıcıları parametre değerlerini alanlar olarak depolayabilir. Aşağıdaki loglama 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 ve RunTime ö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

Kayıt mesajı şablonları yer tutucu biçimlendirmeyi destekler. Şablonlar, verilen tür bağımsız değişkeni için herhangi bir geçerli biçimi belirtebilir. Ö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

Önceki örnekte, DateTimeOffset örneği, günlükçü mesaj şablonundaki PlaceHolderName öğesine karşılık gelen türdür. Değerler sıra tabanlı olduğundan bu ad herhangi bir şey olabilir. Format MMMM dd, yyyy, tür DateTimeOffset için geçerlidir.

Daha fazla bilgi için DateTime ve DateTimeOffset biçimlendirmeye bakın, Özel tarih ve saat formatı dizeleri.

Örnekler

Aşağıdaki örnekler, {} yer tutucu söz dizimini kullanarak bir ileti şablonunun nasıl biçimlendirileceğini göstermektedir. 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, giriş kaydı yaparken log mesaj ş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.

Kayıt özel durumları

Logger yöntemlerinde istisna 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 kayıt düzeyi

Varsayılan günlük düzeyi ayarlı değilse, varsayılan günlük düzeyi değeri olur Information.

Örneğin, aşağıdaki çalışan hizmeti uygulamasını göz önünde bulundurun:

  • .NET Worker şablonları ile oluşturulmuş.
  • appsettings.json ve appsettings.Development.json silindi veya yeniden adlandırıldı.

Yukarıdaki kurulumda gizlilik veya giriş sayfasına gitmek, kategori adında Trace içeren birçok Debug, Information ve Microsoft iletisi oluşturur.

Aşağıdaki kod, varsayılan günlük düzeyinin yapılandırmada ayarlanmamış olması durumunda 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.

Kayıt kapsamları

Kapsam, bir dizi Mantıksal işlemi gruplandırır. Bu gruplandırma, bir kümenin parçası olarak oluşturulan her günlüğe aynı verileri ekleyebilir. Örneğin, bir işlemi işleme sürecinin parçası olarak oluşturulan her günlük, işlem kimliğini içerebilir.

Kapsam:

Bu sağlayıcılar, aşağıdaki kapsamları destekler.

Günlükçü çağrılarını bir using bloğunda sarmalayarak kapsam 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 kapsam alanlarını etkinleştirmeye olanak tanır.

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

builder.Logging.ClearProviders();
builder.Logging.AddSimpleConsole(options => options.IncludeScopes = true);

using IHost host = builder.Build();

await host.RunAsync();

Main'de günlük oluşturma

Aşağıdaki kod, DI'den bir Main örneği alarak konağı oluşturduktan sonra ILogger'e giriş yapar:

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:

<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>

Eşzamansız kaydedici yöntemleri yok

Günlük kaydının o kadar hızlı olması gerekir ki asenkron kodun performans maliyetine değmesin. Günlük veri deposu yavaşsa, doğrudan oraya günlükleri yazmayın. Günlük mesajlarını önce hızlı bir depoya yazmayı, daha sonra yavaş depoya taşımayı düşünün. Örneğin, SQL Server'a günlüğe kaydederken, bunu doğrudan Log yönteminde yapmayın, çünkü Log yöntemleri eşzamanlıdır. Bunun yerine, günlük iletilerini zaman uyumlu biçimde bir bellek içi kuyruğa ekleyin ve bir arka plan işçisi verileri SQL Server'a zaman uyumsuz biçimde aktarmak için iletileri kuyruktan çeksin.

Çalışmakta olan bir uygulamada kayıt düzeylerini değiştirme

Günlük tutma API'si, bir uygulama çalışırken günlük seviyelerini değiştirmeye yönelik bir senaryo içermez. Ancak, bazı yapılandırma sağlayıcıları yapılandırmayı yeniden yükleyebilir ve bu da günlük yapılandırması üzerinde hemen etkili olur. Örneğin, Dosya Yapılandırma Sağlayıcısı günlük yapılandırmasını varsayılan olarak yeniden yükler. Bir uygulama çalışırken koddaki yapılandırmayı değiştirirseniz uygulama, uygulamanın günlük yapılandırmasını güncelleştirmek için IConfigurationRoot.Reload'ı çağırabilir.

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:

Daha fazla bilgi için hangi .NET SDK'sı örtük paket başvuruları içerdiğine bakın: .NET SDK: örtük ad alanı tablosu.

Ayrıca bkz.