İngilizce dilinde oku

Aracılığıyla paylaş


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 bir string 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 çifti Description = funiç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="9.0.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
  </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:

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şlendi ExampleHandler.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ğunu ILogger gösterir. DI kapsayıcısı doğru kategoriye sahip bir ILogger bulur ve oluşturucu bağımsız değişkeni olarak sağlar. Henüz bu kategoriye sahip hayır ILogger varsa, DI kapsayıcısı bunu hizmet sağlayıcısından otomatik olarak oluşturur ILoggerFactory .
  • logger Oluşturucuda alınan parametre, işlevde HandleRequest 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 WebApplicationBuildersağ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şturuldu ILogger<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üzeyinde Warning 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 Informationayarlanı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 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ı, 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 Informationsahip 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:

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.ReadLog 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 veya Debug 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çin Trace ve Debug düzeyindeki iletileri yüksek hacimli ve düşük maliyetli bir veri deposunda günlüğe kaydedin. Trace ve Debug düzeylerini belirli kategorilerle sınırlamayı göz önünde bulundurun.
    • Warning ile Critical 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 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"
            }
        }
    }
}

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

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:

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:

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.

Ayrıca bkz.