Nlog фиксированное имя файла за сеанс приложения - PullRequest
10 голосов
/ 09 июня 2011

Я использую Nlog для входа в приложение c #. Ниже приведен раздел <targets> из моего Nlog.config:

<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 ]

10 голосов
/ 09 июня 2011

Не знаю точно, но я предполагаю, что 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>
9 голосов
/ 10 июня 2011

Очевидно, существует ${cached} средство визуализации макета, которое будет отображать макет один раз и повторно использовать его. https://github.com/nlog/nlog/wiki/Cached-Layout-Renderer

Однако, спасибо @wageoghe за ваш вклад. Ваше решение с использованием GlobalDiagnosticContext заставило меня задуматься о передаче других значений в NLog.config.

4 голосов
/ 09 января 2014

Пример использования оболочки $ {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"
/>
1 голос
/ 26 августа 2012

Я так думаю, изменяя файл журнала, указанный в файле конфигурации NLog в функции Main или в начале вашей программы.Это цель "logfile" как цель файла в файле конфигурации вашего примера.

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