3

I'm switching from log4net to Serilog but miss some of the formatting possibilities I had in log4net. I don't find any documentation for what formatters I can use in the outputTemplate. Is there a way to accomplish what I describe below?

Using the outputTemplate

"outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u3}] ({SourceContext}) {Message:lj}{NewLine}{Exception}"

It looks like this

[2020-03-30 11:31:06.464 DBG] (DomainLogic.TCMessageHandler) >>>Poll
[2020-03-30 11:31:06.481 DBG] (AmqpReader.Reader)    >>>Read
[2020-03-30 11:31:06.485 INF] (AmqpReader.Reader)       Fetched a message from the queue.
[2020-03-30 11:31:06.487 DBG] (AmqpReader.Reader)    <<<Read - 00:00:00.0066941
[2020-03-30 11:31:06.504 DBG] (DomainLogic.TCMessageHandler) <<<Poll - 00:00:00.0399191

This is what I want

[2020-03-30 11:31:06.464 DBG] (DomainLogic.TCMessageHandler) >>>Poll
[2020-03-30 11:31:06.481 DBG] (AmqpReader.Reader           )    >>>Read
[2020-03-30 11:31:06.485 INF] (AmqpReader.Reader           )       Fetched a message from the queue.
[2020-03-30 11:31:06.487 DBG] (AmqpReader.Reader           )    <<<Read - 00:00:00.0066941
[2020-03-30 11:31:06.504 DBG] (DomainLogic.TCMessageHandler) <<<Poll - 00:00:00.0399191

And if I set a fixed width and the SourceContext is longer than that, I'd like it to truncate from the left. Like this

[2020-03-30 11:31:06.464 DBG] (ogic.TCMessageHandler) >>>Poll
[2020-03-30 11:31:06.481 DBG] (AmqpReader.Reader    )    >>>Read
[2020-03-30 11:31:06.485 INF] (AmqpReader.Reader    )       Fetched a message from the queue.
[2020-03-30 11:31:06.487 DBG] (AmqpReader.Reader    )    <<<Read - 00:00:00.0066941
[2020-03-30 11:31:06.504 DBG] (ogic.TCMessageHandler) <<<Poll - 00:00:00.0399191
Carl Björknäs
  • 593
  • 4
  • 15

2 Answers2

3

Serilog output templates (and message templates) are based on .NET format strings, and these don't support truncation of substituted values. There's no way to do this directly in the output template, though you could write an ILogEventEnricher that substitutes the property for a truncated version of it, depending on how else you plan to consume the events.

Nicholas Blumhardt
  • 30,271
  • 4
  • 90
  • 101
1

Here's an enricher that does just what I asked for.

public class StaticWidthSourceContextEnricher : ILogEventEnricher
{
    private readonly int _width;

    public StaticWidthSourceContextEnricher(int width)
    {
        _width = width;
    }

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        var typeName = logEvent.Properties.GetValueOrDefault("SourceContext").ToString();

        if (typeName.Length > _width)
        {
            typeName = typeName.Substring(typeName.Length - _width);
        }
        else if (typeName.Length < _width)
        {
            typeName = typeName + new string(' ', _width - typeName.Length);
        }

        logEvent.AddOrUpdateProperty(propertyFactory.CreateProperty("SourceContext", typeName));
    }
}
Carl Björknäs
  • 593
  • 4
  • 15
  • I appreciate your question and follow-up answer - thank you! I am just getting started with Serilog and would appreciate any guidance you could give regarding how to configure this enricher. – Phil May 12 '22 at 19:50
  • @Phil I think I used it like described here https://briancaos.wordpress.com/2019/02/22/serilog-add-thread-id-to-the-log-file/ `.Enrich.With(new StaticWidthSourceContextEnricher(40))` – Carl Björknäs May 13 '22 at 21:15