これは一種の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"/>
私の提案では、アーカイブされたファイルには、現在の日付までの「前の日付」に基づいて名前を付ける必要があると想定しています。また、ファイルが日付の変更時にロールされるという上記の事実にも依存します。したがって、「前の」日付ではなく「現在の」日付がファイル名に割り当てられます。確かに、このアプローチでは期待どおりの結果が得られない場合があります。アプリケーションが平日のみ実行される場合はどうなりますか? 月曜日に終日実行され、火曜日に最初のログが記録され、ログ ファイルがローリングされ、前日 (月曜日) の日付に基づいて名前が付けられます。それは結構です。残りの週、つまり週末までは問題ありません。プログラムが金曜日に実行されると、ログが取得されます。プログラムは週末には実行されません。月曜日に初めてメッセージがログに記録され、ログ ファイルはロールされます。この場合、前の日付は日曜日ですが、おそらく前の日付を金曜日にしたいと思います。何らかの理由で、特定の日のログがない場合もあります。翌日、ロールオーバーの原因となるログがあります。繰り返しますが、ここで説明するアプローチでは、前の日付が実際の「物理的な」前日であると判断されます。「ログが書き込まれた」前日を意味するよりも「前」を好む場合があります。
これはちょっと長くなりましたが、役に立つかもしれません。