Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
.NET 6 ve sonraki sürümlerde yüksek performanslı loglama senaryoları için LoggerMessageAttributederleme zamanı kaynak üretimi ile kullanın. Bu yaklaşım, çalışma zamanında kutulama, geçici ayırmalar ve ileti şablonu ayrıştırmalarını ortadan kaldırarak en iyi performansı sağlar.
Kaynak tarafından oluşturulan günlük kaydı, LogInformationLogDebug gibi günlükçü genişletme yöntemlerine göre aşağıdaki performans avantajlarını sağlar:
-
Kutulama ortadan kalkar: Günlükçü uzantı yöntemleri,
intgibi değer türleriniobjectiçine "boxing" (kutulama) gerektirir. Kaynak tabanlı günlük, güçlü yazılmış parametreler kullanarak kutulama işleminden kaçınıyor. - Şablonları derleme zamanında ayrıştırma: Logger uzantısı yöntemleri, günlük iletisi her yazıldığında ileti şablonunu (adlandırılmış biçim dizesi) ayrıştırmalıdır. Kaynak tarafından oluşturulan günlük, şablonları derleme zamanında bir kez ayrıştırıyor.
- Ayırmaları azaltır: Kaynak oluşturucu, nesne ayırmalarını ve geçici bellek kullanımını en aza indiren iyileştirilmiş kod oluşturur.
Örnek uygulama, öncelik sırasına göre işleyen bir çalışan hizmetiyle yüksek performanslı loglama özelliklerini gösterir. Uygulama, iş öğelerini öncelik sırasına göre işler. Bu işlemler gerçekleşirken, günlük iletileri kaynak tarafından oluşturulan günlük kaydı kullanılarak oluşturulur.
Tavsiye
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.
Kaynak oluşturma ile logger mesajlarını tanımlama
Yüksek performanslı günlük iletileri oluşturmak için, .NET 6 ve sonraki sürümlerde partial ile dekore edilmiş yöntemleri tanımlayın LoggerMessageAttribute. Kaynak oluşturucu derleme zamanında uygulamayı oluşturur.
Temel günlük yöntemi
Basit bir günlük iletisi için olay kimliğini, günlük düzeyini ve ileti şablonunu belirten özniteliğiyle kısmi bir yöntem tanımlayın:
public static partial class Log
{
[LoggerMessage(
EventId = 13,
Level = LogLevel.Critical,
Message = "Epic failure processing item!")]
public static partial void FailedToProcessWorkItem(
ILogger logger, Exception ex);
}
İleti şablonu, yöntem parametreleriyle doldurulan yer tutucuları kullanır. Yer tutucu adları, şablonlar arasında açıklayıcı ve tutarlı olmalıdır. Yapılandırılmış günlük verileri içinde özellik adları olarak görev yaparlar. Yer tutucu adları için Pascal büyük/küçük harflerini kullanmanızı öneririz. Örneğin, {Item}, {DateTime}.
Kodunuzda loglama metodunu çağırın. Örneğin, iş öğesi işlenirken bir özel durum oluştuğunda:
try
{
// Process work item.
}
catch (Exception ex)
{
Log.FailedToProcessWorkItem(logger, ex);
}
Bu kod aşağıdaki gibi bir konsol çıkışı oluşturur:
crit: WorkerServiceOptions.Example.Worker[13]
Epic failure processing item!
System.Exception: Failed to verify communications.
Parametrelerle günlüğe kaydetme
Günlük iletisine parametre geçirmek için bunları yöntem parametresi olarak ekleyin. Parametre adları ileti şablonundaki yer tutucularla eşleşmektedir:
public static partial class Log
{
[LoggerMessage(
EventId = 1,
Level = LogLevel.Information,
Message = "Processing priority item: {Item}")]
public static partial void PriorityItemProcessed(
ILogger logger, WorkItem item);
}
Logger'ı ve parametre değerlerini kullanarak metodu çağırın.
var workItem = queue.Dequeue();
Log.PriorityItemProcessed(logger, workItem);
Bu kod aşağıdaki gibi bir konsol çıkışı oluşturur:
info: WorkerServiceOptions.Example.Worker[1]
Processing priority item: Priority-Extreme (50db062a-9732-4418-936d-110549ad79e4): 'Verify communications'
Yapılandırılmış günlük depoları, günlüğü zenginleştirmek için olay kimliğiyle birlikte sağlandığında olay adını kullanabilir. Örneğin, Serilog olay adını kullanır.
Kaynak üretimi ile logger mesaj kapsamını tanımlama
Bir dizi günlük mesajını ek bağlamla sarmak için günlük kapsamları tanımlayabilirsiniz. Kaynak tarafından oluşturulan günlük kaydıyla, LoggerMessageAttribute yöntemleri ILogger.BeginScope standart yöntemle birleştirirsiniz.
IncludeScopes dosyasının konsol günlükçüsü bölümünde etkinleştirin:
{
"Logging": {
"Console": {
"IncludeScopes": true
},
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
kaynağa özgü günlük yöntemleri oluşturun ve bunları BeginScope kullanarak bir kapsama sarmalayın:
public static partial class Log
{
[LoggerMessage(
EventId = 1,
Level = LogLevel.Information,
Message = "Processing priority item: {Item}")]
public static partial void PriorityItemProcessed(
ILogger logger, WorkItem item);
}
Uygulama kodunuzda bir kapsam içinde günlük kaydı yöntemini kullanın.
using (_logger.BeginScope("Processing scope, started at: {DateTime}", DateTime.Now))
{
Log.PriorityItemProcessed(_logger, workItem);
}
Uygulamanın konsol çıkışındaki günlük iletilerini inceleyin. Aşağıdaki sonuç, kayıt kapsam mesajının dahil olduğu kayıt mesajlarının öncelik sıralamasını gösterir.
info: WorkerServiceOptions.Example.Worker[1]
=> Processing scope, started at: 04/11/2024 11:27:52
Processing priority item: Priority-Extreme (7d153ef9-8894-4282-836a-8e5e38319fb3): 'Verify communications'
Eski yaklaşım: LoggerMessage.Define (.NET Framework ve .NET Core 3.1 için)
.NET 6'da kaynak tarafından oluşturulan günlük kaydı tanıtılmadan önce, yüksek performanslı günlüğe kaydetme için önerilen yaklaşım, önbelleğe alınabilir temsilciler oluşturmak amacıyla LoggerMessage.Define yöntemini kullanmaktı. Bu yaklaşım geriye dönük uyumluluk için hala destekleniyor olsa da, yeni kod bunun yerine kaynak tarafından üretilen günlük kullanmalıdır LoggerMessageAttribute.
LoggerMessage sınıfı, , LogInformation ve LogDebug gibi günlükçü uzantı yöntemlerine kıyasla daha az nesne ayırma ve daha az hesaplama yükü gerektiren önbelleğe alınabilir temsilciler oluşturma işlevselliğini sunar. LoggerMessage günlükçü uzantısı yöntemlerine göre aşağıdaki performans avantajlarını sağlar:
- Günlükçü uzantısı yöntemleri, gibi
int"boxing" (dönüştürme) değer türlerini içine gerektirirobject. Desen, LoggerMessage kesin olarak yazılan parametrelerle statik Action alanlar ve uzantı yöntemleri kullanarak kutulama yapmaktan kaçınır. - Günlükçü uzantısı yöntemleri, günlük iletisi her yazıldıktan sonra ileti şablonunu (adlandırılmış biçim dizesi) ayrıştırmalıdır. LoggerMessage bir şablonun yalnızca ileti tanımlandığında ayrıştırılması gerekir.
Uyarı
kullanan bir kodu sürdürüyorsanız, kaynaktan üretilen kayda geçmeyi düşünün. .NET Framework veya .NET Core 3.1 uygulamaları için kullanmaya LoggerMessage.Definedevam edin.
Kayıt tutucu mesajı tanımlama
Define(LogLevel, EventId, String) kullanarak bir iletiyi günlüğe kaydetmek için bir Action temsilci oluşturun. Define aşırı yüklemeler, adlandırılmış biçim dizesine (şablon) en fazla altı tür parametresi geçirmesine izin verir.
yöntemine Define sağlanan dize, ilişkilendirilmiş bir dize değil, bir şablondur. Yer tutucular, türlerin belirtilmesi sırasına göre doldurulur. Şablondaki yer tutucu adları, şablonlar arasında açıklayıcı ve tutarlı olmalıdır. Yapılandırılmış günlük verileri içinde özellik adları olarak görev yaparlar. Yer tutucu adları için Pascal Case kullanmanızı öneririz. Örneğin, {Item}, {DateTime}.
Her günlük iletisi, ActionLoggerMessage.Define tarafından oluşturulan statik bir alanda tutulur. Örneğin, örnek uygulama iş öğelerinin işlenmesine yönelik bir günlük iletisini açıklamak için bir alan oluşturur:
private static readonly Action<ILogger, Exception> s_failedToProcessWorkItem;
Action için belirtin:
- Log seviyesi.
- Statik uzantı yönteminin adıyla benzersiz bir olay tanımlayıcısı (EventId).
- İleti şablonu (adlandırılmış biçim dizesi).
İş öğeleri işlenmek üzere sıralandığından, çalışan hizmeti uygulaması şunları ayarlar:
- Günlük seviyesini LogLevel.Critical olarak ayarla.
-
13olay kimliğiFailedToProcessWorkItemyöntem adını içerir. - Mesaj şablonu (adlandırılmış biçim dizesi) bir dizeye dönüştürülür.
s_failedToProcessWorkItem = LoggerMessage.Define(
LogLevel.Critical,
new EventId(13, nameof(FailedToProcessWorkItem)),
"Epic failure processing item!");
LoggerMessage.Define yöntemi, günlük iletisini temsil eden bir Action temsilciyi yapılandırmak ve tanımlamak için kullanılır.
Yapılandırılmış günlük depoları, günlüğü zenginleştirmek için olay kimliğiyle birlikte verildiğinde olay adını kullanabilir. Örneğin, Serilog olay adını kullanır.
Action türü kesin olarak belirlenmiş bir uzantı yöntemiyle çağrılır.
PriorityItemProcessed yöntemi, her iş öğesi işlendiğinde bir mesajı günlüğe kaydeder.
FailedToProcessWorkItem bir özel durum oluşursa ve oluştuğunda çağrılır:
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
using (IDisposable? scope = logger.ProcessingWorkScope(DateTime.Now))
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
WorkItem? nextItem = priorityQueue.ProcessNextHighestPriority();
if (nextItem is not null)
{
logger.PriorityItemProcessed(nextItem);
}
}
catch (Exception ex)
{
logger.FailedToProcessWorkItem(ex);
}
await Task.Delay(1_000, stoppingToken);
}
}
}
Uygulamanın konsol çıkışını inceleyin:
crit: WorkerServiceOptions.Example.Worker[13]
Epic failure processing item!
System.Exception: Failed to verify communications.
at WorkerServiceOptions.Example.Worker.ExecuteAsync(CancellationToken stoppingToken) in
..\Worker.cs:line 27
Parametreleri bir günlük iletisine geçirmek için, statik alanı oluştururken en fazla altı tür tanımlayın. Örnek uygulama, Action alanı için bir WorkItem türü tanımlayarak öğeleri işlerken iş öğesi ayrıntılarını günlüğe kaydeder.
private static readonly Action<ILogger, WorkItem, Exception> s_processingPriorityItem;
Temsilcinin log mesajı şablonu, sağlanan türlerden yer tutucu değerlerini edinir. Örnek uygulama, WorkItem öğe parametresinin olduğu bir iş öğesi eklemek için bir temsilci tanımlar.
s_processingPriorityItem = LoggerMessage.Define<WorkItem>(
LogLevel.Information,
new EventId(1, nameof(PriorityItemProcessed)),
"Processing priority item: {Item}");
Bir iş öğesinin işlendiğini günlüğe kaydetmek için kullanılan statik uzantı yöntemi, PriorityItemProcessed iş öğesi bağımsız değişken değerini alır ve bunu Action temsilcisine geçirir.
public static void PriorityItemProcessed(
this ILogger logger, WorkItem workItem) =>
s_processingPriorityItem(logger, workItem, default!);
Çalışan hizmetinin ExecuteAsync yönteminde, PriorityItemProcessed iletiyi günlüğe kaydetmek için çağrılır:
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
using (IDisposable? scope = logger.ProcessingWorkScope(DateTime.Now))
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
WorkItem? nextItem = priorityQueue.ProcessNextHighestPriority();
if (nextItem is not null)
{
logger.PriorityItemProcessed(nextItem);
}
}
catch (Exception ex)
{
logger.FailedToProcessWorkItem(ex);
}
await Task.Delay(1_000, stoppingToken);
}
}
}
Uygulamanın konsol çıkışını inceleyin:
info: WorkerServiceOptions.Example.Worker[1]
Processing priority item: Priority-Extreme (50db062a-9732-4418-936d-110549ad79e4): 'Verify communications'
Günlük düzeyinde güvenli iyileştirmeler
İlgili Log* yöntemini çağırmadan önce LogLevel öğesini ILogger.IsEnabled(LogLevel) ile denetleyerek performansı iyileştirebilirsiniz. Verilen LogLevel için günlük kaydı yapılandırılmadığında, ILogger.Log çağrılmaz. Buna ek olarak, değer türü kutulama ve object[] ayırması (parametreleri temsil etmek için) önlenir.
Daha fazla bilgi için bakınız:
- .NET çalışma zamanında mikro karşılaştırmalar
- Günlük düzeyinde denetimler için arka plan ve motivasyon