如何配置NLog目标的Layout以获取异常的原始序列化数据?
获取NLog中异常的原始序列化数据
好问题!默认的${exception:format=toString,Data}会输出格式化后的字符串,丢失了异常对象的原始结构和类型信息。要获取类似Visual Studio异常窗口里的原始数据结构,你可以试试以下几种配置方式:
方法1:用JsonLayout序列化完整异常对象
这是最直接的方式,NLog的JsonLayout可以直接将异常对象序列化为JSON,保留所有原始属性(包括嵌套的内部异常、Data字典的键值对等)。
示例配置:
<target name="jsonExceptionTarget" xsi:type="File" fileName="exceptions-raw.json"> <layout xsi:type="JsonLayout"> <!-- 序列化完整异常对象,自动包含所有属性 --> <attribute name="RawException" encode="false"> <layout xsi:type="JsonLayout" includeAllProperties="true" maxRecursionLimit="10" /> </attribute> <!-- 可选:添加其他日志元数据 --> <attribute name="Timestamp" value="${date:format=o}" /> <attribute name="LogLevel" value="${level}" /> </layout> </target>
如果需要更精细控制要包含的属性,也可以手动指定:
<attribute name="RawException" encode="false"> <layout xsi:type="JsonLayout" maxRecursionLimit="10"> <property name="ExceptionType" value="${exception:format=Type}" /> <property name="Message" value="${exception:format=Message}" /> <property name="StackTrace" value="${exception:format=StackTrace}" /> <property name="Data" value="${exception:format=Data}" /> <property name="InnerExceptions" value="${exception:format=InnerException:maxInnerExceptionLevel=10}" /> </layout> </attribute>
这种方式生成的JSON结构和Visual Studio异常窗口展示的原始数据几乎一致,能保留所有类型信息(比如Data里的数值、布尔值不会被转成字符串)。
方法2:自定义布局渲染器实现完全控制
如果需要更灵活的序列化逻辑(比如用Newtonsoft.Json而非System.Text.Json,或者自定义序列化规则),可以写一个自定义NLog布局渲染器:
using NLog; using NLog.LayoutRenderers; using System.Text.Json; [LayoutRenderer("exception-raw")] public class RawExceptionLayoutRenderer : LayoutRenderer { protected override void Append(StringBuilder builder, LogEventInfo logEvent) { if (logEvent.Exception == null) return; var serializerOptions = new JsonSerializerOptions { WriteIndented = true, ReferenceHandler = ReferenceHandler.IgnoreCycles, // 处理循环引用 MaxDepth = 10 // 匹配你的maxInnerExceptionLevel设置 }; var rawJson = JsonSerializer.Serialize(logEvent.Exception, serializerOptions); builder.Append(rawJson); } }
然后在NLog配置中注册这个扩展,并使用${exception-raw}:
<extensions> <!-- 替换成你的程序集名称 --> <add assembly="YourApplicationAssembly" /> </extensions> <target name="rawExceptionTarget" xsi:type="File" fileName="raw-exceptions.log"> <layout>${date:format=yyyy-MM-dd HH:mm:ss} - ${exception-raw}</layout> </target>
注意事项
- 记得设置
maxRecursionLimit或maxInnerExceptionLevel来避免因深层嵌套异常导致的序列化问题。 - 如果使用JsonLayout,
encode="false"很重要,否则JSON会被转义成字符串,失去原始结构。
内容的提问来源于stack exchange,提问作者Bram Van Den Bossche
相关产品推荐
相关产品推荐

