Serilog有一种方便的对象解构方法,如下例所示:
logger.Debug(exception, "This is an {Exception} text", exception); logger.Debug(exception, "This is an {@Exception} structure", exception);
第一行导致记录器将异常记录为纯文本(通过调用ToString()),第二行使记录器将异常属性写为单独的字段.但是这个重载呢:
logger.Debug(exception, "This is an exception", exception);
这个作为第一个参数使用异常,它总是写成一个字符串.我想要做的是以结构化的方式启用日志记录异常.是否可以配置Serilog来实现这一目标?
UPDATE.我想这个问题会导致记录异常的另一个方面:如何确保使用异常属性来丰富消息(因此它们以结构化的方式记录到富散问件,如Elasticsearch),而无需将所有异常属性写入呈现的文本消息(所以纯文本记录器没有大量的异常细节).
看一下Serilog.Exceptions日志异常详细信息和Exception.ToString()中未输出的自定义属性.
此库具有自定义代码,用于处理大多数常见异常类型的额外属性,并且只有在内部Serilog.Exceptions不支持异常时才会使用反射来获取额外信息.
添加NuGet包,然后像这样添加richher:
using Serilog; using Serilog.Exceptions; ILogger logger = new LoggerConfiguration() .Enrich.WithExceptionDetails() .WriteTo.Sink(new RollingFileSink( @"C:\logs", new JsonFormatter(renderMessage: true)) .CreateLogger();
现在,您的JSON日志将补充详细的异常信息甚至自定义异常属性.下面是从EntityFramework记录DbEntityValidationException时会发生什么的示例(此异常因深度嵌套的自定义属性而臭名昭着.ToString()
).
try { ... } catch (DbEntityValidationException exception) { logger.Error(exception, "Hello World"); }
上面的代码记录了以下内容:
{ "Timestamp": "2015-12-07T12:26:24.0557671+00:00", "Level": "Error", "MessageTemplate": "Hello World", "RenderedMessage": "Hello World", "Exception": "System.Data.Entity.Validation.DbEntityValidationException: Message", "Properties": { "ExceptionDetail": { "EntityValidationErrors": [ { "Entry": null, "ValidationErrors": [ { "PropertyName": "PropertyName", "ErrorMessage": "PropertyName is Required.", "Type": "System.Data.Entity.Validation.DbValidationError" } ], "IsValid": false, "Type": "System.Data.Entity.Validation.DbEntityValidationResult" } ], "Message": "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.", "Data": {}, "InnerException": null, "TargetSite": null, "StackTrace": null, "HelpLink": null, "Source": null, "HResult": -2146232032, "Type": "System.Data.Entity.Validation.DbEntityValidationException" }, "Source": "418169ff-e65f-456e-8b0d-42a0973c3577" } }
Serilog.Exceptions支持.NET标准并支持许多常见的异常类型而没有反射但我们想添加更多,所以请随时贡献.
您可以使用Ben.Demystifier NuGet包为您的异常获取人类可读的堆栈跟踪,或者如果您使用Serilog,则可以使用serilog -enrichers-demystify NuGet包.
有一个讨论这个的论坛帖子,其中提出了几个解决方案.Thomas Bolon创建了一个你可以在Gist中找到的"异常解构"扩展.
在这种情况下,您只使用以下语法:
logger.Debug(exception, "This is an exception");
无需将异常添加到格式字符串中.
要确保将异常打印到文本接收器,请确保{Exception}
包含在输出模板中.标准内置的已经有了这个,例如:
outputTemplate: "{Timestamp} [{Level}] {Message}{NewLine}{Exception}";