Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behavior with ConsoleLoggerProvider & LoggerExternalScopeProvider #39022

Closed
Ninds opened this issue Jul 9, 2020 · 8 comments
Closed
Labels
area-Extensions-Logging question Answer questions and provide assistance, not an issue with source code or documentation.
Milestone

Comments

@Ninds
Copy link

Ninds commented Jul 9, 2020

There are 2 scenarios :

Scenario 1

  1. Setup logging with Dependency Injection using ConsoleLoggerProvider
  2. Set a scopeprovider on the ConsoleLoggerProvider
  3. Create a Logger
  4. Log something

The output is not what is expected in that the scope information is missing from the output:

info: DemonstrateWeirdScopedLoggerBehaviour.ScopedLoggerDemo[0]
      Hello world at 09/07/2020 22:19:09

Scenario 2

  1. Setup logging with Dependency Injection using ConsoleLoggerProvider
  2. Create a (unnecessary) logger
  3. Set a scopeprovider on the ConsoleLoggerProvider
  4. Create a Logger
  5. Log something

The output is what is expected in that the scope information is present in the output:

info: DemonstrateWeirdScopedLoggerBehaviour.ScopedLoggerDemo[0]
      => MyScope
      Hello world at 09/07/2020 22:22:11

A reproducer can be found here : ScopedLoggerDemo.cs

I see the same behaviour in 3.1.5 and 5.0.0-preview6

Perhaps the behaviour is by design but it does seem odd.

@Dotnet-GitSync-Bot
Copy link
Collaborator

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Jul 9, 2020
@maryamariyan
Copy link
Member

I checked your sample, it is because for ConsoleLoggerProvider you have IncludeScopes option enabled:

opt => opt.IncludeScopes=true

@maryamariyan maryamariyan added customer assistance and removed untriaged New issue has not been triaged by the area owner labels Jul 24, 2020
@Ninds
Copy link
Author

Ninds commented Jul 24, 2020

HI
Thankyou for looking at it.
Can you elaborate why the difference in behaviour ?
Specifically why should it make any difference whether an unnecessary logger is instantiated before setting a scopeprovider on the ConsoleLoggerProvider ?

@maryamariyan
Copy link
Member

@Ninds so basically

var logger = sp.GetRequiredService<ILogger<Program>>();

would need to be called before the scope provider setup. That's why ILogger defined in your "if (itWorks)" code block works and not the one define underneath.

@maryamariyan maryamariyan added this to the Future milestone Jul 27, 2020
@davidfowl
Copy link
Member

You shouldn't be setting the scope provider yourself, that's the job of the LoggerFactory. What exactly are you trying to do?

@maryamariyan
Copy link
Member

And to further elaborate, I believe when you use LoggerFactory your code sample should look something like below:

    using var loggerFactory = LoggerFactory.Create(builder =>
    {
         builder.AddConsole(opt => opt.IncludeScopes = true);
    });
    var logger = loggerFactory.CreateLogger<Program>();

But (a heads up), when you update to using .NET5 preview8 or later you'll notice due to some API deprecations you'll end up using the below sample instead:

    using var loggerFactory = LoggerFactory.Create(builder =>
    {
         builder.AddSimpleConsole(opt => opt.IncludeScopes = true);
    });
    var logger = loggerFactory.CreateLogger<Program>();

Refer to: #34742 which introduced the changes.

@Ninds
Copy link
Author

Ninds commented Jul 28, 2020

But (a heads up),....

Thank you. That's good to know.

What exactly are you trying to do?

Nothing specific, I was on an exploration exercise.

The original context was to have a way of adding attributes to the logging output at the Microsoft.Extensions.Logging level without having to resort to the underlying implementation library , for example :

ILogEventEnricher in Serilog

or

LoggingEvent.Properties in Log4Net

Example of attributes I'd like to add are :

  • Name of the AssemblyLoadContext
  • Request Id (designated by the server when a new request arrives)

However, I was mistaken about how scopes work in the Logging API and thought that this couldn't be achieved with simple a BeginScope construct because I mistakenly thought it attached a local scope to a local ILogger.

I subsequently did this test and realised that scopes indeed achieve exactly what I was after. On the other hand it also raised a further question; "How does this (magic) work ?"

Moreover, I still find the initial observation counter-intuitive.

@Ninds
Copy link
Author

Ninds commented Jul 29, 2020

@Drawaes just explained the magic with reference to AsyncLocal<T>

@Ninds Ninds closed this as completed Jul 29, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 8, 2020
@eiriktsarpalis eiriktsarpalis added question Answer questions and provide assistance, not an issue with source code or documentation. and removed customer assistance labels Oct 5, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Extensions-Logging question Answer questions and provide assistance, not an issue with source code or documentation.
Projects
None yet
Development

No branches or pull requests

6 participants