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";
目前的结果是什么?
当 application/service 开始时它会写入覆盖的位置,但有时(不确定场景 - 可能 翻转)它开始写入配置位置。
预期结果是什么?
日志应始终写入被覆盖的位置。
你检查过Internal log了吗?
否
请post完整的异常详细信息(消息、堆栈跟踪、内部异常)
没有例外
有什么解决方法吗? yes/no
重新启动 service/application.
有没有可以用的版本?
不知道。这是我们开始并坚持使用的版本。
你能帮我们写一个单元测试吗?
单元测试无济于事,因为它是间歇性场景。
您启用了自动重新加载 (<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();
}
而不是进行目标查找,直接修改目标属性。然后我建议使用 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()
。
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";
目前的结果是什么?
当 application/service 开始时它会写入覆盖的位置,但有时(不确定场景 - 可能 翻转)它开始写入配置位置。预期结果是什么?
日志应始终写入被覆盖的位置。你检查过Internal log了吗?
否请post完整的异常详细信息(消息、堆栈跟踪、内部异常)
没有例外有什么解决方法吗? yes/no
重新启动 service/application.有没有可以用的版本?
不知道。这是我们开始并坚持使用的版本。你能帮我们写一个单元测试吗?
单元测试无济于事,因为它是间歇性场景。
您启用了自动重新加载 (<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();
}
而不是进行目标查找,直接修改目标属性。然后我建议使用 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()
。