Closed quabug closed 9 months ago
The [serilog] scope is stored in the .NET ExecutionContext, which is Attached to the logical thread (and flows to child Tasks etc).
At the serilog level, you can make a contextual logger with properties attached using the .ForContext<>()
overloads - this layers a set of properties into the logger by holding them in a wrapper/decorator object that you can then pass inwards.
I'd suggest asking this as a question with some more details on what you have tried and are seeking exactly (and/or whether its critical for you to stay using the Microsoft.Extensions.Logging
APIs) on stackoverflow using a serilog
tag as you'll get way more eyes on it there than here.
The [serilog] scope is stored in the .NET ExecutionContext, which is Attached to the logical thread (and flows to child Tasks etc).
At the serilog level, you can make a contextual logger with properties attached using the
.ForContext<>()
overloads - this layers a set of properties into the logger by holding them in a wrapper/decorator object that you can then pass inwards.I'd suggest asking this as a question with some more details on what you have tried and are seeking exactly (and/or whether its critical for you to stay using the
Microsoft.Extensions.Logging
APIs) on stackoverflow using aserilog
tag as you'll get way more eyes on it there than here.
Thanks for your suggestion.
Make BeginScope
local to a logger or make it global is a design decision from my perspective.
And it is not about serilog itself, it is about how to design this BeginScope
interface.
Yes, I can achieve this by ForContext
method while creating a logger, but there's no way to call a custom ForContext
from Microsoft.Extensions.Logging
APIs, and it is practically a bad idea to create a new logger every time I need some "local" property on a logger.
I suspect it's not an either/or situation. MEL dictates a lot of how stuff works. I don't know all the details, but I can guarantee someone one SO will have a viable answer pretty quick.
and it is practically a bad idea to create a new logger every time I need some "local" property on a logger.
It's a pretty well-established pattern that's designed into Serilog. Yes, it allocates, but no, its not the same cost as making a 'new logger'.
So, in summary:
Actually I have a fork of this project which make a local scope as describe here. So this post is more like a suggestion/discussion of design decision than a question or a help needed...
Maybe the example is not clear, take this as another example:
class SomeClass
{
private ILogger _logger;
public SomeClass(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger("SomeClass"); // create a new logger with category name
_logger.BeginScope(this); // seems like push a scope into "logger", but actually a global-wide provider instead.
}
}
var foo = new SomeClass(loggerFactory);
var bar = new SomeClass(loggerFactory);
// now the scope for both foo and bar is:
// parent: foo -> child: bar
I found it is very confusion and hard to maintain a global wide scope which affect each other when I have an independent logger instance.
update: Begin/End style example
class SomeClass
{
private ILogger _logger;
private IDisposable _scope;
public SomeClass(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger("SomeClass");
}
public void BeginSometing()
{
_logger.BeginScope(this);
}
public void EndSomething()
{
_scope?.Dispose();
}
}
var foo = new SomeClass(loggerFactory);
var bar = new SomeClass(loggerFactory);
foo.BeginSomething();
bar.BeginSomething();
// now the scope for both foo and bar is:
// parent: foo -> child: bar
Thanks for raising this. Unfortunately it's a behavior that the ship has sailed on, and is unlikely to change at this point. Thanks again for taking the time to explain it, though.
consider something like this:
IMO, the scope of
foo
andbar
should not effect each other.