每个应用会话的Nlog固定文件名

时间:2011-06-09 13:17:21

标签: c# logging filenames nlog

我正在使用Nlog从我的c#app登录。以下是我的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修复文件名,每个会话只创建一个日志?

4 个答案:

答案 0 :(得分:10)

我不确定,但我的猜测是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将始终检查文件是否存在(根据写入日志消息时文件名的值),如果存在,将创建文件还不存在。

或者,如果要使用更精确的文件名命名日志文件(即它是在某个时间某个时间创建的),那么您可以将该时间存储在GlobalDiagnosticContext中并使用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>

答案 1 :(得分:9)

显然有一个${cached}布局渲染器,它将渲染一次布局并重复使用它。 https://github.com/nlog/nlog/wiki/Cached-Layout-Renderer

但是,感谢@wageoghe的输入。使用GlobalDiagnosticContext的解决方案让我考虑将其他值传递给NLog.config。

答案 2 :(得分:4)

使用$ {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"
/>

答案 3 :(得分:1)

我认为这样可以通过更改Main函数或程序开头的NLog配置文件中指定的日志文件。这是目标“logfile”作为示例配置文件中的文件目标。

FileTarget target = LogManager.Configuration.FindTargetByName("logfile") as FileTarget;
String logfile = "..\logs\" +  DateTime.Now.ToString("yyyyMMdd_HHmmss") + "_trg.log";
target.FileName = logfile;