'Serilog ThreadId is always output as 1

I have a ThreadId in the outputTemplate but the log always records it as 1. I have several instances of the app running at the same time into the same log and so was hoping I could separate the instances based on the ThreadId.

Can anyone suggest how to work around this? The ThreadName gets assigned after the app sets up a few things and identifies the area it is running in so is not the best seperator. Also there can be multiple functions run in an area concurrently. Hence the need for the ThreadId

Log.Logger = new LoggerConfiguration()
            .ReadFrom.Configuration(builder.Build())
            .Enrich.FromLogContext()
            .Enrich.WithThreadId()
            .Enrich.WithThreadName()
            .WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] <{ThreadName}> <{ThreadId}> {Message:lj}{NewLine}{Exception}")      
            .WriteTo.File(@".\log\log.txt", 
                             rollingInterval: RollingInterval.Day, 
                             shared: true,
                             outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] <{ThreadName}> <{ThreadId}> {Message:lj}{NewLine}{Exception}")
            .CreateLogger();

Log output

2021-04-09 06:30:09.059 [INF] <blackstone> <1> Action : Task A
2021-04-09 06:30:09.059 [INF] <wavell> <1> Action : Task A
2021-04-09 06:30:09.060 [INF] <forest> <1> Action : Task A
2021-04-09 06:30:09.130 [INF] <wavell> <1> Loading CentreDetails
2021-04-09 06:30:09.130 [INF] <forest> <1> Loading CentreDetails
2021-04-09 06:30:09.132 [INF] <blackstone> <1> Loading CentreDetails
2021-04-09 06:30:09.560 [INF] <wavell> <1> Loading ParentDetails
2021-04-09 06:30:09.554 [INF] <blackstone> <1> Loading ParentDetails
2021-04-09 06:30:09.560 [INF] <forest> <1> Loading ParentDetails


Solution 1:[1]

OK I follow what @Nicholas Blumhardt was aiming at...

Added the Serilog.Enrichers.Process nuget and updated the code to this

Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(builder.Build())
                .Enrich.FromLogContext()
                .Enrich.WithProcessId()
                .Enrich.WithThreadName()
                .WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] <{ThreadName}> <{ProcessId}> {Message:lj}{NewLine}{Exception}")      
                .WriteTo.File(@".\log\log.txt", 
                                 rollingInterval: RollingInterval.Day, 
                                 shared: true,
                                 outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] <{ThreadName}> <{ProcessId}> {Message:lj}{NewLine}{Exception}")
                .CreateLogger();

The log is now pushing out a unique Process ID

Solution 2:[2]

Sounds like you want Serilog.Enrichers.Process and Enrich.WithProcessId() instead of WithThreadId().

Solution 3:[3]

This worked for me:

nuget package

<PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />

appsettings.json {ThreadId}

{
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  },
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Error"
      }
    },
      {
        "Name": "File",
        "Args": {
          "path": "/log/api.log",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] Th:{ThreadId} {Message} {NewLine}{Exception}",
          "rollingInterval": "Day"
        }
      }
    ],
    "Properties": {
      "Application": "acme"
    }
  }
}

startup .Enrich.WithThreadId()

public Startup(IConfiguration configuration)
{
    Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).Enrich.WithThreadId()
        .CreateLogger();
    Configuration = configuration;
}

sample log

2022-03-11 14:49:25.425 -05:00 [Information] Th:27 foo
2022-03-11 14:49:25.428 -05:00 [Information] Th:27 Bar

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 KAHartle
Solution 2 Nicholas Blumhardt
Solution 3 JRichardsz