NLog belgelerine göre:
Çoğu uygulama, sınıf başına bir kaydedici kullanır; burada günlükçünün adı, sınıfın adıyla aynıdır.
Bu, log4net'in çalışmasıyla aynıdır. Bu neden iyi bir uygulama?
NLog belgelerine göre:
Çoğu uygulama, sınıf başına bir kaydedici kullanır; burada günlükçünün adı, sınıfın adıyla aynıdır.
Bu, log4net'in çalışmasıyla aynıdır. Bu neden iyi bir uygulama?
Yanıtlar:
Log4net ile, sınıf başına bir kaydedici kullanmak, günlük mesajının kaynağını (yani günlüğe yazan sınıf) yakalamayı kolaylaştırır. Sınıf başına bir kaydediciniz yoksa, bunun yerine tüm uygulama için tek bir kaydediciniz varsa, günlük mesajlarının nereden geldiğini bilmek için daha fazla yansıtma hilesine başvurmanız gerekir.
Aşağıdakileri karşılaştırın:
using System.Reflection;
private static readonly ILog _logger =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public void SomeMethod()
{
_logger.DebugFormat("File not found: {0}", _filename);
}
Logger.DebugFormat("File not found: {0}", _filename); // Logger determines caller
-- or --
Logger.DebugFormat(this, "File not found: {0}", _filename); // Pass in the caller
İkinci örneği kullanarak, Logger'ın kimin aradığını görmek için bir yığın izleme oluşturması veya kodunuzun her zaman arayanı iletmesi gerekir. Sınıf başına kaydedici stiliyle bunu yine de yaparsınız, ancak bunu çağrı başına bir kez yapmak yerine sınıf başına bir kez yapabilir ve ciddi bir performans sorununu ortadan kaldırabilirsiniz.
NLog'da "dosya başına günlük kaydedici" kullanmanın avantajı: günlükleri ad alanına ve sınıf adına göre yönetme / filtreleme olanağınız vardır. Misal:
<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, bunu yapmak için çok kullanışlı bir kod parçacığına sahiptir. nlogger
Pasajı aşağıdaki kodu oluşturur:
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
Yani yalnızca birkaç tuş vuruşu ve sınıf başına günlük kaydediciniz var. Kaydedicinin adı olarak ad alanını ve sınıf adını kullanacaktır. Sınıf kaydedicinize farklı bir ad ayarlamak için şunu kullanabilirsiniz:
private static NLog.Logger logger = NLog.LogManager.GetLogger("MyLib.MyName");
Ve @JeremyWiebe'nin dediği gibi, bir mesajı günlüğe kaydetmeye çalışan sınıfın adını almak için hileler kullanmak zorunda değilsiniz: Kaydedicinin adı (genellikle sınıfın adıdır) kolayca dosyaya kaydedilebilir (veya başka bir hedef) ${logger}
düzende kullanarak .
Bu seçim için birkaç neden görebiliyorum.
Çoğu durumda, sınıfın adı kaydedici için iyi bir ad sağlar. Günlük dosyalarını tararken, günlük mesajını görebilir ve bunu doğrudan bir kod satırıyla ilişkilendirebilirsiniz.
Bunun en iyi yaklaşım olmadığı iyi bir örnek, Hibernate'in SQL günlükleridir. "Hibernate.SQL" veya buna benzer bir adında paylaşılan bir kaydedici var, burada bir dizi farklı sınıf tek bir günlükçü kategorisine ham SQL yazıyor.
Geliştirme açısından, her seferinde bir kaydedici nesnesi oluşturmanız gerekmiyorsa en kolayıdır. Öte yandan, yapmazsanız, daha ziyade yansıma kullanarak dinamik olarak yaratırsanız, performansı yavaşlatacaktır. Bunu çözmek için, günlükçüyü dinamik olarak eşzamansız olarak oluşturan aşağıdaki kodu kullanabilirsiniz:
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);
}
}
}
Akla hemen iki neden geliyor:
Muhtemelen, kapsüllemeyi bozmadan yalnızca sınıf tarafından görülebilen yöntemleri günlüğe kaydedebilmek istediğiniz için, bu, günlük işlevini bozmadan sınıfı başka bir uygulamada kullanmayı da kolaylaştırır.
NLOG kullanıyorsanız, çağrı sitesini yapılandırmada belirtebilirsiniz, bu, günlük ifadesinin bulunduğu sınıf adını ve yöntemi kaydeder.
<property name="CallSite" value="${callsite}" />
Daha sonra kaydedici adınız veya derleme adınız için bir sabit kullanabilirsiniz.
Sorumluluk reddi: NLOG'un bu bilgileri nasıl topladığını bilmiyorum, benim tahminim yansıma olacaktır, bu yüzden performansı değerlendirmeniz gerekebilir. NLOG v4.4 veya sonraki bir sürümünü kullanmıyorsanız Async yöntemleriyle ilgili birkaç sorun vardır.