這可能被認爲是Rube Goldberg方法的一種,但它可能有效......您可以編寫計算「上一個」日期的自定義LayoutRenderer。此LayoutRenderer的參數將是目標配置中的「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可能是這個樣子: (請注意,我既沒有編制也沒有測試過這段代碼,但我之前編寫過LayoutRenderer)。
[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,將適用非常類似的邏輯,但它會被傳遞一個字符串(即包裝會嘗試解釋爲日期),希望從減去所需的時間跨度。
給出的包裝,因爲我以上簡要描述的,它可能會像下面這樣配置:
<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"/>
我的建議假定歸檔文件應基於「以前的日期」爲當前日期來命名。這也取決於你上面提到的事實,即文件是在日期改變時滾動的,因此將「當前」日期分配給文件名而不是「上一個」日期。當然有些情況下這種方法可能不會給出你想要的結果。如果您的應用程序僅在平日運行,該怎麼辦?它週一整天運行,然後在週二的第一個日誌中日誌文件滾動並根據前一天(星期一)的日期命名。沒事兒。在本週的其餘時間,也就是週末前,這很好。當程序在星期五運行時,會記錄日誌。該計劃不會在週末結束。在星期一,第一次記錄消息時,日誌文件將被滾動。在這種情況下,前一個日期將是星期日,您可能更希望前一個日期是星期五。也可能出現這樣的情況,無論出於何種原因,某一天都沒有日誌。第二天有一個日誌,導致翻滾。同樣,我描述的方法將確定之前的日期是實際的「實際」前一天,當您可能更喜歡「上一個」來表示前一天「當有任何日誌寫入時」。
這已經得到了很長的一段時間,但也許你會發現它很有用。
我的申請只會在辦公時間內使用,所以如你所說,只是在前一天獲得並不能完全解決問題。不過,您的帖子仍然有幫助。我可以製作一個獲取當前日誌名稱的LayoutRenderer,然後如果我用當前日誌命名,它應該全部解決。 – moggizx
我的方法也可以修改,以限制「前一天」的工作日。所以,當日志文件在星期一推出時,它會發現「前一天」是星期五。這種行爲可能是硬編碼的,或者可以通過配置設置來控制。 – wageoghe
對不起,我只是覺得如果你不能相信日期,那就沒有意義了。我的方法不起作用,因爲歸檔對於具有動態文件名的日誌根本不起作用。我懷疑這是因爲它會在歸檔時嘗試使用配置的日誌名稱查找日誌,並且如果自從創建當前日誌文件以來它已經發生更改,那麼它將不會找到它並因此無法將其歸檔... I已決定放棄這一點,但感謝你的幫助! – moggizx