Log exception details and custom properties that are not output in Exception.ToString().
Serilog.Exceptions is an add-on to Serilog to log exception details and custom properties that are not output in
Exception.ToString().
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
DbEntityValidationExceptionfrom 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" } }
Add the Serilog.Exceptions NuGet package to your project using the NuGet Package Manager or run the following command in the Package Console Window:
dotnet add package Serilog.Exceptions
When setting up your logger, add the
WithExceptionDetails()line like so:
using Serilog; using Serilog.Exceptions;ILogger logger = new LoggerConfiguration() .Enrich.WithExceptionDetails() .WriteTo.RollingFile( new JsonFormatter(renderMessage: true), @"C:\logs\log-{Date}.txt")
.CreateLogger();
Make sure that the sink's formatter outputs enriched properties.
Serilog.Sinks.Consoleand many more do not do that by default. You may need to add
{Properties:j}to your sink's format template. For example, configuration for console sink may look like that:
.WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception} {Properties:j}")
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. Reflection overhead is present but minimal, because all the expensive relection-based operations are done only once per exception-type.
Add the Serilog.Exceptions.SqlServer NuGet package to your project to avoid the reflection based destructurer for
SqlExceptionwhen using System.Data.SqlClient:
Install-Package Serilog.Exceptions.SqlServer
Add the
SqlExceptionDestructurerduring setup:
csharp .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithDestructurers(new[] { new SqlExceptionDestructurer() }))
Add the Serilog.Exceptions.MsSqlServer NuGet package to your project to avoid the reflection based destructurer for
SqlExceptionwhen using Microsoft.Data.SqlClient:
Install-Package Serilog.Exceptions.MsSqlServer
Add the
SqlExceptionDestructurerduring setup:
csharp .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithDestructurers(new[] { new SqlExceptionDestructurer() }))
WARNING: If you are using EntityFrameworkCore with Serilog.Exceptions you must add this, otherwise in certain cases your entire database will be logged! This is because the exceptions in Entity Framework Core have properties that link to the entire database schema in them (See #100, aspnet/EntityFrameworkCore#15214)
Add the Serilog.Exceptions.EntityFrameworkCore NuGet package to your project when using EntityFrameworkCore in your project
Install-Package Serilog.Exceptions.EntityFrameworkCore
Add the
DbUpdateExceptionDestructurerduring setup:
csharp .Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithDestructurers(new[] { new DbUpdateExceptionDestructurer() }))
You may want to add support for destructuring your own exceptions without relying on reflection. To do this, create your own destructuring class implementing
ExceptionDestructurer(You can take a look at this for
ArgumentException), then simply add it like so:
.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithDestructurers(new[] { new MyCustomExceptionDestructurer() }))
If you write a destructurer that is not included in this project (even for a third party library), please contribute it.
You can configure some additional properties of destructuring process, by passing custom destructuring options during setup:
.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithRootName("Exception"))
Currently following options are supported:
RootName: The property name which will hold destructured exception,
ExceptionDetailby default.
Filter: The object implementing
IExceptionPropertyFilterthat will have a chance to filter properties just before they are put in destructured exception object. Go to "Filtering properties" section for details.
DestructuringDepth: The maximum depth of reflection based recursive destructuring process.
ReflectionBasedDestructurer: Reflection based destructurer is enabled by default, but can be disabled in case you want to have complete control over destructuring process. You will have to register destructurers for all exceptions explicitly.
You may want to skip some properties of all or part your exception classes without directly creating or modifying custom destructurers. Serilog.Exceptions supports this functionality using a filter.
Most typical use case is the need to skip
StackTraceand
TargetSite. Serilog is already reporting them so you may want Serilog.Exceptions to skip them to save space and processing time. To do that you just need to modify a line in configuration:
.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder().WithFilter(someFilter));
Filtering for other scenarios is also supported:
WithIgnoreStackTraceAndTargetSiteExceptionFilterif you need to filter some other set of named properties
IExceptionPropertyFilterif you need some different filtering logic
CompositeExceptionPropertyFilterto combine multiple filters
| Name | Operating System | Status | History |
| :--- | :--- | :--- | :--- |
| Azure Pipelines | Ubuntu | |
| Azure Pipelines | Mac |
|
| Azure Pipelines | Windows |
|
| Azure Pipelines | Overall |
|
|
| GitHub Actions | Ubuntu, Mac & Windows |
|
|
| AppVeyor | Ubuntu, Mac & Windows |
|
|
Please view the contributing guide for more information.