我不知道有一种方法可以很容易地做到这一点。话虽如此,您提供的所有示例都可以添加到每个日志消息中(或者通过一些自定义代码相当容易获得)。也就是说,每条记录的消息都可以通过 Layout 和 LayoutRenderers 标记为可执行名称、文件版本、发布日期、Windows 用户 ID 等。
这显然与仅在日志文件顶部创建标头不同,因此它可能对您没有用处。
另一方面,您可以使用 Pat在本文中的回答中提到的技术将多个布局渲染器与同一目标相关联。您可以定义一个布局,其中包含您在标题中需要的字段,并在 FilteringWrapper 中设置过滤器以仅将该布局应用于会话的第一条消息(或者您可以使用将其添加到输出文件的其他技术只有一次)。
使用他的 NLog.config 文件,这是您可以实现所需的一种方法。请注意,我没有尝试过这个,所以我不知道这个配置文件是否有效,或者如果是,它是否会生成你想要的结果。
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.mono2.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Warn"
internalLogFile="nlog log.log"
>
<variable name="HeaderLayout" value="${processname} ${gdc:item=version} ${gdc:item=releasedate} ${windows-identity}" />
<variable name="NormalLayout" value="${longdate} ${logger} ${level} ${message} />
<targets async="true">
<target name="file" xsi:type="File" fileName="log.log"
layout="${NormalLayout}">
</target>
<target name="fileHeader" xsi:type="File" fileName="log.log"
layout="${HeaderLayout}">
</target>
</targets>
<rules>
<logger name="HeaderLogger" minlevel="Trace" writeTo="fileHeader" final="true" />
<logger name="*" minlevel="Trace" writeTo="file" />
</rules>
</nlog>
在您的代码中,您的启动逻辑可能如下所示:
public void Main()
{
AddHeaderToLogFile();
}
public void AddHeaderToLogFile()
{
Logger headerlogger = LogManager.GetLogger("HeaderLogger");
//Use GlobalDiagnosticContext in 2.0, GDC in pre-2.0
GlobalDiagnosticContext["releasedate"] = GetReleaseDate();
GlobalDiagnosticContext["version"] = GetFileVersion();
GlobalDiagnosticContext["someotherproperty"] = GetSomeOtherProperty();
headerlogger.Info("message doesn't matter since it is not specified in the layout");
//Log file should now have the header as defined by the HeaderLayout
//You could remove the global properties now if you are not going to log them in any
//more messages.
}
这里的想法是在程序启动时将文件版本、发布日期等放入 GDC。使用“HeaderLogger”记录器记录消息。该消息将使用“HeaderLayout”写入日志文件,因为“HeaderLogger”与“fileHeader”目标相关联,该目标与“HeaderLayout”相关联。标题布局中定义的字段将写入日志文件。后续日志消息,因为它们不会使用“HeaderLogger”,所以将使用“root”(*) 布局。它们将转到同一个文件,因为“file”和“fileHeader”目标最终都指向同一个文件名。
在我开始输入此响应之前,我不确定您是否可以轻松地将标头添加到日志文件中。输入了这个,我认为它实际上可能很容易!
祝你好运!
[编辑] 这样的事情可能会根据级别更改布局。在第一节中,我定义了几个变量,每个变量都定义了一个布局。在下一节中,我定义了几个目标,每个目标都使用相同的文件,但被过滤为只允许写入特定级别的消息。在最后一节中,我定义了一个规则,它将所有消息(因此是“*”记录器名称)发送到所有目标。由于每个目标都按级别过滤,“trace”目标将只写入“trace”消息等。因此,“trace”消息将使用“trace”布局编写,“debug”消息将使用“debug”编写布局等。由于所有目标最终都写入同一个文件,因此所有消息最终都会在同一个文件中。这个我没试过
<variable name="TraceLayout" value="THIS IS A TRACE: ${longdate} ${level:upperCase=true} ${message}" />
<variable name="DebugLayout" value="THIS IS A DEBUG: ${longdate} ${level:upperCase=true} ${message}" />
<variable name="InfoLayout" value="THIS IS AN INFO: ${longdate} ${level:upperCase=true} ${message}" />
<targets async="true">
<target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace">
<target xsi:type="File" fileName="log.log" layout="${TraceLayout}" />
</target>
<target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug">
<target xsi:type="File" fileName="log.log" layout="${DebugLayout}" />
</target>
<target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info">
<target xsi:type="File" fileName="log.log" layout="${InfoLayout}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="fileAsTrace, fileAsDebug, fileAsInfo" />
</rules>
(请注意,我在这里只包括了 3 个级别)。
展示了如何(如果可行的话)基于关卡应用不同的布局,这似乎是一个不寻常的用例。我并不是说这是一个好主意或一个坏主意,但我不能说我真的非常看到这样做。根据您希望最终输出的具体外观,我向您展示的内容可能是实现它的最佳方式,也可能不是。也许您可以发布一些示例来说明您希望输出的外观。
您也可以考虑接受我的原始答案,然后提出一个关于改变每个级别的输出布局的新问题,以便我们可以将该问题的讨论集中在级别/布局问题上。这是否有用取决于您。
这有效:
<variable name="TraceLayout" value="This is a TRACE - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="DebugLayout" value="This is a DEBUG - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="InfoLayout" value="This is an INFO - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="WarnLayout" value="This is a WARN - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="ErrorLayout" value="This is an ERROR - ${longdate} | ${logger} | ${level} | ${message}"/>
<variable name="FatalLayout" value="This is a FATAL - ${longdate} | ${logger} | ${level} | ${message}"/>
<targets>
<target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace">
<target xsi:type="File" fileName="xxx.log" layout="${TraceLayout}" />
</target>
<target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug">
<target xsi:type="File" fileName="xxx.log" layout="${DebugLayout}" />
</target>
<target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info">
<target xsi:type="File" fileName="xxx.log" layout="${InfoLayout}" />
</target>
<target name="fileAsWarn" xsi:type="FilteringWrapper" condition="level==LogLevel.Warn">
<target xsi:type="File" fileName="xxx.log" layout="${WarnLayout}" />
</target>
<target name="fileAsError" xsi:type="FilteringWrapper" condition="level==LogLevel.Error">
<target xsi:type="File" fileName="xxx.log" layout="${ErrorLayout}" />
</target>
<target name="fileAsFatal" xsi:type="FilteringWrapper" condition="level==LogLevel.Fatal">
<target xsi:type="File" fileName="xxx.log" layout="${FatalLayout}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="fileAsTrace,fileAsDebug,fileAsInfo,fileAsWarn,fileAsError,fileAsFatal" />
<logger name="*" minlevel="Info" writeTo="dbg" />
</rules>
我为每个日志级别设置了一个布局,在开头添加了一个描述消息级别的文字字符串(这是为了显示每个级别使用不同的格式)。每个 Layout 都与一个 FilteringWrapper 相关联,该 FilteringWrapper 根据消息的级别进行过滤,并将通过过滤器的任何消息引导到输出文件中。每个 FilteringWrapper 都包装同一个输出文件,因此所有日志消息都将记录到同一个文件中。
这是我用于测试的一段代码:
logger.Trace("Trace msg");
logger.Debug("Debug msg");
logger.Info("Info msg");
logger.Warn("Warn msg");
logger.Error("Error msg");
logger.Fatal("Fatal msg");
这是输出的样子:
This is a TRACE - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Trace | Trace msg
This is a DEBUG - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Debug | Debug msg
This is an INFO - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Info | Info msg
This is a WARN - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Warn | Warn msg
This is an ERROR - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Error | Error msg
This is a FATAL - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Fatal | Fatal msg
显然,我之前的配置信息中的问题是"writeTo"
值之间的空间。我猜 NLog 对此很敏感。"writeTo=blah1, blah2, blah3".
当我将其更改为"writeTo=blah1,blah2,blah3"
错误消失时,我有类似的东西。祝你好运!