我想使用归档来限制日志文件的数量,我希望每个归档日志的文件名都是日志的日期。很简单。
这是我的目标之一:
<target xsi:type="File" name="info" fileName="${basedir}/logs/info.log"
layout="${date:format=HH\:mm\:ss}	|	${uppercase:${level}}	|	${message}"
archiveEvery="Day"
archiveFileName="${basedir}/logs/archive/info/${shortdate}.{#}.log"
archiveNumbering="Rolling"
maxArchiveFiles="30"/>
我已经读过你必须在archiveFileName中拥有{#},否则当你在文件名中有日期时归档将根本不起作用,这有点令人讨厌,但我想我可以忍受。
但是,由于日期更改后执行归档,$ {shortdate}将始终成为新日的日期,即一天(或更多)在期望的日期之后。如果今天记录了一条消息,2013-06-12,那么当它明天存档时,它将被放置在一个名为2013-06-13.log的文件中。
是否有任何方式来获取正确的日期?我看到有人建议变量,但我不知道它会如何工作......这看起来就像是一个显而易见的特征。它肯定是archiveNumbering模式之一!与日期相比,现在可用的编号模式似乎是不切实际的。
这个问题与Delete log files after x days有关。如果可以在不使用归档功能的情况下设置最大日志文件数(因为这是我真正想要的归档功能),那实际上会更好,因为我也不必使用{#},但我怀疑是不可能的。
答案 0 :(得分:1)
NLog自此发布此问题后添加了编号格式“日期”,这正是我所寻找的。 p>
有关详细信息,请参阅https://github.com/nlog/NLog/wiki/File-target#archival-options。
答案 1 :(得分:0)
这可能被认为是一种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}	|	${uppercase:${level}}	|	${message}"
archiveEvery="Day"
archiveFileName="${basedir}/logs/archive/info/${previousdate{shortdate,"Day"}}.{#}.log"
archiveNumbering="Rolling"
maxArchiveFiles="30"/>
我的建议假设应根据当前日期的“上一个日期”命名归档文件。它还取决于您在上面提到的文件在日期更改时滚动的事实,因此将“当前”日期分配给文件名而不是“上一个”日期。当然,这种方法可能无法提供您可能想要的结果。如果您的应用程序仅在工作日运行,该怎么办?它在星期一全天运行,然后在星期二的第一个日志中滚动日志文件并根据前一天(星期一)的日期命名。那样就好。一周的剩余时间,也就是周末,这是好的。由于程序在星期五运行,因此会捕获日志。该计划不会在周末运行。星期一,第一次记录消息时,将滚动日志文件。在这种情况下,上一个日期将是星期日,您可能希望上一个日期是星期五。也可能是因为某种原因,某一天没有日志。第二天有一个日志,导致翻转。同样,我描述的方法将确定前一个日期是实际的“实际”前一天,当您可能更喜欢“之前”表示前一天“当有任何日志写入时”。
这已经有点长了,但也许你会发现它很有用。