Serilog with Seq - Adding Properties without Placing in Message Text

2.8k views Asked by At

I have an object with several properties that relate to an event that just occurred on my website.

I want to log this event, and for each of its properties to appear in Seq - as properties. However want to omit most of the properties from the actual log message text - so I don't want them in the message template. v

If I do this:

        var logInfo= new LogInfo() {Foo = 1, Bar= "Pending"};
        logger.Information("{@event}", logInfo);

The only property that lights up in Seq directly against the log, is the @event property. It actually looks like this:

enter image description here

So I tried this:

        var enricher = new DnnLogInfoEnricher(logInfo);
        using (LogContext.PushProperties(enricher))
        {
            Log.Logger.Information("Event: {logInfo}", logInfo.LogTypeKey, logInfo.Exception);
        }

But my concern with this approach, is that as this method is going to fire an enormous number of times, I'd prefer not to have to create a new enricher object instance each time - as I like to keep the number of objects being created generally as low as possible.. Just because I am concerned about GC implications (perhaps my concerns are unfounded?).

Is this the correct / right way to achieve what I want (i.e using the enricher) or am I missing something?

Cheers!

1

There are 1 answers

0
Nicholas Blumhardt On BEST ANSWER

Serilog's ForContext() is quite well optimized for this kind of scenario and won't create too much garbage (it goes out of its way to avoid it where possible). The cost of creating the context won't be significant in proportion to the cost of logging the data to begin with.

var log = Log.ForContext("Info", logInfo, destructureObjects: true);
log.Information(logInfo.Exception, "Event happened");

One observation, you might be better off excluding the exception from the captured object and pass it through as the first parameter of the logging call instead. To exclude it, you can set up a custom policy when the logger is created:

Log.Logger = new LoggerConfiguration()
    .Destructure.ByTransforming<LogInfo>(li => new {
        li.BypassBuffering, li.LogConfigId, li.LogEventId, li.LogGUID
    })
    // <snip>
    .CreateLogger();

While ByTransforming() might seem to add more overhead here, you should be able to get a much tighter and more efficient result by cherry-picking only the interesting properties of LogInfo.

One other minor thing - it's not necessary to call Log.Logger on the static class; Log has methods like Information() on it directly, as in Log.Information(...).