每个应用程序会话的Nlog固定文件名
本文关键字:文件名 Nlog 应用程序 会话 | 更新日期: 2023-09-27 17:58:42
我正在使用Nlog从我的c#应用程序登录。以下是我的Nlog.config中的<targets>
部分:
<targets>
<target name="logfile" xsi:type="File" fileName="..'logs'${date:format=yyyyMMdd_HHmmss}_trg.log"
layout="${counter} | ${date:format=yyyy-MM-dd HH':mm':ss.ffff} | ${machinename} | ${level:uppercase=true} | ${logger:shortName=true} | ${stacktrace} | ${message:exceptionSeparator=EXCEPTION:withException=true}"
keepFileOpen="true"/>
</targets>
对于filename
,我使用${date:format=yyyyMMdd_HHmmss}_trg.log
根据创建日志的时间命名日志。然而,当我的应用程序运行时,记录器每秒都会创建一个新的日志文件。如何强制Nlog修复文件名并在每个会话中只创建一个日志?
我不确定,但我的猜测是NLog根据filename属性检查日志文件的存在(由于您使用的是日期布局渲染器,所以它是动态的)。因此,由于文件名在变化(即每次检索文件名值时都不同(或可能不同)),NLog会创建一个新文件。
尝试使用这样的短期布局渲染器:
<targets>
<target name="logfile" xsi:type="File"
fileName="..'logs'${shortdate}_trg.log"
layout="${counter} | ${date:format=yyyy-MM-dd HH':mm':ss.ffff} | ${machinename} | ${level:uppercase=true} | ${logger:shortName=true} | ${stacktrace} | ${message:exceptionSeparator=EXCEPTION:withException=true}"
keepFileOpen="true"/>
</targets>
我想你会看到你的文件名不会改变(直到午夜)。
关键是,NLog将始终检查文件是否存在(根据写入日志消息时文件名的值),如果还不存在,则将创建文件。
或者,如果您想用更精确的文件名命名日志文件(即它是在某个日期某个时间创建的),那么您可以将该时间存储在GlobalDiagnosticsContext中,并使用gdc布局渲染器来帮助命名文件。类似这样的东西:
//Early in your program do something like this:
NLog.GlobalDiagnosticContext["StartTime"] = DateTime.Now.ToString("yyyyMMdd_HHmmss");
在NLog.config文件中,执行以下操作:
<targets>
<target name="logfile" xsi:type="File"
fileName="..'logs'${gdc:item=StartTime}_trg.log"
layout="${counter} | ${date:format=yyyy-MM-dd HH':mm':ss.ffff} | ${machinename} | ${level:uppercase=true} | ${logger:shortName=true} | ${stacktrace} | ${message:exceptionSeparator=EXCEPTION:withException=true}"
keepFileOpen="true"/>
</targets>
最后,您可以编写一个自定义LayoutRenderer来填充日期/时间。它会得到一次时间,然后每次都返回相同的值。
它看起来像这样:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using System.Globalization;
using NLog;
using NLog.Config;
using NLog.LayoutRenderers;
namespace MyNLogExtensions
{
[LayoutRenderer("StartTime")]
class StartTimeLayoutRenderer : LayoutRenderer
{
private DateTime start = DateTime.Now;
public StartTimeLayoutRenderer()
{
this.Format = "G";
this.Culture = CultureInfo.InvariantCulture;
}
//
// In NLog 1.x, LayoutRenderer defines a Culture property.
// In NLog 2.0, LayoutRenderer does not define a Culture property.
//
public CultureInfo Culture { get; set; }
[DefaultParameter]
public string Format { get; set; }
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
builder.Append(start.ToString(this.Format, this.Culture));
}
protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
{
return 10;
}
}
}
在你的NLog.config文件中,你需要这样的东西来告诉你的扩展名在哪里:
<extensions>
<add assembly="MyAssembly.dll"
</extensions>
然后你的目标配置看起来像这样:
<targets>
<target name="logfile" xsi:type="File"
fileName="..'logs'${StartTime:format=yyyyMMdd_HHmmss}_trg.log"
layout="${counter} | ${date:format=yyyy-MM-dd HH':mm':ss.ffff} | ${machinename} | ${level:uppercase=true} | ${logger:shortName=true} | ${stacktrace} | ${message:exceptionSeparator=EXCEPTION:withException=true}"
keepFileOpen="true"/>
</targets>
显然有一个${cached}
布局渲染器,它将渲染一次布局并重用它。https://github.com/nlog/nlog/wiki/Cached-Layout-Renderer
不过,感谢@wageoghe的参与。您使用GlobalDiagnosticContext
的解决方案让我考虑将其他值传递到NLog.config。
使用${cached}包装器的示例(https://github.com/nlog/NLog/wiki/Cached-Layout-Renderer)要创建每个应用程序会话日志文件:
<target
name="logfile"
xsi:type="File"
fileName="log-${date:cached=True:format=yyyy-MM-dd HH-mm-ss-fff}.txt"
/>
我认为这是通过更改Main函数中NLog配置文件中指定的日志文件或在程序开始时指定的。这是您的示例的配置文件中的目标"日志文件"作为文件目标。
FileTarget target = LogManager.Configuration.FindTargetByName("logfile") as FileTarget;
String logfile = "..'logs'" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + "_trg.log";
target.FileName = logfile;