Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception destructuring in Serilog

Serilog has a convenient way of destructuring objects as shown in this example:

logger.Debug(exception, "This is an {Exception} text", exception); logger.Debug(exception, "This is an {@Exception} structure", exception); 

The first line causes the logger to log an exception as plain text (by calling ToString()), and the second line causes the logger to write exception properties as separate fields. But what about this overload:

logger.Debug(exception, "This is an exception", exception); 

This one takes an exception as its first argument, and it is always written as a string. What I would like to make possible is to enable logging exception in a structured way. Is it possible to configure Serilog to achieve this?

UPDATE. I guess this question leads to another aspect of logging exceptions: how can I ensure that messages are enriched with exception properties (so they are logged in a structured way to the rich sinks like Elasticsearch) without writing all exception properties to the rendered text message (so plain text loggers are not filled with huge piles of exception details).

like image 544
Vagif Abilov Avatar asked Aug 15 '14 08:08

Vagif Abilov


People also ask

Does Serilog throw exceptions?

Exceptions is an add-on to Serilog to log exception details and custom properties that are not output in Exception.

How do I log exception with Serilog?

Debug(exception, "This is an {Exception} text", exception); logger. Debug(exception, "This is an {@Exception} structure", exception); The first line causes the logger to log an exception as plain text (by calling ToString()), and the second line causes the logger to write exception properties as separate fields.

What is enrich in Serilog?

Log Context enricher - Built in to Serilog, this enricher ensures any properties added to the Log Context are pushed into log events. Environment enrichers - Enrich logs with the machine or current user name.


1 Answers

Take a look at Serilog.Exceptions logs exception details and custom properties that are not output in Exception.ToString().

This library has custom code to deal with extra properties on most common exception types and only falls back to using reflection to get the extra information if the exception is not supported by Serilog.Exceptions internally.

Add the NuGet package and then add the enricher like so:

using Serilog; using Serilog.Exceptions;  ILogger logger = new LoggerConfiguration()     .Enrich.WithExceptionDetails()     .WriteTo.Sink(new RollingFileSink(         @"C:\logs",         new JsonFormatter(renderMessage: true))     .CreateLogger(); 

Your JSON logs will now be supplemented with detailed exception information and even custom exception properties. Here is an example of what happens when you log a DbEntityValidationException from EntityFramework (This exception is notorious for having deeply nested custom properties which are not included in the .ToString()).

try {     ... } catch (DbEntityValidationException exception) {     logger.Error(exception, "Hello World"); } 

The code above logs the following:

{   "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 supports the .NET Standard and supports many common exception types without reflection but we'd like to add more, so please feel free to contribute.

Top Tip - Human Readable Stack Traces

You can use the Ben.Demystifier NuGet package to get human readable stack traces for your exceptions or the serilog-enrichers-demystify NuGet package if you are using Serilog.

like image 158
Muhammad Rehan Saeed Avatar answered Oct 03 '22 11:10

Muhammad Rehan Saeed