如何基于全局日志级别配置NLog的日志输出目标?
WPF中NLog按全局配置级别输出到对应文件的实现方案
问题场景
在WPF应用里想用NLog,根据appconfig.json里的全局日志级别输出日志:
- 默认设为Debug级别时,把Debug到Fatal的日志都写到
log-debug.txt - 切换成Trace级别时,把Trace到Fatal的所有日志写到
log-trace.txt
之前配了两条NLog规则,结果日志被拆到两个文件里,不符合需求——要的是切换级别后,对应文件能包含该级别及以上的完整日志,不是分开存。
推荐方案:用NLog变量关联全局配置(无需维护多目标)
这种方式不用搞两个文件目标,靠NLog的变量动态关联配置里的日志级别,自动切换文件名和输出级别,简洁高效。
1. 修改appconfig.json配置
把全局日志级别和NLog配置绑定,用变量实现动态切换:
{ "settings": { "logLevel": "Debug" // 可选值:Debug/Trace }, "NLog": { "internalLogLevel": "Info", "autoReload": true, "variables": { "globalLogLevel": "${configsetting:name=settings.logLevel}", "logFileName": "${when:when='${globalLogLevel}' == 'Trace':inner=log-trace.txt:else=log-debug.txt}" }, "targets": { "logfile": { "type": "File", "fileName": "${logFileName}", "layout": "${longdate}|${level}|${message}|${exception:format=tostring}" }, "logconsole": { "type": "Debugger", "layout": "${longdate}|${level}|${message}|${exception:format=tostring}" } }, "rules": [ { "logger": "*", "minLevel": "${globalLogLevel}", "writeTo": "logfile,logconsole" } ] } }
2. 调整代码里的日志配置
代码里不用硬写日志级别,只要确保Microsoft.Extensions.Logging的最低级别不限制NLog的输出就行:
serviceCollection.AddLogging(builder => { builder.ClearProviders(); // 设为Trace避免过滤掉NLog要处理的日志 builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); builder.AddNLog(); });
改完之后,修改settings.logLevel的值,重启应用(或者开了autoReload等配置自动刷新),NLog就会自动切换到对应日志文件,输出该级别及以上的所有日志,不会拆分文件。
备选方案:代码动态修改NLog规则(支持运行时切换)
如果需要在应用运行时切换日志级别不用重启,就用这种方式,直接通过代码修改NLog的目标和规则:
1. 简化appconfig.json配置
只保留一个文件目标,规则留默认值后期代码修改:
{ "settings": { "logLevel": "Debug" }, "NLog": { "internalLogLevel": "Info", "autoReload": true, "targets": { "logfile": { "type": "File", "fileName": "log.txt", // 文件名后期代码改 "layout": "${longdate}|${level}|${message}|${exception:format=tostring}" }, "logconsole": { "type": "Debugger", "layout": "${longdate}|${level}|${message}|${exception:format=tostring}" } }, "rules": [ { "logger": "*", "minLevel": "Debug", // 默认级别,后期代码改 "writeTo": "logfile,logconsole" } ] } }
2. 代码里读取配置并调整NLog
// 读取配置里的日志级别 var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appconfig.json") .Build(); var globalLogLevelStr = config["settings:logLevel"]; var globalLogLevel = Enum.Parse<NLog.LogLevel>(globalLogLevelStr, ignoreCase: true); // 配置Logging serviceCollection.AddLogging(builder => { builder.ClearProviders(); builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); builder.AddNLog(); }); // 修改NLog的文件目标和规则 var nLogConfig = NLog.LogManager.Configuration; // 切换日志文件名 var fileTarget = nLogConfig.FindTargetByName<FileTarget>("logfile"); fileTarget.FileName = globalLogLevel == NLog.LogLevel.Trace ? "log-trace.txt" : "log-debug.txt"; // 切换规则的最低输出级别 var rule = nLogConfig.LoggingRules.First(r => r.LoggerNamePattern == "*"); rule.SetLoggingLevels(globalLogLevel, NLog.LogLevel.Fatal); // 重载NLog配置生效 NLog.LogManager.Configuration = nLogConfig;
这样就能在运行时动态切换日志级别,不用重启应用。
内容的提问来源于stack exchange,提问作者Ari Roth
相关产品推荐
相关产品推荐

