NLog: регистрирует неправильный файл при перезагрузке

#c# #nlog

#c# #nlog

Вопрос:

У нас есть конфигурационный файл, который редактируется нашим графическим интерфейсом для динамического изменения уровня журнала нашего целевого файла.

Наше имя файла выглядит следующим образом: fileName=»${logDir}${var:subLogDir}/${var:RegionName}${logName}.dlog» Все переменные находятся в файле base .config программы, а RegionName задается динамически при запуске программы путем установки переменнойнепосредственно в конфигурации через NLog.LogManager.Конфигурация.Переменные [«RegionName»] = строка.Concat(RegionName, «/»);.

Наша проблема в том, что когда мы изменяем уровень журнала, пока программа генерирует журналы, наступает момент, когда журналы попадают в $ {var:subLogDir} напрямую, как если бы $ {var:RegionName} не был установлен, даже если мы знаем, что это так.

Похоже, что есть момент времени, когда динамические переменные еще не разрешены. Можем ли мы что-нибудь сделать, чтобы предотвратить это? Буферизация журналов при перезагрузке?

Версия NLog: 4.7.4

файл .config

 <nlog keepVariablesOnReload="true">
    <variable name="subLogDir" value="/Regions" />
    <include file="..CommonLogsBaseVariables.xml" />
    <include file="..CommonLogsBaseTargets.xml" />
    <include file="..CommonLogsBaseRules.xml" />
</nlog>
  

BaseVariables.xml

 <nlog>  
  <!-- Default variables values -->
  <variable name="logLevel" value="LogLevel.Info"/>
  <variable name="callstackLogLevel" value="LogLevel.Debug"/>
  <variable name="keepFileOpen" value="true"/>
  <variable name="autoFlush" value="true"/>
  <variable name="concurrentWrites" value="false"/>
  <variable name="hasAudit" value="false"/>
  <variable name="archiveAboveSize" value="52428800"/>
  <variable name="maxArchiveDays" value="365"/>
  <variable name="archiveNumbering" value="DateAndSequence"/>
</nlog>
  

BaseTargets.xml

 <nlog>
  <targets async="true">
    <target Type="File" name="LogFile" createDirs="true" keepFileOpen="${keepFileOpen}" autoFlush="${autoFlush}"
            fileName="${logDir}${var:subLogDir}/${var:regionName}${logName}.dlog"
            concurrentWrites="${concurrentWrites}"
            cleanupFileName="false"
            archiveFileName="${archiveLogDir}${var:subLogDir}/${var:regionName}${archiveLogName}.dlog"
            archiveEvery="${archiveEvery}" archiveAboveSize="${archiveAboveSize}"
            archiveNumbering="${archiveNumbering}" archiveDateFormat="${archiveDateFormat}" maxArchiveDays="${maxArchiveDays}">
      <layout Type="CSVLayout" delimiter="Tab" >
        <column name="date" layout="${longdate}" />
        <column name="level" layout="${uppercase:${level}}" />
        <column name="source,keywords" layout="${logger}" />
        <column name="message" layout="${message}" />
      </layout>
    </target>
   </targets>
</nlog>
  

Спасибо

Комментарии:

1. Думаю, ваш пример настолько сложен, что вам придется создать проблему для NLog-проекта и включить пример приложения, демонстрирующий проблему. github.com/NLog/NLog/issues/new/choose

Ответ №1:

Вы хотите, чтобы переменные конфигурации NLog вели себя двумя способами:

  1. При редактировании файла NLog.config он должен отбросить существующие переменные конфигурации NLog и использовать их при перезагрузке обновленного NLog.config.

    • Для этого требуется, чтобы вы настроили KeepVariablesOnReload=false (по умолчанию)

      • Было бы проще, если бы вы включили NLog.config в свой вопрос. Вместо того, чтобы угадывать.
  2. После перезагрузки NLog.config остается одна переменная конфигурации NLog ( ${var:regionName} ), которую вы хотели бы сохранить.

    • Поскольку вы настроили KeepVariablesOnReload=false (по умолчанию), я предполагаю, что вы подключились к LogManager.ConfigurationReloaded -event и переназначили его вручную.

      • Было бы проще, если бы вы включили в свой вопрос логику динамического присвоения переменной конфигурации NLog. Вместо того, чтобы угадывать.

Событие LogManager.ConfigurationReloaded -event вызывается после назначения и инициализации перезагруженной конфигурации NLog. Таким образом, любое ведение журнала происходит до тех пор, пока динамически переназначенное значение ${var:regionName} не получит пустое значение. Смотрите также https://github.com/NLog/NLog/pull/3954 и https://github.com/NLog/NLog/pull/3952

Текущий обходной путь — прекратить использование LogManager.ConfigurationReloaded -event и вместо этого просто использовать глобальный диагностический контекст NLog (GDC) для единственной переменной конфигурации NLog, которую необходимо восстанавливать при каждой перезагрузке. Таким образом, это становится ${gdc:regionName} , и вы назначаете его так (один раз при запуске):

 NLog.GlobalDiagnosticsContext.Set("regionName", "Europe");
  

Смотрите также: https://github.com/NLog/NLog/wiki/Gdc-layout-renderer

Комментарии:

1. Мы устанавливаем для keepVariablesOnReload значение true, чтобы избежать необходимости устанавливать его каждый раз, когда config.xml файл перезагружается. Вот почему я смущен поведением.

2. @cakeby Тогда я также не понимаю, как вы на самом деле меняете другие переменные NLog-config 🙂

3. @cakeby Рад, что мой ответ может помочь вам включить более подробную информацию в ваш вопрос. Вам все еще не хватает, какую версию NLog вы используете, и как / когда вы динамически обновляете regionName config-переменную.

4. @cakeby Думаю, что ваш пример настолько сложный, что вам придется создать проблему для NLog-проекта и включить пример приложения, демонстрирующий проблему. github.com/NLog/NLog/issues/new/choose

5. Использование GDC в любом случае устранило нашу проблему. Спасибо.