根据NLog的文档:
大多数应用程序每个类将使用一个记录器,其中记录器的名称与类的名称相同。
这与log4net的运行方式相同。为什么这是个好习惯?
Answers:
使用log4net,每个类使用一个记录器可以轻松捕获日志消息的源(即,类写入日志)。如果每个班级没有一个记录器,而整个应用程序只有一个记录器,那么您需要采取更多的反射技巧来了解日志消息的来源。
比较以下内容:
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
使用第二个示例,记录器将需要构建堆栈跟踪以查看谁在调用它,否则您的代码将始终必须传入调用者。仍然使用每类记录器样式,您仍然可以执行此操作,但是您可以在每个类中执行一次操作,而不是在每个调用中执行一次操作,从而消除了严重的性能问题。
在NLog中使用“每个文件记录器”的优点:您可以按名称空间和类名称来管理/过滤日志。例:
<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有一个非常有用的代码片段来执行此操作。该nlogger
代码段将创建以下代码:
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
因此,只有几次击键,并且每个班级都有记录器。它将使用名称空间和类名称作为记录器的名称。要为类记录器设置不同的名称,可以使用以下命令:
private static NLog.Logger logger = NLog.LogManager.GetLogger("MyLib.MyName");
而且,正如@JeremyWiebe所说的,您不必使用技巧来获取尝试记录消息的类的名称:记录器的名称(通常是类的名称)可以很容易地记录到文件中。 (或其他目标)通过${logger}
在版式中使用。
在大多数情况下,类的名称为记录器提供了很好的名称。扫描日志文件时,您可以看到日志消息并将其直接与一行代码关联。
一个不是最佳方法的好例子是Hibernate的SQL日志。有一个名为“ Hibernate.SQL”或类似名称的共享记录器,其中许多不同的类将原始SQL写入单个记录器类别。
从开发角度来看,最简单的方法是不必每次都创建一个logger对象。另一方面,如果不这样做,而是使用反射来动态创建它,则会降低性能。为了解决这个问题,您可以使用以下代码以异步方式动态创建记录器:
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);
}
}
}