Serilog: Log Event Id as the data type that was inserted into LogInformation

Created on 18 Aug 2019  路  4Comments  路  Source: serilog/serilog

Does this issue relate to a new feature or an existing bug?

  • [ X ] Bug
  • [ ] New Feature

Serilog.AspNetCore 2.1.1

In the current behaviour when I call Log logger.LogInformation(1000, "My message), the EventId gets serialized as {"EventId": {"Id": 1000}}.

I would expect {"EventId": 1000}. This would force it to be a scalar which is what I desire. I think this is a bug, as this somehow changes the expected semantics described in the AspNetCore Logger documentation. Am I missing something?

Edit: I tried to use the Destructuing primitive but it is never called, so I cannot proceed further.
.Destructure.ByTransforming<EventId>(r => r.Id)

question

Most helpful comment

Hi @ptsneves, thanks for the heads-up.

EventId can carry both the name and numeric identifier at the same time:

https://github.com/aspnet/Logging/blob/2d2f31968229eddb57b6ba3d34696ef366a6c71b/src/Microsoft.Extensions.Logging.Abstractions/EventId.cs#L23

Representing it as a struct was the only full-fidelity option that would make queries like EventId.Name = 'foo' behave predictably.

To change this, though, you can plug in an ILogEventEnricher like:

    .Enrich.With<EventIdIsAlwaysNumericEnricher>()

implemented something like (untested code warning!):

class EventIdIsAlwaysNumericEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent evt, ILogEventPropertyFactory _)
    {
        if (evt.Properties.TryGetValue("EventId", out var val) &&
            val is StructureValue sv &&
            sv.Properties.TryGetValue("Id", out var idval))
        {
            evt.AddOrUpdateProperty("EventId", idval);
        }
    }
}

馃殌

All 4 comments

Hi @ptsneves, thanks for the heads-up.

EventId can carry both the name and numeric identifier at the same time:

https://github.com/aspnet/Logging/blob/2d2f31968229eddb57b6ba3d34696ef366a6c71b/src/Microsoft.Extensions.Logging.Abstractions/EventId.cs#L23

Representing it as a struct was the only full-fidelity option that would make queries like EventId.Name = 'foo' behave predictably.

To change this, though, you can plug in an ILogEventEnricher like:

    .Enrich.With<EventIdIsAlwaysNumericEnricher>()

implemented something like (untested code warning!):

class EventIdIsAlwaysNumericEnricher : ILogEventEnricher
{
    public void Enrich(LogEvent evt, ILogEventPropertyFactory _)
    {
        if (evt.Properties.TryGetValue("EventId", out var val) &&
            val is StructureValue sv &&
            sv.Properties.TryGetValue("Id", out var idval))
        {
            evt.AddOrUpdateProperty("EventId", idval);
        }
    }
}

馃殌

Hello @nblumhardt
Thanks for the answer. I was for a long time trying to figure out how to do that with an enricher but was stuck with the concept that adding a property that already existed seemed to not make sense. You provided the key piece. Thank you very much.

Regarding the destructure. Do you know why it did not work?

Great, thanks @ptsneves !

RE destructuring, the event id is mapped across explicitly, without invoking the configured IDestructuringPolicys. We could probably enable this, but at some performance cost - for now I think the enrichment route may be the best one. Cheers!

Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

riiight picture riiight  路  3Comments

CADbloke picture CADbloke  路  4Comments

dazinator picture dazinator  路  3Comments

Pvlerick picture Pvlerick  路  5Comments

sicollins picture sicollins  路  4Comments