4

The package Serilog.Exceptions is nice for logging exceptions. It has a large list of supported exception types.

e.g. the current setup:

Log.Logger = new LoggerConfiguration()
    .Enrich.WithExceptionDetails()
    .CreateLogger();

Currently it falls back to a "reflection based destructurer" if no destructurer is found for a exception type.

Because of performance, but more important of predictability, we would like to disable the reflection fallback.

I tried configuring this with DestructuringOptions, e.g. disable some of the default destructors or setting the DestructuringDepth to 0.

Unfortunately, those options won't work:

  • the ReflectionBasedDestructurer isn't in the default destructor list
  • setting DestructuringDepth to 0 isn't allowed (exception)

Any idea how to configure Serilog.Exceptions for this?

Julian
  • 33,915
  • 22
  • 119
  • 174

2 Answers2

2

I think the best option you have is to implement your own ExceptionDecostructor, something like this:

 public class FallbackExceptionDestructurer : ExceptionDestructurer
 {
        public override Type[] TargetTypes => new[]
        {
            typeof(Exception),
        };

        public override void Destructure(
            Exception exception,
            IExceptionPropertiesBag propertiesBag,
            Func<Exception, IReadOnlyDictionary<string, object>> destructureException)
        {
            base.Destructure(exception, propertiesBag, destructureException);
        }
 }

This way you will keep all the available destructurers and the reflection based will be ignored because FallbackExceptionDestructurer will cover all unknown exceptions due to this code:

public override Type[] TargetTypes => new[]
{
  typeof(Exception),
};

This is how you are registering destructurers

.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder()
    .WithDefaultDestructurers()
    .WithDestructurers(new[] { new FallbackExceptionDestructurer () }))

If you check the source code of the ExceptionDestructurer.Decostruct(...) it does not use any reflection - only well known properties from the Exception type.

vasil oreshenski
  • 2,788
  • 1
  • 14
  • 21
2

This has been added to Serilog.Exceptions 5.4.0, see changelog. There is a new method WithoutReflectionBasedDestructurer.

Usage

Helper class

public static class LoggerEnrichmentConfigurationExtensions
{
    public static LoggerConfiguration WithExceptionDetailsWithoutReflection(
        this LoggerEnrichmentConfiguration loggerEnrichmentConfiguration)
    {
        if (loggerEnrichmentConfiguration is null)
        {
            throw new ArgumentNullException(nameof(loggerEnrichmentConfiguration));
        }
        var options = new DestructuringOptionsBuilder()
            .WithDefaultDestructurers()
            .WithoutReflectionBasedDestructurer() //new in 5.4.0!
            .WithIgnoreStackTraceAndTargetSiteExceptionFilter();
        var logEventEnricher = new ExceptionEnricher(options);
        return loggerEnrichmentConfiguration.With(logEventEnricher);
    }
}

Config

Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration)
                .Enrich.WithExceptionDetailsWithoutReflection()
                .CreateLogger();
Julian
  • 33,915
  • 22
  • 119
  • 174