Search code examples
c#loggingparallel-processingtaskserilog

How to mark a specific processing chain in Serilog


I have an application in which I'm using tasks to process items from the resultset in parallel. Each execution involves the nested calling of common functions across different execution paths. I would like to be able to mark a specific execution chain in the log to know which messages belong to the processing of a specific work item.
I am using Serilog as a logging facility calling the static Log.Debug("...."), Log.Information("...."), etc calls to avoid passing instances of the Log class into every method. I tried to use

_ = Log.ForContext("TaskID", $"Item Type 1: {UniqueItem1Id}");

and

_ = Log.ForContext("TaskID", $"Item Type 2: {UniqueItem2Id}");

depending on the function, processing the specific type of data.
I used format string

"{Timestamp:HH:mm:ss.fff} {TaskID} {Level:u3} {Message:lj}{NewLine}{Exception}"
expecting the TaskID placeholder to be populated with the UniqueItemXId. This attempt, however, failed to introduce an entry into the log placing an empty string at the TaskID location.

What would be the way to introduce TaskID into the log?


Solution

  • You need to do:

    var taskLog = Log.ForContext("TaskId", <value>);
    taskLog.Information("Test"); // LogEvent will have the TaskId property in it
    

    (Obv Log.ForContext("TaskId", <value>).Information("Test"); is equivalent).

    The other option, assuming you are nesting a set of work inside a call chain within a block is to do using LogContext.PushProperty("TaskId, <value>) { <do work>} by using the LogContext.

    I'd recommend reading up on the best practices but also the walkthrough in serilog.net - some of it will be old hat, but there's plenty subtlety to things, as you've run into in this instance.