/// <summary> /// Enrich logger output with a destuctured object containing /// exception's public properties. Default destructurers are registered. /// <see cref="Exception.StackTrace"/> and <see cref="Exception.TargetSite"/> are omitted /// by the destructuring process because Serilog already attaches them to log event. /// </summary> /// <param name="loggerEnrichmentConfiguration">The enrichment configuration</param> /// <returns>Configuration object allowing method chaining.</returns> public static Serilog.LoggerConfiguration WithExceptionDetails( this LoggerEnrichmentConfiguration loggerEnrichmentConfiguration) { var options = new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithIgnoreStackTraceAndTargetSiteExceptionFilter(); var logEventEnricher = new ExceptionEnricher(options); return(loggerEnrichmentConfiguration.With(logEventEnricher)); }
public void WithoutReflectionBasedDestructurer_CustomExceptionIsNotLogged() { // Arrange var exception = new DictNonScalarKeyException(); var options = new DestructuringOptionsBuilder().WithoutReflectionBasedDestructurer(); // Act var rootObject = LogAndDestructureException(exception, options); // Assert rootObject.Properties().Should().NotContain(x => x.Name == "Properties"); }
/// <summary> /// Enrich logger output with a destuctured object containing exception's public properties. Default /// destructurers are registered. <see cref="Exception.StackTrace"/> and Exception.TargetSite /// are omitted by the destructuring process because Serilog already attaches them to log event. /// </summary> /// <param name="loggerEnrichmentConfiguration">The enrichment configuration.</param> /// <returns>Configuration object allowing method chaining.</returns> public static LoggerConfiguration WithExceptionDetails( this LoggerEnrichmentConfiguration loggerEnrichmentConfiguration) { if (loggerEnrichmentConfiguration is null) { throw new ArgumentNullException(nameof(loggerEnrichmentConfiguration)); } var options = new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithIgnoreStackTraceAndTargetSiteExceptionFilter(); var logEventEnricher = new ExceptionEnricher(options); return(loggerEnrichmentConfiguration.With(logEventEnricher)); }
public void WithoutReflectionBasedDestructurerAndCustomRootName_StandardExceptionIsLogged() { // Arrange var exception = new ArgumentException("ARG", "arg"); var options = new DestructuringOptionsBuilder() .WithDefaultDestructurers() .WithoutReflectionBasedDestructurer() .WithRootName("CUSTOM-ROOT"); // Act var rootObject = LogAndDestructureException(exception, options); // Assert var exceptionObject = ExtractExceptionDetails(rootObject, "CUSTOM-ROOT"); var paramObject = exceptionObject.Properties().Should().ContainSingle(x => x.Name == "ParamName").Which; paramObject.Value.Should().BeOfType <JValue>().Which.Value.Should().Be("arg"); }
private static void ConfigureLogger(HostBuilderContext hostBuilderContext, LoggerConfiguration loggerConfiguration) { if (Debugger.IsAttached) { // allow serilog warnings to show when running in debug // see https://github.com/serilog/serilog/wiki/Debugging-and-Diagnostics // if you're having issues with serilog in some environments (sandbox/uat/prod) consider enabling this Serilog.Debugging.SelfLog.Enable(Console.Error); } // setup your serilog logger configuration // the configuration below is just an example, you should configure it as it fits your use case var jsonValueFormatter = new JsonValueFormatter(typeTagName: null); //passing null removes $type from being added to all serialized objects var jsonFormatter = new CompactJsonFormatter(jsonValueFormatter); var exceptionDetailsDeconstructorers = new DestructuringOptionsBuilder().WithDefaultDestructurers(); loggerConfiguration.ReadFrom.Configuration(hostBuilderContext.Configuration) .Destructure.UsingAttributes() .Enrich.FromLogContext() .Enrich.WithExceptionDetails(exceptionDetailsDeconstructorers) .Enrich.WithMachineName() .Enrich.WithEnvironmentName() .WriteTo.Console(jsonFormatter); }