Zgodnie z dokumentacją NLog:
Większość aplikacji będzie używać jednego programu rejestrującego na klasę, gdzie nazwa programu rejestrującego jest taka sama, jak nazwa klasy.
To jest ten sam sposób, w jaki działa log4net. Dlaczego jest to dobra praktyka?
Odpowiedzi:
W log4net użycie jednego programu rejestrującego na klasę ułatwia przechwytywanie źródła komunikatu dziennika (tj. Klasy zapisującej w dzienniku). Jeśli nie masz jednego rejestratora na klasę, ale zamiast tego masz jeden rejestrator dla całej aplikacji, musisz skorzystać z większej liczby sztuczek refleksji, aby wiedzieć, skąd pochodzą komunikaty dziennika.
Porównaj następujące:
Zaloguj się na zajęcia
using System.Reflection; private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public void SomeMethod() { _logger.DebugFormat("File not found: {0}", _filename); }
Jeden rejestrator na aplikację (lub podobny)
Logger.DebugFormat("File not found: {0}", _filename); // Logger determines caller -- or -- Logger.DebugFormat(this, "File not found: {0}", _filename); // Pass in the caller
Korzystając z drugiego przykładu, Logger musiałby zbudować ślad stosu, aby zobaczyć, kto go wywołuje, lub twój kod zawsze musiałby przekazać wywołujący. W przypadku stylu rejestratora według klasy nadal to robisz, ale możesz to zrobić raz na klasę zamiast raz na wywołanie i wyeliminować poważny problem z wydajnością.
źródło
Zaleta używania "logger per file" w NLog: masz możliwość zarządzania / filtrowania logów według przestrzeni nazw i nazwy klasy. Przykład:
<logger name="A.NameSpace.MyClass" minlevel="Debug" writeTo="ImportantLogs" /> <logger name="A.NameSpace.MyOtherClass" minlevel="Trace" writeTo="ImportantLogs" /> <logger name="StupidLibrary.*" minlevel="Error" writeTo="StupidLibraryLogs" /> <!-- Hide other messages from StupidLibrary --> <logger name="StupidLibrary.*" final="true" /> <!-- Log all but hidden messages --> <logger name="*" writeTo="AllLogs" />
NLogger ma do tego bardzo przydatny fragment kodu.
nlogger
Fragment stworzy następujący kod:private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
Więc tylko kilka naciśnięć klawiszy i masz rejestrator na klasę. Użyje przestrzeni nazw i nazwy klasy jako nazwy rejestrującego. Aby ustawić inną nazwę dla swojego rejestratora klasy, możesz użyć tego:
private static NLog.Logger logger = NLog.LogManager.GetLogger("MyLib.MyName");
I, jak powiedział @JeremyWiebe, nie musisz używać sztuczek, aby uzyskać nazwę klasy, która próbuje zarejestrować wiadomość: Nazwa loggera (która zwykle jest nazwą klasy) może być łatwo zalogowana do pliku (lub inny cel) przy użyciu
${logger}
w układzie.źródło
Widzę kilka powodów takiego wyboru.
źródło
W przypadku NLog istnieje również korzyść wydajnościowa. Większość użytkowników będzie używać
Wyszukiwanie bieżącej klasy ze śledzenia stosu wymaga pewnej (ale nie dużej) wydajności.
źródło
W większości przypadków nazwa klasy stanowi dobrą nazwę dla programu rejestrującego. Podczas skanowania plików dziennika można zobaczyć komunikat dziennika i powiązać go bezpośrednio z wierszem kodu.
Dobrym przykładem, w którym nie jest to najlepsze podejście, są dzienniki SQL Hibernate. Istnieje współużytkowany program rejestrujący o nazwie „Hibernate.SQL” lub coś podobnego, w którym wiele różnych klas wypisuje surowy kod SQL do jednej kategorii rejestratora.
źródło
Z punktu widzenia programisty najłatwiej jest, jeśli nie musisz za każdym razem tworzyć obiektu rejestrującego. Z drugiej strony, jeśli tego nie zrobisz, ale raczej utworzysz ją dynamicznie za pomocą odbicia, spowolni to wydajność. Aby rozwiązać ten problem, możesz użyć następującego kodu, który tworzy rejestrator dynamicznie asynchronicznie:
using NLog; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WinForms { class log { public static async void Log(int severity, string message) { await Task.Run(() => LogIt(severity, message)); } private static void LogIt(int severity, string message) { StackTrace st = new StackTrace(); StackFrame x = st.GetFrame(2); //the third one goes back to the original caller Type t = x.GetMethod().DeclaringType; Logger theLogger = LogManager.GetLogger(t.FullName); //https://github.com/NLog/NLog/wiki/Log-levels string[] levels = { "Off", "Trace", "Debug", "Info", "Warn", "Error", "Fatal" }; int level = Math.Min(levels.Length, severity); theLogger.Log(LogLevel.FromOrdinal(level), message); } } }
źródło
Natychmiast przychodzą na myśl dwa powody:
źródło
Prawdopodobnie dlatego, że chcesz mieć możliwość rejestrowania metod, które są widoczne tylko dla klasy bez przerywania hermetyzacji, ułatwia to również korzystanie z klasy w innej aplikacji bez przerywania funkcji rejestrowania.
źródło
Ułatwia konfigurowanie programów dopisujących według przestrzeni nazw lub klas.
źródło
Jeśli używasz NLOG, możesz określić callsite w konfiguracji, to zapisze nazwę klasy i metodę, w której znajduje się instrukcja logowania.
<property name="CallSite" value="${callsite}" />
Następnie możesz użyć stałej dla nazwy programu rejestrującego lub nazwy zestawu.
Zastrzeżenie: nie wiem, w jaki sposób NLOG zbiera te informacje, przypuszczam, że będzie to refleksja, więc być może będziesz musiał rozważyć wydajność. Istnieje kilka problemów z metodami Async, jeśli nie używasz NLOG w wersji 4.4 lub nowszej.
źródło