Nlog 日志位置被代码覆盖,仍在配置位置进行日志记录

Nlog logs location overwritten by code still logging happening at config location

NLog 版本 - 4.4.3

平台 - .Net 4.5.2

当前的 NLog 配置 -

<nlog autoReload="true" xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <variable name="layout" value="${longdate}|${level:uppercase=true}|${threadid}|${logger}|${message}" />
  <variable name="logLocation" value="logs" />
  <targets async="true">
    <target name="debugger" xsi:type="Debugger" layout="${layout}" />
    <target name="console" xsi:type="Console" layout="${layout}" />
    <target name="logfile" 
            xsi:type="File" 
            fileName="${logLocation}${processname}.log" 
            archiveFileName="${logLocation}\${processname}.{###}.log" 
            archiveEvery="Day" 
            archiveAboveSize="2048000" 
            archiveNumbering="Rolling" 
            maxArchiveFiles="10" 
            concurrentWrites="false" 
            keepFileOpen="false" 
            layout="${layout}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Info" writeTo="logfile" />
    <logger name="*" minlevel="Debug" writeTo="debugger" />
    <logger name="*" minlevel="Info" writeTo="console" />
  </rules>
</nlog>

覆盖位置的代码

LogManager.ReconfigExistingLoggers();
var target = (FileTarget)LogManager.Configuration.FindTargetByName<AsyncTargetWrapper>("logfile").WrappedTarget;
target.FileName = $@"..\..\..\..\logs\Foobar.log";

您启用了自动重新加载 (<nlog autoReload="true”),因此如果它需要重新加载(在睡眠或更改配置后),您将丢失在代码中所做的更改。

解决办法是禁用自动重载,或者重载后再设置更改。参见代码示例:

static void Main(string[] args)
{
    UpdateNLogConfig();

    LogManager.ConfigurationReloaded += LogManager_ConfigurationReloaded;

    log.Info("Entering Application.");

    Console.WriteLine("Press any key to exit ...");
    Console.Read();
}


private static void LogManager_ConfigurationReloaded(object sender, LoggingConfigurationReloadedEventArgs e)
{
    UpdateNLogConfig();
}

private static void UpdateNLogConfig()
{
    //note: don't set  LogManager.Configuration because that will overwrite the nlog.config settings
    var target = (FileTarget)LogManager.Configuration.FindTargetByName<AsyncTargetWrapper>("logfile").WrappedTarget;
    target.FileName = $@"..\..\..\..\logs\Foobar.log";   
    LogManager.ReconfigExistingLoggers();
}

另见 Combine XML config with C# config · NLog/NLog Wiki

而不是进行目标查找,直接修改目标属性。然后我建议使用 NLog 布局逻辑。

<nlog autoReload="true" xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <targets async="true">
    <target name="logfile" 
            xsi:type="File" 
            fileName="${gdc:item=logFile:whenEmpty=log/${processname}.log}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Info" writeTo="logfile" />
  </rules>
</nlog>

然后只需分配 logLocation:

NLog.GlobalDiagnosticsContext.Set("logFile", $@"..\..\..\..\logs\Foobar.log");

使用 GDC 也可以很好地与 autoReload=true 一起使用,无需调用 LogManager.ReconfigExistingLoggers()