C#
LoggerMessage
LoggerMessage.Define ile yüksek performanslı log öğrenirsin.
LoggerMessage.Define
Her LogInformation("...") çağrısı çalışma zamanında bir dize ayırır (allocation). Sık çağrılan yerlerde bu maliyetlidir. LoggerMessage.Define, ileti şablonunu bir kez derleyen ve yeniden kullanılan bir temsilci (delegate) döndürür.
Örnek: private static readonly Action<ILogger, string> _greet = LoggerMessage.Define<string>(LogLevel.Information, 0, "Merhaba {User}");. Sonra _greet(logger, "Ayşe") çağrısı her seferinde şablonu yeniden ayrıştırmaz; hazır temsilciyi çalıştırır.
Uygulama LoggerMessage ile yüksek performanslı günlük
Genel olmayan bir ILogger arayüzü (void LogInformation(string message)) ve ILogger<T> : ILogger arayüzü tanımla. ConsoleLogger<T> sınıfı ILogger<T>'yi uygulayıp Console.WriteLine("[INF] " + message) yapsın. Statik LoggerMessage sınıfında DefineInformation(string message) metodu Action<ILogger, string> döndürsün; döndürülen temsilci ikinci argümanı {Arg} yer tutucusunun yerine koyup LogInformation çağrısı yapsın. Main'de bir ConsoleLogger<Program> yarat, DefineInformation("Merhaba {Arg}") ile temsilciyi al ve greet(logger, "Ayşe") çağrısı yap.
Örnek çözümü göster
interface ILogger { void LogInformation(string message); } ve interface ILogger<T> : ILogger { } tanımla. class ConsoleLogger<T> : ILogger<T> { public void LogInformation(string message) => Console.WriteLine("[INF] " + message); } yaz. static class LoggerMessage { public static Action<ILogger, string> DefineInformation(string message) => (logger, arg) => logger.LogInformation(message.Replace("{Arg}", arg)); } yaz. Main'de: var logger = new ConsoleLogger<Program>(); var greet = LoggerMessage.DefineInformation("Merhaba {Arg}"); greet(logger, "Ayşe");
Örnek çözüm:
using System;
public interface ILogger
{
void LogInformation(string message);
}
public interface ILogger<T> : ILogger { }
public class ConsoleLogger<T> : ILogger<T>
{
public void LogInformation(string message) =>
Console.WriteLine("[INF] " + message);
}
public static class LoggerMessage
{
public static Action<ILogger, string> DefineInformation(string message) =>
(logger, arg) => logger.LogInformation(message.Replace("{Arg}", arg));
}
class Program
{
static void Main()
{
var logger = new ConsoleLogger<Program>();
var greet = LoggerMessage.DefineInformation("Merhaba {Arg}");
greet(logger, "Ayşe");
}
}
Temsilciyi yeniden kullan
Define ile alınan temsilci static readonly alanda saklanır. Böylece uygulama başlatıldığında bir kez üretilir, sonrasında her çağrı aynı nesneyi kullanır. Şablon ayrıştırma bir kere yapılır.
Sık çağrılan sıcak yollarda (örneğin döngü içindeki günlükler) bu yaklaşım belirgin performans kazancı verir. Seyrek çağrılan yerlerde ise doğrudan LogInformation kullanmak yeterince hızlıdır; aşırı tasarım kaçınılmalıdır.
Kendini test et
-
Define çağrısını tamamla
var greet = LoggerMessage.____("Merhaba {User}");
Cevabı göster
var greet = LoggerMessage.DefineInformation("Merhaba {User}");
-
LoggerMessage.Define neden tercih edilir?
- Daha kısa kod yazmak için
- Günlükleri renklendirmek için
- Yalnızca hataları yakalamak için
- Her çağrıda dize ayırmayı önlemek için
Cevabı göster
Her çağrıda dize ayırmayı önlemek için — Doğru. Define şablonu bir kez derler; tekrarlayan ayırmayı önler.
-
LoggerMessage kavramlarını eşleştir
- Define
- Şablonu derleyen metot
- Action<ILogger, T>
- Döndürülen temsilci
- static readonly
- Temsilciyi saklar
- {Arg}
- Yer tutucu
Sıradaki ders: Structured logging