.NET kitaplığı yazarları için günlüğe kaydetme kılavuzu

Bir kitaplık yazarı olarak, günlüğe kaydetmeyi kullanıma sunmak, tüketicilere kitaplığınızın iç çalışmalarıyla ilgili içgörüler sağlamanın harika bir yoludur. Bu kılavuz, günlüğü diğer .NET kitaplıkları ve çerçeveleriyle tutarlı bir şekilde kullanıma sunmanıza yardımcı olur. Ayrıca, aksi halde belirgin olmayan yaygın performans sorunlarını önlemenize de yardımcı olur.

Arabirimin ne zaman kullanılacağı ILoggerFactory

Günlükleri yayan bir kitaplık yazarken, günlükleri kaydetmek için bir ILogger nesneye ihtiyacınız vardır. Bu nesneyi almak için API'niz bir ILogger<TCategoryName> parametreyi kabul edebilir veya çağırdığınız ILoggerFactory.CreateLoggerbir ILoggerFactory parametreyi kabul edebilir. Hangi yaklaşım tercih edilmelidir?

  • Tümünün günlükleri yayabilmesi için birden çok sınıfa geçirilebilen bir günlük nesnesine ihtiyacınız olduğunda kullanın ILoggerFactory. Her sınıfın, sınıfla aynı adlı ayrı bir kategoriye sahip günlükler oluşturması önerilir. Bunu yapmak için fabrikanın günlükleri yayan her sınıf için benzersiz ILogger<TCategoryName> nesneler oluşturması gerekir. Yaygın örnekler arasında, bir kitaplık için genel giriş noktası API'leri veya dahili olarak yardımcı sınıflar oluşturabilecek türlerin ortak oluşturucuları yer alır.

  • Yalnızca bir sınıfta kullanılan ve hiç paylaşılmamış bir günlük nesnesine ihtiyacınız olduğunda, kullanın ILogger<TCategoryName>. Burada TCategoryName günlükleri oluşturan türdür. Bunun yaygın bir örneği, bağımlılık ekleme tarafından oluşturulan bir sınıf için oluşturucudur.

Zaman içinde kararlı kalması gereken bir genel API tasarlarsanız, gelecekte iç uygulamanızı yeniden düzenlemeyi isteyebileceğinizi unutmayın. Bir sınıf başlangıçta herhangi bir iç yardımcı türü oluşturmasa bile, kod geliştikçe bu değişebilir. kullanımı ILoggerFactory , genel API'yi değiştirmeden tüm yeni sınıflar için yeni nesneler oluşturmayı ILogger<TCategoryName> kapsar.

Daha fazla bilgi için bkz . Filtreleme kuralları nasıl uygulanır?

Kaynak tarafından oluşturulan günlüğü tercih edin

API, ILogger API'yi kullanmaya yönelik iki yaklaşımı destekler. ve LoggerExtensions.LogInformationgibi LoggerExtensions.LogError yöntemleri çağırabilir veya günlüğe kaydetme kaynak oluşturucuyu kullanarak kesin olarak yazılan günlük yöntemlerini tanımlayabilirsiniz. Çoğu durumda, üstün performans ve daha güçlü yazma özelliği sunduğundan kaynak oluşturucu önerilir. Ayrıca ileti şablonları, kimlikler ve günlük düzeyleri gibi günlüğe kaydetmeye özgü endişeleri de çağıran koddan ayırır. Kaynak oluşturulmayan yaklaşım, kodu daha kısa hale getirmek için bu avantajlardan vazgeçmeye istekli olduğunuz senaryolar için öncelikli olarak yararlıdır.

using Microsoft.Extensions.Logging;

namespace Logging.LibraryAuthors;

internal static partial class LogMessages
{
    [LoggerMessage(
        Message = "Sold {Quantity} of {Description}",
        Level = LogLevel.Information)]
    internal static partial void LogProductSaleDetails(
        this ILogger logger,
        int quantity,
        string description);
}

Yukarıdaki kod:

  • türünde uzantı yöntemlerini ILogger tanımlamak için kullanılabilmesi için adlandırılmış LogMessagesbir partial class öğesini static tanımlar.
  • Bir LogProductSaleDetails uzantı yöntemini özniteliği ve Message şablonuyla LoggerMessage süsler.
  • LogProductSaleDetailsve 'yi genişleten ILogger ve kabul eden quantitydescriptionöğesini bildirir.

İpucu

Hata ayıklama sırasında kaynak tarafından oluşturulan koda adım atabilirsiniz çünkü bu kod, onu çağıran kodla aynı derlemenin bir parçasıdır.

Pahalı parametre değerlendirmesini önlemek için kullanın IsEnabled

Parametreleri değerlendirmenin pahalı olduğu durumlar olabilir. Önceki örneği genişleterek parametresinin description işlem için pahalı bir string parametre olduğunu düşünün. Belki de satılan ürün kolay bir ürün açıklaması alır ve bir veritabanı sorgusuna veya bir dosyadan okumaya dayanır. Böyle durumlarda, kaynak oluşturucuya korumayı atlayıp IsEnabled korumayı IsEnabled çağrı alanına el ile eklemesini sağlayabilirsiniz. Bu, kullanıcının korumanın nerede çağrıldığını belirlemesine olanak tanır ve hesaplanması pahalı olabilecek parametrelerin yalnızca gerçekten gerekli olduğunda değerlendirilmesini sağlar. Aşağıdaki kodu inceleyin:

using Microsoft.Extensions.Logging;

namespace Logging.LibraryAuthors;

internal static partial class LogMessages
{
    [LoggerMessage(
        Message = "Sold {Quantity} of {Description}",
        Level = LogLevel.Information,
        SkipEnabledCheck = true)]
    internal static partial void LogProductSaleDetails(
        this ILogger logger,
        int quantity,
        string description);
}

LogProductSaleDetails Uzantı yöntemi çağrıldığında, IsEnabled koruma el ile çağrılır ve pahalı parametre değerlendirmesi gerektiğinde ile sınırlıdır. Aşağıdaki kodu inceleyin:

if (_logger.IsEnabled(LogLevel.Information))
{
    // Expensive parameter evaluation
    var description = product.GetFriendlyProductDescription();

    _logger.LogProductSaleDetails(
        quantity,
        description);
}

Daha fazla bilgi için bkz . Derleme zamanı günlüğü kaynak oluşturma ve .NET'te yüksek performanslı günlük.

Günlükte dize ilişkilendirmesini önleme

Günlük iletileri oluşturmak için dize ilişkilendirmesini kullanmak yaygın bir hatadır. Dize, ilgili LogLevel etkin olmasa bile değerlendirildiğinden, günlükteki dize ilişkilendirmesi performans açısından sorunludur. Dize ilişkilendirmesi yerine günlük iletisi şablonunu, biçimlendirmesini ve bağımsız değişken listesini kullanın. Daha fazla bilgi için bkz . .NET'te oturum açma: Günlük iletisi şablonu.

İşlem dışı günlük varsayılanlarını kullanma

Bazen, veya ILoggerFactoryolmasını bekleyen ILogger günlük API'lerini kullanıma sunan bir kitaplık kullanırken günlükçü sağlamak istemediğiniz zamanlar olabilir. Bu gibi durumlarda, Microsoft.Extensions.Logging.Abstractions NuGet paketi, çalışma dışı günlük varsayılanları sağlar.

Kitaplık tüketicileri, sağlanmayan ILoggerFactory null günlüğe kaydetmeyi varsayılan olarak kullanabilir. Null günlüğe kaydetmenin kullanılması, türleri null olmayan türler olduğundan, türlerin null atanabilir ()ILoggerFactory? olarak tanımlanmasından farklıdır. Bu kolaylık tabanlı türler hiçbir şeyi günlüğe kaydetmez ve temelde işlem yapılmaz. Uygun olduğunda kullanılabilir soyutlama türlerinden herhangi birini kullanmayı göz önünde bulundurun: