当对象含带异常的属性时,如何使用NLog结构化日志?
问题描述
使用NLog结构化日志记录对象时触发异常:System.IO.FileNotFoundException: 'Could not find file 'C:\Non-Existent-File'.',该异常来自FileInfo的Length属性访问。需求是让NLog忽略该属性,或仅记录Bar.ToString()结果。
代码示例:
public class Foo() { public FileInfo Bar { get; set; } = new FileInfo(@"C:\Non-Existent File"); // 更多属性 } public class App { private static readonly Logger MyLogger = LogManager.GetLogger("MyLogger"); public App() { MyLogger.Info("Foo is [{@foo}]", new Foo()); } }
已尝试设置JsonLayout的MaxRecursionLimit=0,但未解决问题。
解决方案
方法1:自定义类型转换器处理FileInfo
注册自定义转换器,让NLog序列化FileInfo时仅输出路径字符串,避免访问触发异常的属性:
// 程序启动时执行注册 NLog.Config.ConfigurationItemFactory.Default.TypeConverters.RegisterConverter<FileInfo>(new FileInfoConverter()); public class FileInfoConverter : NLog.LayoutRenderers.Wrappers.TypeConverterWrapper { protected override object Convert(object value) { if (value is FileInfo fileInfo) { return fileInfo.ToString(); // 仅返回文件路径字符串 } return base.Convert(value); } }
方法2:通过配置过滤属性
排除触发异常的单个属性
在NLog配置的JsonLayout中,使用excludeProperties指定忽略FileInfo的Length属性:
<layout xsi:type="JsonLayout"> <attribute name="foo" encode="false" layout="${json-encode:${event-properties:foo}:excludeProperties=Bar.Length}" /> </layout>
手动记录Bar的字符串表示
如果不需要Bar的其他属性,直接在日志调用时传入Bar.ToString():
// 修改日志调用代码 MyLogger.Info("Foo is [Bar: {bar}, ...]", foo.Bar.ToString());
方法3:全局对象转换配置
通过NLog全局序列化配置,指定FileInfo仅序列化指定属性(如FullName),避免访问异常属性:
// 全局配置(程序启动时执行) LogManager.Setup().SetupSerialization(s => { s.RegisterObjectTransformation<FileInfo>(fileInfo => new { FullName = fileInfo.FullName }); });
内容的提问来源于stack exchange,提问作者JasonC
相关产品推荐
相关产品推荐

