NLog调用LogManager.ReconfigExistingLoggers()后日志归档保留天数未生效
问题根本原因
NLog 的 File 类型日志目标的归档类参数(包括 maxArchiveDays),在目标实例首次激活时就会对绑定的布局值做静态缓存,后续不会随全局变量的动态修改自动重新解析。
具体逻辑拆解:
- File target 的参数渲染时机:当 NLog 第一次通过某个 File target 写入日志时,会读取所有配置项,把所有用到
${}语法的布局表达式一次性渲染成固定值,存在 target 内部的私有缓存里。maxArchiveDays就属于这类会被提前固化的参数,哪怕后续你修改了对应的全局变量,已经完成初始化的 target 也不会重新读取、重新计算这个值。 LogManager.ReconfigExistingLoggers()的作用边界:这个方法只会重新匹配 logger 名称和 target 的路由映射规则,不会销毁已经创建完成的 target 实例,更不会触发 target 内部的参数缓存刷新。你调用这个方法时,之前已经生成的所有 File target 仍然保留着最早初始化时拿到的maxArchiveDays=3的缓存值,根本不会读取你后续修改的变量值。- 你验证“变量值已改为1”的操作,只是读取了全局配置字典中的变量值,这个值和已经初始化的 target 内部缓存的值是完全独立的两个存储位置,所以字典里的变量显示为1,不代表 target 真的会用这个值。
对应解决方法
- 修改变量值后,强制触发全量配置重载,而不是只调用路由重匹配方法。参考代码:
// 更新全局变量值 LogManager.Configuration.Variables["logLifetime"] = SetingFromINIfile.Setting[settingIterator++].Parameter; // 强制重新加载配置、重新初始化所有target实例 LogManager.Configuration = LogManager.Configuration.Reload(); LogManager.ReconfigExistingLoggers(); - 调整代码执行时机:把从INI文件读取日志保留时长的逻辑,挪到NLog初始化流程的最前面,等变量值确定之后再加载NLog配置、初始化target。不要等NLog已经加载完默认配置、生成了所有target实例之后,再去异步修改变量值。
- 检查NLog版本:低于4.0的老版本NLog中,
maxArchiveDays参数完全不支持动态布局表达式,必须升级到支持动态参数的版本才能实现变量驱动的配置修改。
额外提醒:不要把配置修改和重载操作放在无同步等待的异步Task里执行,NLog的初始化会在服务启动时自动触发,很容易出现异步任务还没跑完,NLog已经先完成了target初始化、缓存了旧参数值的情况,等后续修改配置时已经无法覆盖缓存值。
内容的提问来源于stack exchange,提问作者Иван Онищенко
相关产品推荐
相关产品推荐

