ASP.NET Core 'de LoggerMessage ile yüksek performanslı günlüğe kaydetme

LoggerMessage özellikler, ve gibi günlükçü uzantısı yöntemlerinekıyasla daha az nesne ayırma ve daha düşük hesaplama yükü gerektiren önbelleğe alınabilir temsilciler oluşturur LogInformation LogDebug . Yüksek performanslı günlük senaryoları için, bu kalıbı kullanın LoggerMessage .

LoggerMessage Günlükçü uzantı yöntemlerine göre aşağıdaki performans avantajlarını sağlar:

  • Günlükçü uzantı yöntemleri, gibi "kutulama" (dönüştürme) değer türlerini gerektirir int object . Bu LoggerMessage model, Action kesin türü belirtilmiş parametrelerle statik alanlar ve genişletme yöntemleri kullanarak kutulamayı önler.
  • Günlükçü uzantısı yöntemlerinin her bir günlük iletisi yazıldığında ileti şablonunu (biçim dizesi olarak adlandırılır) ayrıştırması gerekir. LoggerMessage yalnızca ileti tanımlandığında bir şablonu ayrıştırmayı gerektirir.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Örnek uygulama, LoggerMessage temel bir Quote izleme sistemine sahip özellikleri gösterir. Uygulama, bellek içi veritabanı kullanarak tırnak ekler ve siler. Bu işlemler gerçekleştiğinde, günlük iletileri model kullanılarak oluşturulur LoggerMessage .

LoggerMessage. define

Define (LogLevel, EventID, String) Action bir iletiyi günlüğe kaydetmek için bir temsilci oluşturur. Define Aşırı Yüklemeler, adlandırılmış biçim dizesine (şablon) altı tür parametre geçişine izin verir.

Yöntemine girilen dize, Define enterpolasyonlu bir dize değil, bir şablondur. Yer tutucular, türlerin belirtilme sırasına göre doldurulur. Şablondaki yer tutucu adları, şablonlar genelinde açıklayıcı ve tutarlı olmalıdır. Bunlar, yapılandırılmış günlük verileri içinde özellik adı olarak görev yapar. Yer tutucu adları için Pascal büyük harfleri öneririz. Örneğin,, {Count} {FirstName} .

Her günlük iletisi, Action Loggermessage. definetarafından oluşturulan statik bir alanda tutulur. Örneğin, örnek uygulama, Dizin sayfası (iç/LoggerExtensions. cs) IÇIN bir GET isteğinin günlük iletisini tanımlayacak bir alan oluşturur:

private static readonly Action<ILogger, Exception> _indexPageRequested;

İçin Action şunu belirtin:

  • Günlük düzeyi.
  • EventIdStatik Uzantı yönteminin adı ile benzersiz bir olay tanımlayıcısı ().
  • İleti şablonu (biçim dizesi olarak adlandırılır).

Örnek uygulamanın dizin sayfası için bir istek şunları ayarlar:

  • Günlük düzeyi Information .
  • 1Yöntemin adı ile olay kimliği IndexPageRequested .
  • Bir dizeye ileti şablonu (biçim dizesi olarak adlandırılır).
_indexPageRequested = LoggerMessage.Define(
    LogLevel.Information, 
    new EventId(1, nameof(IndexPageRequested)), 
    "GET request for Index page");

Yapılandırılmış günlük depoları, olay kimliği ile birlikte verileri zenginleştirmek için sağlandığında olay adını kullanabilir. Örneğin, Serilog olay adını kullanır.

, Action Türü kesin belirlenmiş bir uzantı yöntemiyle çağrılır. IndexPageRequestedYöntemi, örnek uygulamada bir dizin sayfası get isteği için bir ileti kaydeder:

public static void IndexPageRequested(this ILogger logger)
{
    _indexPageRequested(logger, null);
}

IndexPageRequested , OnGetAsync sayfa/dizin. cshtml. cs içindeki yöntemdeki günlükçü üzerinde çağrılır:

public async Task OnGetAsync()
{
    _logger.IndexPageRequested();

    Quotes = await _db.Quotes.AsNoTracking().ToListAsync();
}

Uygulamanın konsol çıkışını inceleyin:

info: LoggerMessageSample.Pages.IndexModel[1]
      => RequestId:0HL90M6E7PHK4:00000001 RequestPath:/ => /Index
      GET request for Index page

Parametreleri bir günlük iletisine geçirmek için, statik alanı oluştururken en fazla altı tür tanımlayın. Örnek uygulama, alan için bir tür tanımlayarak bir alıntı eklerken bir dizeyi günlüğe kaydeder string Action :

private static readonly Action<ILogger, string, Exception> _quoteAdded;

Temsilcinin günlük iletisi şablonu, belirtilen türlerden yer tutucu değerlerini alır. Örnek uygulama, quote parametresinin bir tırnak işareti eklemek için bir temsilci tanımlar string :

_quoteAdded = LoggerMessage.Define<string>(
    LogLevel.Information, 
    new EventId(2, nameof(QuoteAdded)), 
    "Quote added (Quote = '{Quote}')");

Tırnak eklemek için statik genişletme yöntemi, QuoteAdded quote bağımsız değişkeni değerini alır ve Action temsilciye geçirir:

public static void QuoteAdded(this ILogger logger, string quote)
{
    _quoteAdded(logger, quote, null);
}

Dizin sayfasının sayfa modelinde (Sayfalar/Index. cshtml. cs), QuoteAdded iletiyi günlüğe kaydetmek için çağrılır:

public async Task<IActionResult> OnPostAddQuoteAsync()
{
    _db.Quotes.Add(Quote);
    await _db.SaveChangesAsync();

    _logger.QuoteAdded(Quote.Text);

    return RedirectToPage();
}

Uygulamanın konsol çıkışını inceleyin:

info: LoggerMessageSample.Pages.IndexModel[2]
      => RequestId:0HL90M6E7PHK5:0000000A RequestPath:/ => /Index
      Quote added (Quote = 'You can avoid reality, but you cannot avoid the 
          consequences of avoiding reality. - Ayn Rand')

Örnek uygulama, teklif silme için bir try-catch kalıbı uygular. Başarılı silme işlemi için bir bilgilendirici ileti günlüğe kaydedilir. Bir özel durum oluştuğunda silme işlemi için bir hata iletisi günlüğe kaydedilir. Başarısız silme işleminin günlük iletisi, özel durum yığın izlemesini içerir (iç/LoggerExtensions. cs):

private static readonly Action<ILogger, string, int, Exception> _quoteDeleted;
private static readonly Action<ILogger, int, Exception> _quoteDeleteFailed;
_quoteDeleted = LoggerMessage.Define<string, int>(
    LogLevel.Information, 
    new EventId(4, nameof(QuoteDeleted)), 
    "Quote deleted (Quote = '{Quote}' Id = {Id})");

_quoteDeleteFailed = LoggerMessage.Define<int>(
    LogLevel.Error, 
    new EventId(5, nameof(QuoteDeleteFailed)), 
    "Quote delete failed (Id = {Id})");

Özel durumun içindeki temsilciye nasıl geçtiğini aklınızda yapın QuoteDeleteFailed :

public static void QuoteDeleted(this ILogger logger, string quote, int id)
{
    _quoteDeleted(logger, quote, id, null);
}

public static void QuoteDeleteFailed(this ILogger logger, int id, Exception ex)
{
    _quoteDeleteFailed(logger, id, ex);
}

Dizin sayfasının sayfa modelinde, başarılı bir teklif silme işlemi QuoteDeleted günlükçü üzerindeki yöntemi çağırır. Silinmek üzere bir teklif bulunamadığında, bir oluşturulur ArgumentNullException . Özel durum, try-catch ifadesiyle QuoteDeleteFailed yakalar ve catch bloğunda (Pages/Index. cshtml. cs) günlükçü üzerindeki yöntemi çağırarak günlüğe kaydedilir:

public async Task<IActionResult> OnPostDeleteQuoteAsync(int id)
{
    try
    {
        var quote = await _db.Quotes.FindAsync(id);
        _db.Quotes.Remove(quote);
        await _db.SaveChangesAsync();

        _logger.QuoteDeleted(quote.Text, id);
    }
    catch (NullReferenceException ex)
    {
        _logger.QuoteDeleteFailed(id, ex);
    }

    return RedirectToPage();
}

Bir teklif başarıyla silindiğinde, uygulamanın konsol çıkışını inceleyin:

info: LoggerMessageSample.Pages.IndexModel[4]
      => RequestId:0HL90M6E7PHK5:00000016 RequestPath:/ => /Index
      Quote deleted (Quote = 'You can avoid reality, but you cannot avoid the 
          consequences of avoiding reality. - Ayn Rand' Id = 1)

Teklif silme başarısız olduğunda, uygulamanın konsol çıkışını inceleyin. Özel durumun günlük iletisine dahil edildiğini unutmayın:

LoggerMessageSample.Pages.IndexModel: Error: Quote delete failed (Id = 999)

System.NullReferenceException: Object reference not set to an instance of an object.
   at lambda_method(Closure , ValueBuffer )
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at Microsoft.EntityFrameworkCore.InMemory.Query.Internal.InMemoryShapedQueryCompilingExpressionVisitor.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at LoggerMessageSample.Pages.IndexModel.OnPostDeleteQuoteAsync(Int32 id) in c:\Users\guard\Documents\GitHub\Docs\aspnetcore\fundamentals\logging\loggermessage\samples\3.x\LoggerMessageSample\Pages\Index.cshtml.cs:line 77

LoggerMessage. DefineScope

DefineScope (String) , Func<TResult> günlük kapsamıtanımlamak için bir temsilci oluşturur. DefineScope Aşırı Yüklemeler, adlandırılmış biçim dizesine (şablon) üç tür parametrenin geçirilmesine izin verir.

Yönteminde olduğu gibi Define , yöntemi için girilen dize, ilişkili DefineScope dize değil, bir şablondur. Yer tutucular, türlerin belirtilme sırasına göre doldurulur. Şablondaki yer tutucu adları, şablonlar genelinde açıklayıcı ve tutarlı olmalıdır. Bunlar, yapılandırılmış günlük verileri içinde özellik adı olarak görev yapar. Yer tutucu adları için Pascal büyük harfleri öneririz. Örneğin,, {Count} {FirstName} .

Yöntemini kullanarak bir dizi günlük mesajı için uygulanacak günlük kapsamını tanımlayın DefineScope .

Örnek uygulamanın, veritabanındaki tüm teklifleri silmek için Tümünü Temizle düğmesi vardır. Tırnak işaretleri tek seferde kaldırılarak silinir. Bir teklifin her silindiği her seferinde QuoteDeleted yöntemi günlükçü üzerinde çağrılır. Bu günlük iletilerine bir günlük kapsamı eklenir.

IncludeScopesKonsol günlükçü bölümünde appsettings.json şunları etkinleştirin:

{
  "Logging": {
    "Console": {
      "IncludeScopes": true
    },
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Bir günlük kapsamı oluşturmak için, kapsam için bir temsilci tutacak bir alan ekleyin Func<TResult> . Örnek uygulama _allQuotesDeletedScope (Iç/LoggerExtensions. cs) adlı bir alan oluşturur:

private static Func<ILogger, int, IDisposable> _allQuotesDeletedScope;

DefineScopeTemsilciyi oluşturmak için kullanın. Temsilci çağrıldığında Şablon bağımsız değişkenleri olarak kullanmak için en fazla üç tür belirlenebilir. Örnek uygulama, silinen tekliflerin sayısını (bir tür) içeren bir ileti şablonu kullanır int :

_allQuotesDeletedScope = 
    LoggerMessage.DefineScope<int>("All quotes deleted (Count = {Count})");

Günlük iletisi için bir statik genişletme yöntemi sağlayın. İleti şablonunda görünen adlandırılmış özellikler için herhangi bir tür parametresi ekleyin. Örnek uygulama, count silmek ve geri döndürmek için tırnak içine alır _allQuotesDeletedScope :

public static IDisposable AllQuotesDeletedScope(
    this ILogger logger, int count)
{
    return _allQuotesDeletedScope(logger, count);
}

Kapsam, oturum açma uzantısı çağrılarını bir using bloğunda sarmalar:

public async Task<IActionResult> OnPostDeleteAllQuotesAsync()
{
    var quoteCount = await _db.Quotes.CountAsync();

    using (_logger.AllQuotesDeletedScope(quoteCount))
    {
        foreach (Quote quote in _db.Quotes)
        {
            _db.Quotes.Remove(quote);

            _logger.QuoteDeleted(quote.Text, quote.Id);
        }
        await _db.SaveChangesAsync();
    }

    return RedirectToPage();
}

Uygulamanın konsol çıkışında günlük iletilerini inceleyin. Aşağıdaki sonuç, günlük kapsamı iletisi dahil olmak üzere silinen üç tırnak gösterir:

info: LoggerMessageSample.Pages.IndexModel[4]
      => RequestId:0HL90M6E7PHK5:0000002E RequestPath:/ => /Index => 
          All quotes deleted (Count = 3)
      Quote deleted (Quote = 'Quote 1' Id = 2)
info: LoggerMessageSample.Pages.IndexModel[4]
      => RequestId:0HL90M6E7PHK5:0000002E RequestPath:/ => /Index => 
          All quotes deleted (Count = 3)
      Quote deleted (Quote = 'Quote 2' Id = 3)
info: LoggerMessageSample.Pages.IndexModel[4]
      => RequestId:0HL90M6E7PHK5:0000002E RequestPath:/ => /Index => 
          All quotes deleted (Count = 3)
      Quote deleted (Quote = 'Quote 3' Id = 4)

LoggerMessage özellikler, ve gibi günlükçü uzantısı yöntemlerinekıyasla daha az nesne ayırma ve daha düşük hesaplama yükü gerektiren önbelleğe alınabilir temsilciler oluşturur LogInformation LogDebug . Yüksek performanslı günlük senaryoları için, bu kalıbı kullanın LoggerMessage .

LoggerMessage Günlükçü uzantı yöntemlerine göre aşağıdaki performans avantajlarını sağlar:

  • Günlükçü uzantı yöntemleri, gibi "kutulama" (dönüştürme) değer türlerini gerektirir int object . Bu LoggerMessage model, Action kesin türü belirtilmiş parametrelerle statik alanlar ve genişletme yöntemleri kullanarak kutulamayı önler.
  • Günlükçü uzantısı yöntemlerinin her bir günlük iletisi yazıldığında ileti şablonunu (biçim dizesi olarak adlandırılır) ayrıştırması gerekir. LoggerMessage yalnızca ileti tanımlandığında bir şablonu ayrıştırmayı gerektirir.

Örnek kodu görüntüleme veya indirme (nasıl indirileceği)

Örnek uygulama, LoggerMessage temel bir Quote izleme sistemine sahip özellikleri gösterir. Uygulama, bellek içi veritabanı kullanarak tırnak ekler ve siler. Bu işlemler gerçekleştiğinde, günlük iletileri model kullanılarak oluşturulur LoggerMessage .

LoggerMessage. define

Define (LogLevel, EventID, String) Action bir iletiyi günlüğe kaydetmek için bir temsilci oluşturur. Define Aşırı Yüklemeler, adlandırılmış biçim dizesine (şablon) altı tür parametre geçişine izin verir.

Yöntemine girilen dize, Define enterpolasyonlu bir dize değil, bir şablondur. Yer tutucular, türlerin belirtilme sırasına göre doldurulur. Şablondaki yer tutucu adları, şablonlar genelinde açıklayıcı ve tutarlı olmalıdır. Bunlar, yapılandırılmış günlük verileri içinde özellik adları olarak görev yapacaktır. Yer tutucu adları için Pascal büyük/büyük/büyük/yenisi önerilir. Örneğin, {Count} , {FirstName} .

Her günlük Action iletisi, LoggerMessage.Definetarafından oluşturulan statik bir alanda tutulan bir iletidir. Örneğin, örnek uygulama Dizin sayfası (Internal/LoggerExtensions.cs) için bir GET isteği için günlük iletisi açıklamak için bir alan oluşturur:

private static readonly Action<ILogger, Exception> _indexPageRequested;

için Action şunları belirtin:

  • Günlük düzeyi.
  • Statik uzantı yönteminin adıyla benzersiz bir olay tanımlayıcısı ( EventId ).
  • İleti şablonu (adlandırılmış biçim dizesi).

Örnek uygulamanın Dizin sayfası için bir istek şunları ayarlar:

  • Günlük düzeyi: Information .
  • yönteminin adıyla olay 1 IndexPageRequested kimliği.
  • bir dizeye ileti şablonu (adlandırılmış biçim dizesi).
_indexPageRequested = LoggerMessage.Define(
    LogLevel.Information, 
    new EventId(1, nameof(IndexPageRequested)), 
    "GET request for Index page");

Yapılandırılmış günlük depoları, günlüğe kaydetmeyi zenginleştirmek için olay kimliğiyle birlikte sağlandıklarında olay adını kullanabilir. Örneğin Serilog olay adını kullanır.

Action, kesin türü kesin olarak türü kesin olan bir genişletme yöntemiyle çağrılır. yöntemi, IndexPageRequested örnek uygulamada dizin sayfası GET isteği için bir ileti günlüğe kaydeder:

public static void IndexPageRequested(this ILogger logger)
{
    _indexPageRequested(logger, null);
}

IndexPageRequested , OnGetAsync Pages/Index.cshtml.cs içinde yönteminde günlükte çağrılır:

public async Task OnGetAsync()
{
    _logger.IndexPageRequested();

    Quotes = await _db.Quotes.AsNoTracking().ToListAsync();
}

Uygulamanın konsol çıkışını inceleme:

info: LoggerMessageSample.Pages.IndexModel[1]
      => RequestId:0HL90M6E7PHK4:00000001 RequestPath:/ => /Index
      GET request for Index page

Parametreleri bir günlük iletisine geçmek için statik alanı oluştururken en fazla altı tür tanımlayın. Örnek uygulama, alan için bir tür tanımlayarak tırnak eklerken string bir dize Action kaydeder:

private static readonly Action<ILogger, string, Exception> _quoteAdded;

Temsilcinin günlük iletisi şablonu, sağlanan türlerden yer tutucu değerlerini alır. Örnek uygulama, tırnak parametresinin bir olduğu teklif ekleme temsilcisini string tanımlar:

_quoteAdded = LoggerMessage.Define<string>(
    LogLevel.Information, 
    new EventId(2, nameof(QuoteAdded)), 
    "Quote added (Quote = '{Quote}')");

teklifi eklemek için statik genişletme yöntemi, tırnak bağımsız QuoteAdded değişken değerini alır ve temsilciye Action iletir:

public static void QuoteAdded(this ILogger logger, string quote)
{
    _quoteAdded(logger, quote, null);
}

Dizin sayfasının sayfa modelinde (Pages/Index.cshtml.cs QuoteAdded ), iletiyi günlüğe kaydettirilen çağrılır:

public async Task<IActionResult> OnPostAddQuoteAsync()
{
    _db.Quotes.Add(Quote);
    await _db.SaveChangesAsync();

    _logger.QuoteAdded(Quote.Text);

    return RedirectToPage();
}

Uygulamanın konsol çıkışını inceleme:

info: LoggerMessageSample.Pages.IndexModel[2]
      => RequestId:0HL90M6E7PHK5:0000000A RequestPath:/ => /Index
      Quote added (Quote = 'You can avoid reality, but you cannot avoid the 
          consequences of avoiding reality. - Ayn Rand')

Örnek uygulama, teklif silme için bir try-catch deseni uygulama. Başarılı bir silme işlemi için bilgilendirme iletisi günlüğe kaydedilir. Bir özel durum iletiyi iletiyi silinecek şekilde günlüğe kaydedilir. Başarısız silme işlemi için günlük iletisi özel durum yığını izlemesini içerir (Internal/LoggerExtensions.cs):

private static readonly Action<ILogger, string, int, Exception> _quoteDeleted;
private static readonly Action<ILogger, int, Exception> _quoteDeleteFailed;
_quoteDeleted = LoggerMessage.Define<string, int>(
    LogLevel.Information, 
    new EventId(4, nameof(QuoteDeleted)), 
    "Quote deleted (Quote = '{Quote}' Id = {Id})");

_quoteDeleteFailed = LoggerMessage.Define<int>(
    LogLevel.Error, 
    new EventId(5, nameof(QuoteDeleteFailed)), 
    "Quote delete failed (Id = {Id})");

özel durumun içinde temsilciye nasıl geçirildiklerini QuoteDeleteFailed unutmayın:

public static void QuoteDeleted(this ILogger logger, string quote, int id)
{
    _quoteDeleted(logger, quote, id, null);
}

public static void QuoteDeleteFailed(this ILogger logger, int id, Exception ex)
{
    _quoteDeleteFailed(logger, id, ex);
}

Dizin sayfasının sayfa modelinde başarılı bir tırnak silme işlemi QuoteDeleted günlükte yöntemini çağırıyor. Silme için bir tırnak bulunamasa, ArgumentNullException bir atılan. Özel durum try-catch deyimi tarafından yakalanıyor ve catch bloğunda günlükç üzerinde yöntemi çağrılarak günlüğe kaydedilir QuoteDeleteFailed (Pages/Index.cshtml.cs):

public async Task<IActionResult> OnPostDeleteQuoteAsync(int id)
{
    var quote = await _db.Quotes.FindAsync(id);

    // DO NOT use this approach in production code!
    // You should check quote to see if it's null before removing 
    // it and saving changes to the database. A try-catch is used 
    // here for demonstration purposes of LoggerMessage features.
    try
    {
        _db.Quotes.Remove(quote);
        await _db.SaveChangesAsync();

        _logger.QuoteDeleted(quote.Text, id);
    }
    catch (ArgumentNullException ex)
    {
        _logger.QuoteDeleteFailed(id, ex);
    }

    return RedirectToPage();
}

Tırnak başarıyla silindiğinde uygulamanın konsol çıkışını incele:

info: LoggerMessageSample.Pages.IndexModel[4]
      => RequestId:0HL90M6E7PHK5:00000016 RequestPath:/ => /Index
      Quote deleted (Quote = 'You can avoid reality, but you cannot avoid the 
          consequences of avoiding reality. - Ayn Rand' Id = 1)

Teklif silme işlemi başarısız olduğunda uygulamanın konsol çıkışını kontrol edin. Özel durumun günlük iletisine dahil olduğunu unutmayın:

fail: LoggerMessageSample.Pages.IndexModel[5]
      => RequestId:0HL90M6E7PHK5:00000010 RequestPath:/ => /Index
      Quote delete failed (Id = 999)
System.ArgumentNullException: Value cannot be null.
Parameter name: entity
   at Microsoft.EntityFrameworkCore.Utilities.Check.NotNull[T]
       (T value, String parameterName)
   at Microsoft.EntityFrameworkCore.DbContext.Remove[TEntity](TEntity entity)
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Remove(TEntity entity)
   at LoggerMessageSample.Pages.IndexModel.<OnPostDeleteQuoteAsync>d__14.MoveNext() 
      in <PATH>\sample\Pages\Index.cshtml.cs:line 87

LoggerMessage.DefineScope

DefineScope(String), bir günlük Func<TResult> kapsamı tanımlamak için bir temsilci oluşturur. DefineScope aşırı yüklemeler adlandırılmış biçim dizesine (şablon) üç tür parametre geçirmeye izin verir.

yönteminde olduğu Define gibi, yöntemine sağlanan dize bir şablondur ve irdelenmiş DefineScope bir dize değildir. Yer tutucular, türlerin belirtilen sırasıyla doldurulur. Şablonda yer tutucu adları, şablonlar arasında açıklayıcı ve tutarlı olmalıdır. Bunlar, yapılandırılmış günlük verileri içinde özellik adları olarak görev yapacaktır. Yer tutucu adları için Pascal büyük/büyük/büyük/yenisi önerilir. Örneğin, {Count} , {FirstName} .

yöntemini kullanarak bir dizi günlük mesajına uygulanacak bir günlük kapsamı DefineScope tanımlayın.

Örnek uygulama, veritabanındaki tüm tırnakları silmek için Bir Hepsini Temizle düğmesine sahip. Tırnaklar tek tek kaldırılarak silinir. Her teklif silindiğinde QuoteDeleted günlükte yöntemi çağrılır. Bu günlük iletilerine bir günlük kapsamı eklenir.

konsol IncludeScopes günlükleyicisi bölümünde appsettings.json etkinleştirin:

{
  "Logging": {
    "Console": {
      "IncludeScopes": true
    },
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Günlük kapsamı oluşturmak için, kapsam için bir temsilci tutmak Func<TResult> için bir alan ekleyin. Örnek uygulama adlı bir alan oluşturur _allQuotesDeletedScope (Internal/LoggerExtensions.cs):

private static Func<ILogger, int, IDisposable> _allQuotesDeletedScope;

Temsilciyi DefineScope oluşturmak için kullanın. Temsilci çağrıldığında şablon bağımsız değişkenleri olarak kullanmak için en fazla üç tür belirtilebilir. Örnek uygulama, silinen tırnak (tür) sayısını içeren bir ileti şablonu int kullanır:

_allQuotesDeletedScope = 
    LoggerMessage.DefineScope<int>("All quotes deleted (Count = {Count})");

Günlük iletisi için statik bir uzantı yöntemi sağlar. İleti şablonunda görünen adlandırılmış özellikler için herhangi bir tür parametresini dahil etmek. Örnek uygulama, silmek için count tırnak içine alır ve _allQuotesDeletedScope döndürür:

public static IDisposable AllQuotesDeletedScope(
    this ILogger logger, int count)
{
    return _allQuotesDeletedScope(logger, count);
}

Kapsam, günlük uzantısı çağrılarını bir using bloğuna sarmalar:

public async Task<IActionResult> OnPostDeleteAllQuotesAsync()
{
    var quoteCount = await _db.Quotes.CountAsync();

    using (_logger.AllQuotesDeletedScope(quoteCount))
    {
        foreach (Quote quote in _db.Quotes)
        {
            _db.Quotes.Remove(quote);

            _logger.QuoteDeleted(quote.Text, quote.Id);
        }
        await _db.SaveChangesAsync();
    }

    return RedirectToPage();
}

Uygulamanın konsol çıkışında günlük iletilerini inceleme. Aşağıdaki sonuç, günlük kapsamı iletisinin dahil olduğu üç tırnak iletinin silinmiş olduğunu gösterir:

info: LoggerMessageSample.Pages.IndexModel[4]
      => RequestId:0HL90M6E7PHK5:0000002E RequestPath:/ => /Index => 
          All quotes deleted (Count = 3)
      Quote deleted (Quote = 'Quote 1' Id = 2)
info: LoggerMessageSample.Pages.IndexModel[4]
      => RequestId:0HL90M6E7PHK5:0000002E RequestPath:/ => /Index => 
          All quotes deleted (Count = 3)
      Quote deleted (Quote = 'Quote 2' Id = 3)
info: LoggerMessageSample.Pages.IndexModel[4]
      => RequestId:0HL90M6E7PHK5:0000002E RequestPath:/ => /Index => 
          All quotes deleted (Count = 3)
      Quote deleted (Quote = 'Quote 3' Id = 4)

Ek kaynaklar