Coder Social home page Coder Social logo

rehansaeed / serilog.exceptions Goto Github PK

View Code? Open in Web Editor NEW
479.0 13.0 50.0 931 KB

Log exception details and custom properties that are not output in Exception.ToString().

License: MIT License

C# 99.03% HTML 0.97%
serilog nuget logging exception reflection dotnet dotnet-core c-sharp

serilog.exceptions's Introduction

Serilog.Exceptions Banner

Serilog.Exceptions NuGet Package Serilog.Exceptions package in serilog-exceptions feed in Azure Artifacts Serilog.Exceptions NuGet Package Downloads Twitter URL Twitter Follow

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

What Does It Do?

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"
  }
}

Getting Started

Warning Entity Framework Core Users: If you are using Entity Framework with Serilog.Exceptions you should read the following instructions.

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.Console and 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}")

JSON appSettings.json configuration

Alternatively to fluent configuration setting can be stored in application configuration using Serilog.Settings.Configuration:

{
  "Serilog": {
    "Using": [ "Serilog.Exceptions" ],
    "Enrich": [ "WithExceptionDetails" ],
    "WriteTo": [
      { "Name": "Console" }
    ]
  }
}

Performance

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.

Additional Destructurers

Serilog.Exceptions.SqlServer

Serilog.Exceptions.SqlServer NuGet Package Serilog.Exceptions.SqlServer package in serilog-exceptions feed in Azure Artifacts Serilog.Exceptions.SqlServer NuGet Package Downloads

Add the Serilog.Exceptions.SqlServer NuGet package to your project to avoid the reflection based destructurer for SqlException when using System.Data.SqlClient:

dotnet add package Serilog.Exceptions.SqlServer

Add the SqlExceptionDestructurer during setup:

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

Serilog.Exceptions.MsSqlServer

Serilog.Exceptions.MsSqlServer NuGet Package Serilog.Exceptions.MsSqlServer package in serilog-exceptions feed in Azure Artifacts Serilog.Exceptions.MsSqlServer NuGet Package Downloads

Add the Serilog.Exceptions.MsSqlServer NuGet package to your project to avoid the reflection based destructurer for SqlException when using Microsoft.Data.SqlClient:

dotnet add package Serilog.Exceptions.MsSqlServer

Add the SqlExceptionDestructurer during setup:

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

Serilog.Exceptions.EntityFrameworkCore

Serilog.Exceptions.EntityFrameworkCore NuGet Package Serilog.Exceptions.EntityFrameworkCore package in serilog-exceptions feed in Azure Artifacts Serilog.Exceptions.EntityFrameworkCore NuGet Package Downloads

Warning If you are using Entity Framework with Serilog.Exceptions you must follow the instructions below, otherwise in certain cases your entire database will be logged! This is because the exceptions in Entity Framework have properties that link to the entire database schema in them (See #100, aspnet/EntityFrameworkCore#15214). Version 8 or newer of Serilog.Exceptions reduces the problem by preventing the destructure of properties that implement IQueryable but the rest of the DbContext object will still get logged.

Add the Serilog.Exceptions.EntityFrameworkCore NuGet package to your project when using EntityFrameworkCore in your project

dotnet add package Serilog.Exceptions.EntityFrameworkCore

Add the DbUpdateExceptionDestructurer during setup:

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

Serilog.Exceptions.Refit

Serilog.Exceptions.Refit NuGet Package Serilog.Exceptions.Refit package in serilog-exceptions feed in Azure Artifacts Serilog.Exceptions.Refit NuGet Package Downloads

Add the Serilog.Exceptions.Refit NuGet package to your project to provide detailed logging for the ApiException when using Refit:

dotnet add package Serilog.Exceptions.Refit

Add the ApiExceptionDestructurer during setup:

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

Depending on your Serilog setup, common System.Exception properties may already be logged. To omit the logging of these properties, use the overloaded constructor as follows:

.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder()
    .WithDefaultDestructurers()
    .WithDestructurers(new[] { new ApiExceptionDestructurer(destructureCommonExceptionProperties: false) }))

The default configuration logs the following properties of an ApiException:

  • Uri
  • StatusCode

In addition, the ApiException.Content property can be logged with the following setup:

.Enrich.WithExceptionDetails(new DestructuringOptionsBuilder()
    .WithDefaultDestructurers()
    .WithDestructurers(new[] { new ApiExceptionDestructurer(destructureHttpContent: true) }))

Be careful with this option as the HTTP body could be very large and/or contain sensitive information.

Serilog.Exceptions.Grpc

Serilog.Exceptions.Grpc NuGet Package Serilog.Exceptions.Grpc package in serilog-exceptions feed in Azure Artifacts Serilog.Exceptions.Grpc NuGet Package Downloads

Add the Serilog.Exceptions.Grpc NuGet package to your project to avoid the reflection based destructurer for RpcException when using Grpc.Net.Client:

dotnet add package Serilog.Exceptions.Grpc

Add the RpcExceptionDestructurer during setup:

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

Custom Exception Destructurers

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.

Additional configuration

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, ExceptionDetail by default.
  • Filter: The object implementing IExceptionPropertyFilter that 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.

Filtering properties

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 StackTrace and 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:

  • Use WithIgnoreStackTraceAndTargetSiteExceptionFilter if you need to filter some other set of named properties
  • Implement custom IExceptionPropertyFilter if you need some different filtering logic
  • Use CompositeExceptionPropertyFilter to combine multiple filters

Continuous Integration

Name Operating System Status History
Azure Pipelines Ubuntu Azure Pipelines Ubuntu Build Status
Azure Pipelines Mac Azure Pipelines Mac Build Status
Azure Pipelines Windows Azure Pipelines Windows Build Status
Azure Pipelines Overall Azure Pipelines Overall Build Status Azure DevOps Build History
GitHub Actions Ubuntu, Mac & Windows GitHub Actions Status GitHub Actions Build History
AppVeyor Ubuntu, Mac & Windows AppVeyor Build Status AppVeyor Build History

Contributions and Thanks

Please view the contributing guide for more information.

  • 304NotModified - Added Markdown syntax highlighting.
  • joelweiss - Added Entity Framework Core destructurers.
  • krajek & JeroenDragt - For adding filters to help ignore exception properties you don't want logged.
  • krajek - For helping with cyclic dependencies when using the reflection destructurer.
  • mraming - For logging properties that throw exceptions.
  • optical - For a huge VS 2017 upgrade PR.
  • Jรฉrรฉmie Bertrand - For making Serilog.Exceptions compatible with Mono.
  • krajek - For writing some much needed unit tests.

serilog.exceptions's People

Contributors

304notmodified avatar arphox avatar billhally avatar codingmoh avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar driedas avatar heavyoranjs avatar ikopytko avatar joelweiss avatar krajek avatar mraming avatar mrtristan avatar olsh avatar optical avatar rahulpnath avatar rehansaeed avatar renovate-bot avatar renovate[bot] avatar ricosuter avatar shatl avatar simoncropp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

serilog.exceptions's Issues

Question: when following the example from the readme: no extra ExceptionDetails in the log

The example as explained in Readme.md is not working for me, no extra information is shown.
I made a little testprogram (see attached TestSeri.zip), using serilog v2.3 and Serilog.Exceptions v2.2.1 (installed via NuGet) and EntityFramework 6.1.3.
In that program I use the following structure taken from the Readme.md:
try { ... } catch (DbEntityValidationException exception) { logger.Error(exception, "Hello World"); }

But I see no additional information, for example

{ "Timestamp": "2016-11-08T10:21:32.0619281+01:00", "Level": "Error", "MessageTemplate": "Hello World", "RenderedMessage": "Hello World", "Exception": "System.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.\r\n at System.Data.Entity.Internal.InternalContext.SaveChanges()\r\n at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()\r\n at System.Data.Entity.DbContext.SaveChanges()\r\n at TestSeri.Program.Main(String[] args) in C:\\Users\\arnold.de.groot\\Documents\\Visual Studio 2015\\Projects\\TestSeri\\TestSeri\\Program.cs:line 34" }

As a workaround, I do now:
try { ... } catch (DbEntityValidationException exception) { logger.Error(exception, "Hello World {@exception}", exception); }

and then the RenderedMessage contains the expected
destructured exception details.
What's wrong?

Feature Request: Fluent Destructure API

This is a feature request. Can we update the library so that Exception Destructures can be hooked in using a fluent API as opposed to passing a list into .Enrich.WithExceptionDetails()? I'm envisioning something like:

ILogger logger = new LoggerConfiguration()
     .Enrich.WithExceptionDetails()
           DestructureException.ByTransforming<MyException>(e => new { e.MyProperty }) // These could be chained and are specific to the Exception Enricher
    .WriteTo.Sink(new RollingFileSink(
        @"C:\logs",
        new JsonFormatter(renderMessage: true))
    .CreateLogger();

Or better yet somehow hook into the existing LoggerConfiguration's Destructures:

ILogger logger = new LoggerConfiguration()
    .Enrich.WithExceptionDetails()
    .WriteTo.Sink(new RollingFileSink(
        @"C:\logs",
        new JsonFormatter(renderMessage: true))
    Destructure.ByTransforming<MyException>(e => new { e.MyProperty }) // Declare a MyException destructure just like any other Serilog destructure.
    .CreateLogger();

Insert data from ex.data into output template

I tried the following but can't get it to work.

var ex = new InvalidOperationException("SubJob {SubJobId} Status<>Startable");
ex.Data.Add("SubJobId", subJobId);

_logger.Fatal(ex, ex.Message);

But the Property is not replaced in the output, it seems that I'm doing something wrong, or is this not feasible?

Can you please offer some advice?

Enricher is throwing System.InvalidCastException

Issue Description

When we enabled Serilog.SelfDebug we found out that enricher is throwing exceptions like this:

System.InvalidCastException: Unable to cast object of type 'Serilog.Events.SequenceValue' to type 'Serilog.Events.ScalarValue'.
   at Serilog.Capturing.PropertyValueConverter.<TryConvertEnumerable>g__MapToDictionaryElements|14_0(IDictionary dictionaryEntries, Destructuring destructure)+MoveNext()
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at Serilog.Events.DictionaryValue..ctor(IEnumerable`1 elements)
   at Serilog.Capturing.PropertyValueConverter.TryConvertEnumerable(Object value, Destructuring destructuring, Type valueType, LogEventPropertyValue& result)
   at Serilog.Capturing.PropertyValueConverter.CreatePropertyValue(Object value, Destructuring destructuring, Int32 depth)
   at Serilog.Capturing.MessageTemplateProcessor.CreateProperty(String name, Object value, Boolean destructureObjects)

Version Serilog.Exceptions NuGet package?

5.3.1

PushProperty and a data object

_logger.Information("{@DaTa}", data); writes out the data object properties and values just fine. How do I do the same thing with PushProperty? I tried using (LogContext.PushProperty("{@DaTa}", data)) but all it does is .ToString() which is essentially the class name.

Thanks

Allow to configure depth of destructuring

For now, reflection destructurer depth traversal is hardcoded to 10, I think it would be a good idea to allow configuration for the field. Serilog has that and more in form of Destructure.ToMaximumDepth(n).
What do you think about that?
My dream solution is to be using Serilog configuration directly and support all the limits that Serilog does(collection length, string length).

Add configuration example to readme

It will be good to add to readme an example of configuration as an alternative to hardcoded new LoggerConfiguration() .Enrich.WithExceptionDetails()- something like

{
"Serilog": {
"MinimumLevel": "Debug",
"Using": [ "Serilog.Exceptions" ],
"Enrich": [ "WithExceptionDetails"],
"WriteTo": [
{ "Name": "Console" }
]
}
}

I havenโ€™t tried it yet.
Will it work ?

Add inner exception text as a property

Hello,

first of all. Thank you for Serilog.Exceptions.

I want to ask you for an improvement:
most of the time, you should take a look at the message of the most inner exception to understand why there was a problem. It would be great if you can add an option to generate a property (f.e. InnerMostExceptionMessage") with that message.

It should take you very little time to add and I think that makes debugging a problem a lot easier.

BR

Memory hogging happening in ReflectionBasedDestruturer

Issue Description

Server memory is suddenly getting filled from 11% to 99% within ~3 mins. Came to this conclusion based on the memory dumps.

image

Unexpected EF Core entities found in memory.

Version Serilog.Exceptions NuGet package?

5.3.1

Stack Trace Property Missing

Describe the bug

My understanding from Issue 29 was that excluding the stack trace property was an optional filter, however for me it seems to be excluding it by default.

I am using the Google Cloud Logging sink, injecting Serilog logger and using the Microsoft ILogger interface.

It would be great to get some clarity if this property is ignored by default and if so, is it possible to include it once again?

[Docs] Destructurer via json

I have all my config in json. Does anyone know how to use the destructurer via json?

For example, for Serilog.Exceptions.EntityFrameworkCore:

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

How is that represented in the appsettings.json?

It would also be useful to add that to the docs in the corresponding section.

Properties are written in PascalCase

Hi

Thank you for this excellent library which I am just getting to grips with.

I have an issue in that the property names are PascalCase where the standard serilog exception properties are camelCase - at least in elastic search which is my use case.

Is there a way to get them to follow the normal convention and also be camelCase?
Also, any way to merge them with the standard exception properties logged by serilog itself?
It seems a bit odd to have exception.foo, exception.bar etc and then a completely separate section with exceptionDetail.baz etc...

thanks

Do not destructure CancellationToken

Currently exception details is showing CancellationToken like this:

    "CancellationToken": {
        "_typeTag": "CancellationToken",
        "IsCancellationRequested": true,
        "CanBeCanceled": true,
        "WaitHandle": "The property accessor threw an exception: ObjectDisposedException"
      },

rendering ObjectDisposedException if it is disposed

Should render it as

"CancellationToken": "CancellationRequested: true"

Exception when logging DbEntityValidationException

When logging a DbEntityValidationException I get the following exception in Log.Error(exception)

Exception thrown: 'System.Reflection.TargetParameterCountException' in mscorlib.dll

Additional information: Parameter count mismatch.

Platform: .NET 4.5.2

Is this a known issue?

Failing build

@RehanSaeed did you notice that build for master branch is failing?
From the history of builds, it seems that the problem showed up after version 4.1, possibly by merging dependabot commits.

Do you have a plan to fix the build?

EDIT: I have just pushed 9fbb55a, which fixes the failing test, part of the problem of failing the build.

Not showing Exception stack trace in "Exception" field of the log

Describe the feature

Here is an exception logged using Seriolog.Exceptions in a json file:

image

A part of my logger configuration with ExceptionDetails and RollingFile configuration is:

.Enrich.WithExceptionDetails( new DestructuringOptionsBuilder() .WithDefaultDestructurers()) .WriteTo.RollingFile(new JsonFormatter(","), HttpContext.Current.Server.MapPath($"~/logs/log-.json"));

With the above configuration, the stack trace displays inside the "ExceptionDetails" section which is just right.

I understand that I am using the new JsonFormatter() in the RollingFile sink, hence the Exception field inside the LogEvent object gets logged as Exception.ToString() and the stack trace becomes a part of the value of the "Exception" field in the log. But there is no need to display stack trace there when it can be shown as a separate field inside the "ExceptionDetails".

There should be an option in Exception Destructuring to show stack trace as a part of the value of the "Exception" or remove the "Exception" field altogether when the "ExceptionDetails" section is being written to the log.

Failing build

@RehanSaeed you must have noticed that build is failing. Did you try to fix it? Do you any idea why it started failing in the first place?
I would suggest fixing the problem before releasing next major version.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update dependency coverlet.collector to v6.0.2
  • chore(deps): update dependency stylecop.analyzers to v1.2.0-beta.556
  • chore(deps): update dependency system.data.sqlclient to v4.8.6
  • chore(deps): update dependency cake.tool to v3.2.0
  • chore(deps): update dependency grpc.core.api to v2.62.0
  • chore(deps): update dependency junitxml.testlogger to v3.1.12
  • chore(deps): update dependency microsoft.data.sqlclient to v5.2.0
  • chore(deps): update dependency microsoft.net.test.sdk to v17.9.0
  • chore(deps): update dependency microsoft.visualstudio.threading.analyzers to v17.10.48
  • chore(deps): update actions/setup-dotnet action to v4
  • chore(deps): update dependency cake.tool to v4
  • chore(deps): update dependency minver to v5
  • chore(deps): update github artifact actions to v4 (major) (actions/download-artifact, actions/upload-artifact)
  • chore(deps): update github/codeql-action action to v3
  • chore(deps): update release-drafter/release-drafter action to v6
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

cake
build.cake
github-actions
.github/workflows/build.yml
  • actions/checkout v3.6.0
  • actions/setup-dotnet v3.2.0
  • actions/upload-artifact v3.1.3
  • actions/download-artifact v3.0.2
  • test-summary/action v2
  • actions/download-artifact v3.0.2
  • actions/download-artifact v3.0.2
.github/workflows/codeql-analysis.yml
  • actions/checkout v3.6.0
  • github/codeql-action v2
  • github/codeql-action v2
  • github/codeql-action v2
.github/workflows/release-drafter.yml
  • release-drafter/release-drafter v5.24.0
nuget
Benchmarks/Serilog.Exceptions.Benchmark/Serilog.Exceptions.Benchmark.csproj
  • System.Reflection.TypeExtensions 4.7.0
  • System.Security.Principal.Windows 5.0.0
  • System.Net.Primitives 4.3.1
  • System.Net.NameResolution 4.3.0
  • Microsoft.Win32.Primitives 4.3.0
  • BenchmarkDotNet 0.13.8
Directory.Build.props
  • StyleCop.Analyzers 1.2.0-beta.507
  • MinVer 4.3.0
  • Microsoft.VisualStudio.Threading.Analyzers 17.7.30
Source/Directory.Build.props
  • DotNet.ReproducibleBuilds 1.1.1
Source/Serilog.Exceptions.EntityFrameworkCore/Serilog.Exceptions.EntityFrameworkCore.csproj
  • Microsoft.EntityFrameworkCore 3.1.0
  • Microsoft.EntityFrameworkCore 6.0.0
  • Microsoft.EntityFrameworkCore 7.0.0
Source/Serilog.Exceptions.Grpc/Serilog.Exceptions.Grpc.csproj
  • Grpc.Core.Api 2.47.0
Source/Serilog.Exceptions.MsSqlServer/Serilog.Exceptions.MsSqlServer.csproj
  • Microsoft.Data.SqlClient 5.0.0
Source/Serilog.Exceptions.Refit/Serilog.Exceptions.Refit.csproj
  • Refit 6.3.2
Source/Serilog.Exceptions.SqlServer/Serilog.Exceptions.SqlServer.csproj
  • System.Data.SqlClient 4.8.1
Source/Serilog.Exceptions/Serilog.Exceptions.csproj
  • System.Reflection.TypeExtensions 4.7.0
  • Serilog 2.10.0
Tests/Directory.Build.props
  • xunit.runner.visualstudio 2.5.1
  • xunit 2.5.1
  • Moq 4.20.69
  • Microsoft.NET.Test.Sdk 17.7.2
  • JunitXml.TestLogger 3.0.134
  • coverlet.collector 6.0.0
Tests/Serilog.Exceptions.Test/Serilog.Exceptions.Test.csproj
  • Microsoft.EntityFrameworkCore.InMemory 6.0.0
  • Microsoft.EntityFrameworkCore.InMemory 7.0.0
Tools/ExceptionFinderTool/ExceptionFinderTool.csproj
  • System.Reflection.TypeExtensions 4.7.0
dotnet-tools.json
  • cake.tool 3.1.0
global.json
  • dotnet-sdk 7.0.302

  • Check this box to trigger a request for Renovate to run again on this repository

Separated Column or Porperty for exception stacktrace

Considering the use of structured logs in order to ease processing the logs and being able to generate more precise errors and performance reports:

I was woundering if it would be possible to implement a new property of the current output object that consists of the file and function where the exception occured in order to facilitate post processing the log, for example to create a Dashboard with the most problematic part of the system.

Rigth now, I am able to log the entire exception, but that is not of grate help, once sometimes there are a lot more information than it's needed and parsing those informations before presenting it to the user is may not be a good solution from a performance perspecitve.

It would good if it were possible to integrate with others sinks options available in serilog library.

Maybe there is already a way of acchieving such result, and I may be not aware of. If that's the case, please disconsider the issue, but still would be good to discuss it with the comunity!

Thanks in advance for the attention!

Cheers!

GitHub Docs

@krajek I added every type of GitHub document under the .github folder. Been going through all my repos doing so.

One of the docs is funding.yml which adds a sponsor button to the top. Never tried it, don't expect anything from it but am giving it a go. I added you as a GitHub user but you need to register for the GitHub sponsors beta. I also registered you for the Open Collective project, you should have received an email. Feel free to add your other details.

StyleCop Rules Enabled?

It appears when I upgrade to Serilog.Exceptions 2.2.0, it adds StyleCop analysis to my solution. All sorts of warnings are appearing now when I build my projects. Is this a known issue, by chance?

Rolling FIles creating more than one log file per date

When a new exception is logged, a new file is created.

Scenario:
First file created:
log-20170602

Files created per exceptions:
log-20170602_001
log-20170602_002
log-20170602_003

My code (C# - Visual Studio 2015 Project):

public class EventLogging
    {
        private readonly Logger _logger;


        public EventLogging(IOptions<LoggingOptions> logOption)
        {
            var logAccessor = logOption.Value;

            _logger = new LoggerConfiguration()
                .Enrich.WithExceptionDetails()
                .WriteTo.Sink(new RollingFileSink(logAccessor.Path,
                    new JsonFormatter(renderMessage: true), null, null)).CreateLogger();
        }

        public void LogError(string message, Exception exception)
        {
            _logger.Error(exception, message);
        }

        public void LogWarning(string message, Exception exception)
        {
            _logger.Warning(exception, message);
        }
    }

Refer that class to avoid writing the following code in every class:

_logger = new LoggerConfiguration()
                .Enrich.WithExceptionDetails()
                .WriteTo.Sink(new RollingFileSink(logAccessor.Path,
                    new JsonFormatter(renderMessage: true), null, null)).CreateLogger();

Is there a way to prevent the files being created per exception but per new date.

Make it easier to use default destructurer for custom exceptions

Describe the feature

If an exception type isn't recognized by this library, the fallback is to use the ReflectionBasedDestructurer. It's a common case to have custom exception types that I want to use with the base ExceptionDestructurer instead. Currently there's no easy way to configure this to occur.

My current workaround

new DestructuringOptionsBuilder()
    .WithDefaultDestructurers()
    .WithDestructurers(new[]
    {
        new DefaultExceptionDestructurer<MyException>()
    });

class DefaultExceptionDestructurer<T> : ExceptionDestructurer
{
    public override Type[] TargetTypes { get; } = { typeof(T) };
}

While this isn't much code, it's counterintuitive and required analysis of this library's internals. It'd be better to have more obvious support for this use case.

Possible enhancements

Probably the simplest way to address this would be to leverage the existing IDestructuringOptions.DisableReflectionBasedDestructurer. Currently, setting this option causes the enricher to return null for unrecognized exception types. It could be changed to fall back to ExceptionDestructurer instead (I doubt anyone is depending upon that null value).

Alternatively (or additionally), the options could support selecting between ExceptionDestructurer and ReflectionBasedDestructurer for individual types. Something like this maybe:

new DestructuringOptionsBuilder()
    .WithDefaultException<MySimpleException>()
    .WithDefaultException<MyComplexException>(useReflection: true);

public DestructuringOptionsBuilder WithDefaultException<TException>(bool useReflection = false)
{
    // Implementation
}

Let me know if there is interest in a PR for one or both of these enhancements.

Exception Destructuring blows up when IDictionary is generic

When ExceptionDestructurer.Destructure is invoked with an Exception that has a .Data property that returns a generic dictionary, eg Dictionary<string, object>, an invalid cast exception is raised. This is because it attempts to cast a KeyValuePair to a DictionaryEntry. See code

See this example for a case where the destructurer fails: https://gist.github.com/optical/6e47c7e46fbba839ab22ba92c0d536ee

Many Custom exceptions don't return a non generic dictionary. For example, Npgsql's NpgsqlException does this

It seems like the destructurer should handle this more gracefully

Destructuring structures

For now, we do not destructure any value type including structures. Obviously, it is correct for primitive types and for types like DateTime or Guid. I am not sure about user-defined structures. It seems to me that types like the following one

struct Point 
{
  public int X { get; set; }
  public int Y { get; set; }
}

should be destructured.

@RehanSaeed what do you think?

Confusion regarding default removal of StackTrace and TargetSite

With Issue 29, it was decided to remove StackTrace and TargetSite from the ExceptionDetail structure because it was alleged Serlilog already included it. The issue was created in late 2017 and resolved in earlier 2018, but using Serilog in 2019 doesn't appear to extract StackTrace and TargetSite into properties and I can't find reference online about Serilog working this way. The only thing it does is call ToString on Exception, which does include the stacktrace if it isn't null. Presumably, if one was using Serilog.Exceptions you wouldn't also be logging the Serilog Exception property, since you had a much richer implementation, so by default you're actually losing StackTrace and TargetSite.

Did Serilog in fact work like this before and it doesn't anymore, or am I missing something? In tests I've done, even removing Serilog.Exceptions does not provide StackTrace and TargetSite as properties when I call LogError. I am using Serilog.Extensions.Logging as the implementation for the MicrosoftLoggingExtensions but I don't see how that would change anything.

TypeLoadException w/ Mono 4.2.3

I'm trying to use Serilog.Exceptions 1.1.0 with Serilog 1.5.14 and Mono 4.2.3 but every time I try to run .Enrich.WithExceptionDetails using either the .NET 4.0 or 4.5 dlls (matching Serilog and Serilog.Exceptions of course) I'm getting a TypeLoadException.

Here is a stack trace:

   SetUp : System.TypeLoadException : Could not resolve type with token 01000058
  at Serilog.Exceptions.Destructurers.ExceptionEnricher..ctor (IEnumerable`1 destructurers) <0x41a1fe80 + 0x000e4> in <filename unknown>:0 
  at Serilog.Exceptions.Destructurers.ExceptionEnricher..ctor (Serilog.Exceptions.Destructurers.IExceptionDestructurer[] destructurers) <0x41a1fe50 + 0x00013> in <filename unknown>:0 
  at Serilog.Exceptions.Destructurers.ExceptionEnricher..ctor () <0x41a1fe10 + 0x0001f> in <filename unknown>:0 
  at Serilog.Exceptions.LoggerEnrichmentConfigurationExtensions.WithExceptionDetails (Serilog.Configuration.LoggerEnrichmentConfiguration loggerEnrichmentConfiguration) <0x41a1fb60 + 0x0005b> in <filename unknown>:0 
  at MyApp.InitializeGlobalLogger () <0x41a1a5d0 + 0x0014b> in <filename unknown>:0 
  at SetUpFixture..ctor () <0x41a1a580 + 0x0000b> in <filename unknown>:0 
  at (wrapper managed-to-native) System.Reflection.MonoCMethod:InternalInvoke (System.Reflection.MonoCMethod,object,object[],System.Exception&)
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) <0x4183a250 + 0x00045> in <filename unknown>:0 

and some version info:

Mono JIT compiler version 4.2.3 (Stable 4.2.3.4/832de4b Wed Mar 16 13:19:08 UTC 2016)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
    TLS:           __thread
    SIGSEGV:       altstack
    Notifications: epoll
    Architecture:  amd64
    Disabled:      none
    Misc:          softdebug 
    LLVM:          supported, not enabled.
    GC:            sgen

If Serilog.Exceptions uses P/Invokes then that is certainly the issue as these are not supported by Mono. Thanks for taking a look, and let me know if I can provide more information.

Be able to exclude the StackTrace

It would be nice to be able to exclude the StackTrace because SeriLog already includes that and the duplication can get quite large.

Serious performance issue in combination with dbsets in dbcontext

The logging causes a very important performance drain in combination with dbsets in you dbcontext.
If an error occurs at dbcontext level, it tries to log the Dbcontext class and al its properties.
If you have dbsets configured in that dbcontext class it will load all data from each table which wil cause a cpu/memory/database crash if it is a large database.

If i have time soon, i will try to solve it via a PR

Log certain ExceptionDetail fields to separate database table columns

I'm using Serilog.Sinks.Postgresql (https://github.com/b00ted/serilog-sinks-postgresql) and I would like to log certain fields from the ExceptionDetail object to separate database table columns.

In Serilog.Sinks.Postgresql context this would mean using SinglePropertyColumnWriter. As an example from https://github.com/b00ted/serilog-sinks-postgresql:

IDictionary<string, ColumnWriterBase> columnWriters = new Dictionary<string, ColumnWriterBase>
{
...
{"machine_name", new SinglePropertyColumnWriter("MachineName", PropertyWriteMethod.ToString, NpgsqlDbType.Text, "l") },
...
};

I'm hoping to accomplish something like this with Serilog.Exceptions together with Serilog.Sinks.Postgresql:

IDictionary<string, ColumnWriterBase> columnWriters = new Dictionary<string, ColumnWriterBase>
{
...
{"exception_source", new SinglePropertyColumnWriter("ExceptionDetail.Source [or ExceptionDetailSource]", PropertyWriteMethod.ToString, NpgsqlDbType.Text, "l") },
{"exception_source", new SinglePropertyColumnWriter("ExceptionDetail.Type", PropertyWriteMethod.ToString, NpgsqlDbType.Text, "l") },
{"exception_source", new SinglePropertyColumnWriter("ExceptionDetail.HResult", PropertyWriteMethod.Raw, NpgsqlDbType.Integer) },
{"exception_source", new SinglePropertyColumnWriter("ExceptionDetail.Message", PropertyWriteMethod.ToString, NpgsqlDbType.Text, "l") },
...
};

Is this currently possible with Serilog.Exceptions or could it be part of it in the future or better left for individual use case in which case, any examples?

When certain Entity Framework exceptions occur, Serilog.Exceptions hangs for up to four minutes and causes a nasty memory spike.

Describe the bug

First off, thanks for the great project. :)

This is the chronicle of my issue: dotnet/efcore#24049

Eventually, after hours of experimentation, I isolated the problem to my Serilog configuration.

Below is my Serilog configuration. I included most of my Program.cs for completeness... Bottom line: if I remove the .Enrich.WithExceptionDetails() line, there are no more issues. The exceptions happen very quickly and the memory spike is gone.

Much of this code was migrated from older versions of Serilog, so parts of it may be a bit out of date. I'm hoping you will spot a simple config error:

    public static int Main(string[] args)
    {
        Log.Logger = ConfigureSerilog();

        try
        {
            Log.Information("Starting web host");
            CreateWebHostBuilder(args).Build().Run();
            return 0;
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host terminated unexpectedly");
            return 1;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    private static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration(ConfigConfiguration)
            .UseStartup<Startup>()
            .ConfigureKestrel(o =>
            {
                o.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(5); 
            })
            .UseSerilog();

    /// <summary>
    /// Set up our app to actually use the appsetting files.
    /// </summary>
    static void ConfigConfiguration(WebHostBuilderContext ctx, IConfigurationBuilder config)
    {
        config.SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{ctx.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true);

    }

    static Serilog.Core.Logger ConfigureSerilog()
    {
        // This logger configuration uses the asp.net core logging infrastructure, and routes it through Serilog.
        // This is also used by the .net webserver itself, and we want the keep those logs going to all the normal places
        // while sending our own logs to Loggly, so:
        //  - We route *all* the log entries to the console, and also appInsights.
        //  - We log just our own custom logging to Loggly. 

        var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        var tags = (environment == Microsoft.Extensions.Hosting.Environments.Development ? "dev" : "production");

        return new LoggerConfiguration()
            .MinimumLevel.Debug()                                                  // grab all log traffic
            .MinimumLevel.Override("Microsoft", LogEventLevel.Information)  // but tone down the chatter from asp.net, EF, etc
            .Enrich.FromLogContext()                                               // enhance
            .Enrich.WithExceptionDetails()
            .WriteTo.Console()                                              // write absolutely everything to the console (mimic normal behavior)
            .WriteTo.Logger(context => context                              // write only our own log entries to Loggly
                .Filter.ByExcluding(Matching.FromSource("Microsoft"))
                .WriteTo.Loggly(
                    customerToken: "REDACTED",
                    tags: tags
                )
            )
            .CreateLogger();
    }

We are running .NET Core 5 if that helps.

Any idea what I should do here?

Handling System.Net.WebException is not complete.

Issue Description

Handling System.Net.WebException is not complete.
During destructuring exception, under Response key ( HttpWebResponse),
Under Headers key, Headers displayed but only keys.Not values.
A sample json example:

{
    "@t": "2019-07-06T11:32:08.3837811Z",
    "@mt": "Web Exception ...",
    "@l": "Error",
    "@x": "System.Net.WebException: The remote server returned an error: (404) Not Found.\r\n   at System.Net.HttpWebRequest.GetResponse()\r\n   at System.Net.WebClient.GetWebResponse(WebRequest request)\r\n   at System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream)\r\n   at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)\r\n   at System.Net.WebClient.DownloadString(Uri address)\r\n   at System.Net.WebClient.DownloadString(String address)\r\n   at _Playground.Playground.TestExceptionEnrichment() in H:\\c#\\ArbMaster\\Core_Tests\\Playground\\Playground.cs:line 274",
    "ExceptionDetail": {
        "HResult": -2146233079,
        "Message": "The remote server returned an error: (404) Not Found.",
        "Source": "System.Net.Requests",
        "Status": "ProtocolError",
        "Response": {
            "IsMutuallyAuthenticated": false,
            "ContentLength": -1,
            "ContentType": "text/html; charset=utf-8",
            "ContentEncoding": null,
            "Cookies": [],
            "LastModified": "2019-07-06T14:32:08.4120293+03:00",
            "Server": "cloudflare",
            "ProtocolVersion": {
                "Major": 1,
                "Minor": 1,
                "Build": -1,
                "Revision": -1,
                "MajorRevision": -1,
                "MinorRevision": -1
            },
            "Headers": [
                "Date",
                "Transfer-Encoding",
                "Connection",
                "Set-Cookie",
                "X-Powered-By",
                "Access-Control-Allow-Origin",
                "Via",
                "CF-Cache-Status",
                "Cache-Control",
                "Expect-CT",
                "Server",
                "CF-RAY",
                "Content-Type",
                "Expires"
            ],
            "Method": "GET",
            "ResponseUri": "https://reqres.in/apixxx/users",
            "StatusCode": "NotFound",
            "StatusDescription": "Not Found",
            "CharacterSet": "utf-8",
            "SupportsHeaders": true,
            "IsFromCache": false
        },
        "Type": "System.Net.WebException"
    }
}

To reproduce issue:

  • Create logging with exception enrichment.
  • In a try - catch , Make a call with system.net.webclient's downloadstring method , ( try uri "https://reqres.in/xxapi/users" for example -a 404-)
  • In catch, Log exception with enrichment ( which already set up)
  • Check the keys mentioned above.

It's possible to destruct NameValueCollections as in Catch block below.
I would open a pull request but I couldn't found specific Enrichment about this exception ( not searched thoroughly).

public void TestExceptionEnrichment()
{
    Log.Logger =
                new LoggerConfiguration()
                //.MinimumLevel.Verbose()
                .Enrich.WithExceptionDetails()                        
                .WriteTo.Console(new Serilog.Formatting.Compact.CompactJsonFormatter())                        
                .CreateLogger();
    var webClient = new System.Net.WebClient();

    try
    {
        var ret = webClient.DownloadString("https://reqres.in/apixxx/users"); // To have 404 response..
    }
    catch (System.Net.WebException ex)
    {
        Log.Error(ex, "Web Exception ...");

        // To get headers with values , this probably about to destructuring NameValueCollection in general.
        var status = ((System.Net.HttpWebResponse)ex.Response);
                                                                
        Dictionary<string, string> _Headers = new Dictionary<string, string>();
        status.Headers?.AllKeys.ToList()
            .ForEach(el => _Headers.Add(el, status.Headers.Get(el)));
    }
}

Version Serilog.Exceptions NuGet package?

.nuget\packages\serilog.exceptions\5.3.0

Remove System.Data.SqlClient dependency

Please extract SqlException destructurer to separate.
There are lots of cases when application does not have a dependency on SQL Server.

Another option is to use reflection to lookup for properties.

Thanks

Add destructurer for SocketException

I suggest adding a destructor for SocketException. I volunteer to do this work, but I also want to do a bit more than the naive implementation.

SocketException has a few properties related to the error (namely ErrorCode, NativeErrorCode, and SocketErrorCode). However, they are all a bit cryptic. The first two are of type int and the last one is of type SocketError, which is an enum. Of course it also has the property HelpLink inherited from Exception. If there was ever a time to set that value, it would be now, but I have only seen it set to null. I think a great help page is the documentation for SocketError, which has a short phrase explaining each case of the enum.

Alongside the other properties of SocketException, I would prefer to also add that URL for the key SocketErrorCodeHelpLink.

How does this sound?

NuGet feed DLL needs to be strong-named

Hi,
The current Serilog.Exceptions package up in Nuget isn't strong-named which obviously causes issues. Esp. when other serilog packages are signed. It would be good if this package was also followed suit.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.