NLog:重新加载时登录错误的文件

NLog: Logs in wrong file on reload

我们有一个配置文件,由我们的 GUI 编辑以动态更改我们的文件目标的日志级别。

我们的文件名如下所示:fileName="${logDir}${var:subLogDir}/${var:regionName}${logName}.dlog" 所有变量都在程序的基本 .config 文件中,并且在程序启动时通过设置动态设置 regionName 通过 NLog.LogManager.Configuration.Variables["regionName"] = string.Concat(RegionName, "/");.

直接在配置中变量

我们的问题是当我们在程序生成日志的时候修改日志级别,会有一个时刻日志会直接落到${var:subLogDir}中,就好像${var:regionName}是即使我们知道它也没有设置。

似乎有一段时间动态变量还没有解决。我们可以做些什么来防止这种情况发生吗?重新加载时缓冲日志?

NLog 版本:4.7.4

.config 文件

<nlog keepVariablesOnReload="true">
    <variable name="subLogDir" value="/Regions" />
    <include file="..\Common\Logs\BaseVariables.xml" />
    <include file="..\Common\Logs\BaseTargets.xml" />
    <include file="..\Common\Logs\BaseRules.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>

谢谢

您希望 NLog 配置变量以两种方式运行:

  1. 当编辑 NLog.config 文件时,它应该丢弃现有的 NLog 配置变量并在重新加载更新的 NLog.config.

    时使用这些变量
    • 这需要您配置KeepVariablesOnReload=false(默认)

      • 如果您在问题中包含 NLog.config 会更容易。而不是猜测。
  2. 重新加载 NLog.config 后,有一个 NLog 配置变量 (${var:regionName}) 您想要保留。

    • 因为您已经配置了 KeepVariablesOnReload=false(默认),所以我猜您已经连接到 LogManager.ConfigurationReloaded-事件并手动重新分配它。

      • 如果您在问题中包含了动态分配 NLog 配置变量的逻辑,那就更容易了。而不是猜测。

LogManager.ConfigurationReloaded-事件在重新加载的 NLog 配置被分配和初始化后被调用。因此,在动态重新分配 ${var:regionName} 之前发生的任何日志记录都将获得空值。另见 https://github.com/NLog/NLog/pull/3954 and 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