Reputation: 3955
I want to use the feature the Microsoft.Logger
has at Serilog directly, the BeginScope
feature.
I know that I can use Microsoft ILogger
and setup Serilog to be the underlying logger but it's too much trouble at this point of the app.
I want to know if there is a BeginScope
equivalent in Serilog.
The information at the internet is not straight forward, there are mentions that Serilog support that but nowhere is mentioned if it's directly supported or by using the Microsoft classes.
Upvotes: 14
Views: 21048
Reputation: 1119
@Nicholas's answer is correct. I just wanted to drop a small worked example for anyone else coming to this thread to point out something that's not so obvious;
Here some example code that shows how to use Serilog context;
void Main()
{
var log = Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Information()
.WriteTo.Console()
.CreateLogger();
Log.Logger = log;
log.Information("Starting app");
Task.WaitAll(
Task.Run (() => GetNums(10,15, 2, "evens")),
Task.Run (() => GetNums(11, 15, 2, "odds"))
);
log.Information("Finished.");
Console.ReadLine();
}
static Random R = new Random();
static void GetNums(int start, int cnt, int inc, string name)
{
using(var log = LogContext.PushProperty("name", name))
{
for (int i = start; i < start + cnt; i+=inc)
{
Log.Information("{number},{name}", i);
Thread.Sleep(R.Next(500));
}
}
}
produces this output
[17:11:31 INF] Starting app
[17:11:31 INF] 10,evens
[17:11:31 INF] 11,odds
[17:11:31 INF] 12,evens
[17:11:31 INF] 14,evens
[17:11:32 INF] 13,odds
[17:11:32 INF] 16,evens
[17:11:32 INF] 15,odds
[17:11:32 INF] 18,evens
[17:11:32 INF] 20,evens
[17:11:32 INF] 17,odds
[17:11:32 INF] 22,evens
[17:11:33 INF] 24,evens
[17:11:33 INF] 19,odds
[17:11:33 INF] 21,odds
[17:11:34 INF] 23,odds
[17:11:34 INF] 25,odds
[17:11:34 INF] Finished.
The thing I wanted to point out, is that the items logged to the context won't appear in the logs, (i.e. won't be logged) if the named value does not appear in your template.
For example, in the code above, if we change Log.Information("{number},{name}",i);
to Log.Information("{number}",i);
then this is what you would get, and this is similar to what you might get if you don't configure enrichment Enrich.FromLogContext()
. It's subtle and easy to forget to update the template and chase your tail trying to find the bug.
without template string including the named properties included in the context
[17:22:11 INF] Starting app
[17:22:11 INF] 10
[17:22:11 INF] 11
[17:22:11 INF] 12
[17:22:11 INF] 13
[17:22:11 INF] 15
[17:22:11 INF] 17
[17:22:12 INF] 14
[17:22:12 INF] 16
[17:22:12 INF] 19
[17:22:12 INF] 18
[17:22:12 INF] 20
[17:22:12 INF] 21
[17:22:12 INF] 23
[17:22:12 INF] 22
[17:22:12 INF] 24
[17:22:13 INF] 25
[17:22:13 INF] Finished.
also, the enriched properties are appended
to the end of the string, so
Log.Information("{name},{number}", i);
would produce
[17:35:11 INF] Starting app
[17:35:11 INF] 11,{number}
[17:35:11 INF] 10,{number}
Happy logging! Hope this helped.
Upvotes: 8
Reputation: 31832
Yes, Serilog has a native equivalent of this feature, called using LogContext.PushProperty()
.
To enable this, you first must add Enrich.FromLogContext()
to your Serilog LoggerConfiguration
, for example:
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext() // <- this line
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} " +
"{Properties:j}{NewLine}{Exception}"))
.CreateLogger();
Then, to push properties onto the context (equivalent to ILogger.BeginScope()
), use:
using (LogContext.PushProperty("OrderId", 1234))
{
Log.Information("Processing a new order");
// ...etc
}
The configuration above includes {Properties:j}
to ensure all event properties, such as those from the log context, are included in the output. How you'll view the additional properties will depend upon which sink you're using.
Upvotes: 27