如何在NLog中实现作用域标题、缩进及时长统计?
NLog实现作用域生命周期日志与缩进格式
需求说明
需要在NLog中实现以下日志效果:
- 每个作用域创建时输出带创建时间的标题
- 作用域结束时输出包含持续时长的收尾信息
- 根据作用域深度对日志内容自动缩进
- 不希望自行包装
BeginScope的IDisposable,优先使用NLog原生功能实现
代码示例
using (_logger.BeginScope("Starting processing")) { _logger.LogInformation("Algorithm1 Initialized"); _logger.LogInformation("Algorithm2 Initialized"); using (_logger.BeginScope("Algorithm 1 running")) { for (int i=0; i<5; i++) _logger.LogInformation($"Algorithm1 progress {i}"); } using (_logger.BeginScope("Algorithm 2 running")) { for (int i = 0; i < 5; i++) _logger.LogInformation($"Algorithm2 progress {i}"); } }
期望输出
Starting processing (Started: XX:XX:XX.XXX) Algorithm1 Initialized Algorithm2 Initialized Algorithm 1 running (Started: XX:XX:XX.XXX) Algorithm1 progress 0 Algorithm1 progress 1 Algorithm1 progress 2 Algorithm1 progress 3 Algorithm1 progress 4 Algorithm 1 running finished in 00:00:10 Algorithm 2 running (Started: XX:XX:XX.XXX) Algorithm2 progress 0 Algorithm2 progress 1 Algorithm2 progress 2 Algorithm2 progress 3 Algorithm2 progress 4 Algorithm 2 running finished in 00:00:10 Starting processing finished in 00:00:XX
实现方案
1. NLog配置文件设置
通过NLog原生布局渲染器实现需求,关键用到:
${scopeindent}:根据作用域深度生成缩进(默认每个层级4个空格,可自定义)${scopetiming}:输出作用域的生命周期信息,包含开始时间和持续时长${scopemessage}:获取当前作用域的消息内容
完整NLog.config配置示例
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <targets> <target name="console" xsi:type="Console"> <!-- 普通日志格式:缩进 + 日志内容 --> <layout type="CompositeLayout"> <layout type="SimpleLayout" text="${scopeindent}" /> <layout type="SimpleLayout" text="${message}" /> </layout> <!-- 作用域开始/结束的专用格式 --> <scope-activity-layout type="CompositeLayout"> <layout type="SimpleLayout" text="${scopeindent}" /> <layout type="SimpleLayout" text="${scopemessage}" /> <!-- 作用域开始时追加启动时间 --> <layout type="SimpleLayout" text="${when:when='${scopetiming:format=Started}' != '':inner= (Started: ${date:format=HH\\:mm\\:ss.fff})}" /> <!-- 作用域结束时追加持续时长 --> <layout type="SimpleLayout" text="${when:when='${scopetiming:format=Elapsed}' != '':inner= finished in ${scopetiming:format=hh\\:mm\\:ss}}" /> </scope-activity-layout> </target> </targets> <rules> <!-- 输出普通业务日志 --> <logger name="*" minlevel="Info" writeTo="console" /> <!-- 启用作用域活动日志,自动输出开始/结束事件 --> <logger name="*" minlevel="Trace" writeTo="console" scope="Activity" /> </rules> </nlog>
2. 关键配置说明
scope-activity-layout:专门处理作用域的创建和结束事件,NLog会在调用BeginScope时自动输出启动信息,在作用域Dispose时自动输出结束信息(包含时长)${scopeindent}:自动根据当前作用域层级生成缩进,可通过${scopeindent:indentSize=2}自定义每个层级的缩进字符数${scopetiming}:通过format参数区分场景,Started返回启动时间,Elapsed返回持续时长,搭配${when}渲染器实现条件输出- 作用域活动日志规则:必须添加
scope="Activity"的日志规则,确保NLog捕获并输出作用域生命周期事件
3. 代码调整说明
无需修改原有业务代码,保持BeginScope的原生调用即可。NLog会自动处理作用域的开始/结束日志输出,同时为普通日志自动添加对应层级的缩进。
内容的提问来源于stack exchange,提问作者msedi
相关产品推荐
相关产品推荐

