Search code examples
c#asp.net-coreasp.net-web-apiserilogserilog-sinks-file

Serilog format context property as top level property


I'm adding properties to the log using LogContext.PushProperty() but the properties end up as properties of "Properties" like this:

{
    "Timestamp":"2024-08-28T15:19:48.7739018-07:00",
    "Level":"Debug",
    "MessageTemplate":"Conditions must have at least two QueryCondition",
    "Properties":{
        "HttpMethod":"POST",
        "Browser":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:129.0) Gecko/20100101 Firefox/129.0",
        "Route":{"Value":"/api/document","HasValue":true,"_typeTag":"PathString"},
        "URL":"http://localhost:54399/api/document",
        "Environment":"localhost:54399",
        "x-app-id":null,
        "x-correlation-id":"d4654a06-e867-4efe-9615-125d694f2291",
        "Application":"Sample"
    }
}

I want it to look more like this:

{
    "Timestamp":"2024-08-28T15:19:48.7739018-07:00",
    "Level":"Debug",
    "MessageTemplate":"Conditions must have at least two QueryCondition",
    "HttpMethod":"POST",
    "Browser":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:129.0) Gecko/20100101 Firefox/129.0",
    "Route":{"Value":"/api/document","HasValue":true,"_typeTag":"PathString"},
    "URL":"http://localhost:54399/api/document",
    "Environment":"localhost:54399",
    "x-app-id":null,
    "x-correlation-id":"d4654a06-e867-4efe-9615-125d694f2291",
    "Application":"Sample"
}

I've looked at a bunch of Serilog tutorials and examples. They all show the properties added by LogContext.PushProperty() as top level properties so I'm not sure why it turn out like it does for me.


Solution

  • This can be achieve by create a custom JsonFormatter. When you use like

        .Enrich.FromLogContext()
        .WriteTo.Console(new JsonFormatter())
    

    If you check the source code of JsonFormatter,then you will find following codes under public void Format(LogEvent logEvent, TextWriter output) method which add "Properties" key to the json. enter image description here Unfortunately, JsonFormatter is sealed so you cannot custom.

    Similarly, you could use the CompactJsonFormatter

        .WriteTo.Console(new CompactJsonFormatter())
    

    It has some variation such as using "@t" instead of "Timestamp" enter image description here
    But you could create a custom formatter using it and change the logic.

        public class CustomJsonFormatter : CompactJsonFormatter
        {
            public override static void FormatEvent(LogEvent logEvent, TextWriter output, JsonValueFormatter valueFormatter)
            {
                ...
            }
        }