【问题标题】:NLog incorrect date when archiving归档时 NLog 日期不正确
【发布时间】:2013-06-08 12:42:27
【问题描述】:

我想使用归档来限制日志文件的数量,并且我希望每个归档日志的文件名都是日志的起始日期。很简单。

这是我的目标之一:

<target xsi:type="File" name="info" fileName="${basedir}/logs/info.log"
        layout="${date:format=HH\:mm\:ss}&#009;|&#009;${uppercase:${level}}&#009;|&#009;${message}"
        archiveEvery="Day"
        archiveFileName="${basedir}/logs/archive/info/${shortdate}.{#}.log"
        archiveNumbering="Rolling"
        maxArchiveFiles="30"/>

我已经读到您必须在archiveFileName 中包含{#},否则当您在文件名中包含日期时,归档将根本不起作用,这有点烦人,但我想我可以忍受。

但是,由于归档是在日期更改后 执行的,${shortdate} 将始终成为 天的日期,即一天(或更多)在所需日期之后。如果今天(2013 年 6 月 12 日)记录了一条消息,那么当它明天存档时,它将被放置在一个名为 2013-06-13.log 的文件中。

有没有任何方法可以得到正确的日期?我见过有人建议一个变量,但我不明白它是如何工作的……这似乎是一个如此明显的特性。它应该绝对是archiveNumbering模式之一!与日期相比,现在可用的编号模式似乎太不切实际了。

这个问题与Delete log files after x days 有点相关。如果可以在不使用存档功能的情况下设置最大日志文件数(因为这是我真正想要的存档功能),那实际上会更好,因为我也不必使用 {#},但我怀疑这是不可能的。

【问题讨论】:

    标签: date nlog archiving


    【解决方案1】:

    NLog 自发布此问题以来添加了编号格式“日期”,这正是我所寻找的。​​p>

    更多信息请参见https://github.com/nlog/NLog/wiki/File-target#archival-options

    【讨论】:

      【解决方案2】:

      这可能被认为是一种Rube Goldberg 方法,但它可能会起作用...您可以编写一个自定义 LayoutRenderer 来计算“先前”日期。此 LayoutRenderer 的参数将是 Target 配置中的“archiveEvery”设置。

      使用 ShortDateLayoutRenderer 作为基础...

      (取自 NLog 的 git 存储库...)

      [LayoutRenderer("shortdate")]
      [ThreadAgnostic]
      public class ShortDateLayoutRenderer : LayoutRenderer
      {
          /// <summary>
          /// Gets or sets a value indicating whether to output UTC time instead of local time.
          /// </summary>
          /// <docgen category='Rendering Options' order='10' />
          [DefaultValue(false)]
          public bool UniversalTime { get; set; }
      
          /// <summary>
          /// Renders the current short date string (yyyy-MM-dd) and appends it to the specified <see cref="StringBuilder" />.
          /// </summary>
          /// <param name="builder">The <see cref="StringBuilder"/> to append the rendered data to.</param>
          /// <param name="logEvent">Logging event.</param>
          protected override void Append(StringBuilder builder, LogEventInfo logEvent)
          {
              var ts = logEvent.TimeStamp;
              if (this.UniversalTime)
              {
                  ts = ts.ToUniversalTime();
              }
      
              builder.Append(ts.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
          }
      }
      

      PreviousDateLayoutRenderer 可能看起来像这样: (注意我没有编译也没有测试过这段代码,但是我之前写过LayoutRenderers)。

      [LayoutRenderer("previousdate")]
      [ThreadAgnostic]
      public class PreviousDateLayoutRenderer : LayoutRenderer
      {
          /// <summary>
          /// Gets or sets a value indicating whether to output UTC time instead of local time.
          /// </summary>
          /// <docgen category='Rendering Options' order='10' />
          [DefaultValue(false)]
          public bool UniversalTime { get; set; }
      
          /// <summary>
          /// Gets or sets the value indicating the unit of time to subtract to get previous date.
          /// </summary>
          [DefaultValue("Day")]
          public string TimeUnit { get; set; }
      
          /// <summary>
          /// Gets the current date, subtracts one TimeUnit, renders the resulting short date string,
          /// then appends it to the specified <see cref="StringBuilder" />.
          /// </summary>
          /// <param name="builder">The <see cref="StringBuilder"/> to append the rendered data to.</param>
          /// <param name="logEvent">Logging event.</param>
          protected override void Append(StringBuilder builder, LogEventInfo logEvent)
          {
              var ts = logEvent.TimeStamp;
              if (this.UniversalTime)
              {
                  ts = ts.ToUniversalTime();
              }
      
              // This could certainly be better.  Probably smarter to put code in the setter of the
              // TimeUnit property to compute a TimeSpan member variable that could then be subtracted
              // in this method rather than check the TimeUnit and compute the TimeSpan every time.
      
              TimeSpan span;
      
              switch (TimeUnit)
              {
                case "Day":
                  span = TimeSpan.FromDays(1);
                  break;
                case "Hour":
                  span = TimeSpan.FromHours(1);
                  break;
              }
      
              ts -= span;
      
              builder.Append(ts.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
          }
      }
      

      或者,您可以编写一个 LayoutRendererWrapper,它会应用非常相似的逻辑,但它会被传递一个字符串(包装器会尝试将其解释为日期)并从中减去所需的 TimeSpan。

      给定我上面简要描述的包装器,它可能被配置为:

      <target xsi:type="File" name="info" fileName="${basedir}/logs/info.log"
              layout="${date:format=HH\:mm\:ss}&#009;|&#009;${uppercase:${level}}&#009;|&#009;${message}"
              archiveEvery="Day"
              archiveFileName="${basedir}/logs/archive/info/${previousdate{shortdate,"Day"}}.{#}.log"
              archiveNumbering="Rolling"
              maxArchiveFiles="30"/>
      

      我的建议假定归档文件应根据当前日期的“上一个日期”命名。这也有点取决于您上面提到的事实,即文件在日期更改时滚动,因此将“当前”日期分配给文件名而不是“上一个”日期。在某些情况下,这种方法可能无法提供您可能想要的结果。如果您的应用程序只在工作日运行怎么办?它在星期一全天运行,然后在星期二的第一个日志中滚动日志文件并根据前一天(星期一)的日期命名。没事儿。本周剩下的时间,也就是直到周末,这都很好。当程序在星期五运行时,会捕获日志。该程序不会在周末运行。星期一,第一次记录消息时,会滚动日志文件。在这种情况下,前一个日期将是星期日,而您可能希望前一个日期是星期五。也可能是由于某种原因,某一天没有日志。第二天有一个日志,导致翻转。同样,我描述的方法会将前一天确定为实际的“物理”前一天,此时您可能更喜欢“前一天”来表示前一天“有任何日志写入时”。

      这已经有点长了,但也许你会发现它很有用。

      【讨论】:

      • 我的应用程序只会在办公时间使用,所以正如你自己所说,仅仅获得前一天并不能完全解决它。但是,您的帖子仍然很有帮助。我可以制作一个获取当前日志名称的 LayoutRenderer,然后如果我用日期命名当前日志,它应该会全部解决。
      • 我的方法也可以修改为限制“以前的”工作日到工作日。因此,当日志文件在星期一滚动时,它会发现“前一天”是星期五。此行为可以是硬编码的,也可以由配置设置控制。
      • 对不起,我只是觉得如果你不能相信日期,那么拥有它是没有意义的。我的方法也不起作用,因为归档对于具有动态文件名的日志根本不起作用。我怀疑这是因为它会在归档时尝试使用配置的日志名称查找日志,并且如果自当前日志文件创建以来这已更改,那么它将找不到它,因此无法归档它......我已决定放弃,但感谢您的帮助!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多