2013-06-12 23 views
3

Я хочу использовать архивирование, чтобы ограничить количество файлов журнала, и я хочу, чтобы имя файла каждого архивного журнала являлось датой, в которой находится журнал. Достаточно просто.NLog некорректная дата при архивации

Это одна из моих целей:

<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-06-12, а затем, когда оно будет архивировано завтра, оно будет помещено в файл с именем 2013-06-13.log.

Есть any Способ получения правильной даты? Я видел, как кто-то предлагал переменную, но я не вижу, как это будет работать ... Это похоже на такую ​​очевидную функцию. Он должен определенно быть одним из режимов archiveNumbering! Доступные теперь режимы нумерации кажутся настолько непрактичными по сравнению с датами.

Этот вопрос относится к Delete log files after x days. Если бы было возможно установить максимальное количество файлов журнала (потому что это то, что я действительно хочу от функции архивирования), не используя функцию архивирования, это было бы даже лучше, потому что мне не пришлось бы использовать {#}, но я подозревать, что это невозможно.

ответ

0

Это может считаться видом подхода Rube Goldberg, но это может сработать ... Вы можете написать собственный LayoutRenderer, который вычисляет «предыдущую» дату. Параметром для этого LayoutRenderer будет параметр «archiveEvery» из вашей целевой конфигурации.

Использование ShortDateLayoutRenderer в качестве основы ...

(Взято из хранилища мерзавца NLog в ...)

[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"/> 

Мое предложение предполагает, что архивный файл должен быть назван на основе «предыдущей даты» к текущей дате. Это также зависит от того, что вы упомянули выше, что файл скатывается при изменении даты, поэтому присвоение «текущей» даты имени файла, а не «предыдущей» дате. Конечно, есть случаи, когда такой подход может не дать результатов, которые вы, возможно, захотите. Что делать, если ваше приложение работает только по будням? Он работает весь день в понедельник, затем с первым входом во вторник файл журнала журнала и называется в соответствии с датой предыдущего дня (понедельник). Это нормально.Это нормально для остальной части недели, то есть до выходных. Когда программа запускается в пятницу, записываются журналы. Программа не работает в выходные дни. В понедельник при первом входе в журнал регистрируется файл журнала. В этом случае предыдущая дата будет в воскресенье, когда вы, вероятно, предпочтете, чтобы предыдущая дата была в пятницу. Также может случиться так, что по какой-либо причине в течение определенного дня нет журналов. На следующий день появляется журнал, который вызывает опрокидывание. Опять же, описанный мной подход определит, что предыдущая дата будет фактическим «физическим» предыдущим днем, когда вы можете предпочесть «предыдущий» означать предыдущий день «когда были записаны какие-либо журналы».

Это стало длинным, но, может быть, вы найдете его полезным.

+1

Мое приложение будет использоваться только в рабочее время, так как вы говорите сами, просто получение предыдущего дня не полностью решает его. Тем не менее, ваш пост по-прежнему полезен. Я могу сделать LayoutRenderer, который получает текущее имя журнала, тогда, если я назову текущий журнал с датой, все должно получиться. – moggizx

+0

Мой подход также может быть изменен, чтобы ограничить «предыдущие» дни от недели до недели. Таким образом, когда файл журнала будет загружаться в понедельник, он выяснит, что «предыдущий» день - пятница. Такое поведение может быть жестко запрограммировано или может контролироваться настройкой конфигурации. – wageoghe

+0

Извините, мне просто кажется, что если вы не можете доверять дате, тогда нет смысла ее иметь. Мой подход не работает, поскольку архивирование вообще не работает для журналов с динамическими именами файлов. Я подозреваю, что это потому, что он попытается найти журнал с настроенным именем журнала при архивировании, и если он изменился с момента создания текущего файла журнала, он не найдет его и, следовательно, не сможет его архивировать ... I решили отказаться от этого, но спасибо за вашу помощь! – moggizx

Смежные вопросы