SunilA
SunilA

Reputation: 583

Populate custom columns in Serilog MsSql sink

I am using Serilog in my dotnet core application. I have added custom columns to the default list of columns provided by Serilog. Below is how my "Serilog" configuration looks like in appsettings.json file -

"Serilog": {
"MinimumLevel": "Information",
"WriteTo": [
  {
    "Name": "MSSqlServer",
    "Args": {
      "connectionString": <connectionString>
      "tableName": "Log",
      "autoCreateSqlTable": true,
      "columnOptionsSection": {
        "removeStandardColumns": [ "MessageTemplate", "Properties"], //remove the Properties column in the standard ones
        "customColumns": [
          {
            "ColumnName": "ControllerName",
            "DataType": "varchar",
            "DataLength": 50
          }
        ]
      },
      "timeStamp": {
        "columnName": "Timestamp",
        "convertToUtc": true
      }
    }
    }
]
}

So I have removed "MessageTemplate" and "Properties" from the default list of columns created by Serilog and added "ControllerName" as a new column to the table Log, where Serilog logs its data. What i want is that when I am logging information , I want to provide value to the "ControllerName" column. How can it be done? I have found the below solution :

_logger.LogInformation("{ControllerName}{Message}", "TestController", "Starting up.."); 

This line of code provides value to the ControllerName column, but the message column gets the value as

"TestController""Starting up.."

I want the message column to get value as

 Starting up..

Upvotes: 7

Views: 14601

Answers (1)

C. Augusto Proiete
C. Augusto Proiete

Reputation: 27828

It seems you are using Microsoft's ILogger<T> instead of Serilog's ILogger thus in order to add a contextual property that will be included in your log event without being part of the message, you have to create a new logging scope using BeginScope e.g.

using (_logger.BeginScope("{ControllerName}", nameof(TestController)))
{
    _logger.LogInformation("{Message}", "Starting up..."); 
}

Another alternative is to add a property to Serilog's LogContext:

using (LogContext.PushProperty("ControllerName", nameof(TestController))
{
    _logger.LogInformation("{Message}", "Starting up..."); 
}

This will give you the same end result as with BeginScope above, but is a Serilog-specific API and kind of defeats the purpose of using ILogger<T> in the first place, so BeginScope would be preferred unless you decide to use Serilog's ILogger instead.

One important observation is that in order for the LogContext to work, you need to enable it when you configure your logger. For example:

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext() // <<<<<<<<<<#############
    .WriteTo.Console()
    .CreateLogger();

If you were to use Serilog's ILogger, then in addition to be able to use the LogContext you can alternatively create a new context using Log.ForContext:

var contextLogger = logger.ForContext("ControllerName", nameof(TestController));
contextLogger.Information("{Message}", "Starting up...");

ps: If you're not sure whether you should use Microsoft's ILogger<T> or Serilog's ILogger, I recommend reading this answer: Serilog DI in ASP.NET Core, which ILogger interface to inject?

Upvotes: 8

Related Questions