调用BeginScope()时能否强制生成日志条目(无需内部显式日志命令)
问题解答
先说结论
默认情况下,不管是.NET原生的ILogger.BeginScope()还是NLog实现的版本,都不会自动生成日志条目——它本来就是用来给后续日志添加上下文信息的,并非用来触发日志输出。但不用自定义扩展类也能实现自动输出范围日志,直接靠日志框架的配置或者内置特性就行,下面以你提到的NLog为例说明:
不用扩展类的实现方法
1. 修改NLog配置,靠布局逻辑自动输出
直接在NLog的配置文件里添加判断逻辑,识别范围创建事件并输出日志:
<target name="console" xsi:type="Console"> <layout type="JsonLayout"> <attribute name="时间" layout="${longdate}" /> <attribute name="级别" layout="${level}" /> <attribute name="范围名称" layout="${scopeproperty:name=ScopeName}" /> <attribute name="消息" layout="${message}" /> <!-- 当标记了是新范围时,自动输出"范围已启动"的消息 --> <attribute name="事件类型" layout="范围已启动" when="${scopeproperty:name=IsNewScope} == 'True'" /> </layout> </target>
创建Scope的时候,传个带标记的字典告诉NLog这是新范围:
using (_logger.BeginScope(new Dictionary<string, object> { ["ScopeName"] = "SomeScope", ["IsNewScope"] = true })) { // 不用在里面写Log命令,NLog会自动输出范围启动的日志 }
2. 用NLog的全局回调触发日志
在程序启动时给NLog注册一个范围创建的回调,只要有新Scope创建,就自动打日志:
// 先把日志实例存到全局上下文里 NLog.LogManager.Configuration.GlobalDiagnosticsContext.Set("ScopeLogger", _logger); // 注册范围创建回调 NLog.LogManager.Configuration.OnScopeCreated += (scope) => { var scopeName = scope?.Properties?.GetValueOrDefault("ScopeName")?.ToString(); if (!string.IsNullOrEmpty(scopeName)) { var logger = NLog.LogManager.Configuration.GlobalDiagnosticsContext.GetLogger("ScopeLogger"); logger.LogInformation("范围已启动:{ScopeName}", scopeName); } };
之后创建Scope时,直接传带名称的匿名对象即可:
using (_logger.BeginScope(new { ScopeName = "SomeScope" })) { // 内部不用写任何Log,回调会自动输出日志 }
小提醒
- 上面的方法都是针对NLog的,如果用的是Serilog之类的其他框架,需要对应调整配置或者回调逻辑。
- 自动输出范围日志会增加日志量,建议根据实际需求控制输出级别,比如只在Debug或Info级别输出。
内容的提问来源于stack exchange,提问作者gziel
相关产品推荐
相关产品推荐

