Skip to content

Microsoft.Extensions.Logging ILogger scopes are lost in async stream after yield return #47951

@CXuesong

Description

@CXuesong

Opened via #47802 (comment). While the previous issue focuses on the decision of whether AsyncLocals (and execution context) should flow acress yield return in async streams, I hope the current one can be triaged to MEL owners, in order to decide on whether the following scoped logging scenario should be supported.

Description

Consider the following use case on .NET 5.0 [.NET Fiddle]

using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;

async IAsyncEnumerable<int> IntSequence(ILogger logger)
{
    using var scope = logger.BeginScope("My scope");
    logger.LogWarning("Log 1");
    yield return 10;
    logger.LogWarning("Log 2");
    yield return 20;
    logger.LogWarning("Log 3");
    yield return 30;
}

using var lf = LoggerFactory.Create(b => b.AddSimpleConsole(o => o.IncludeScopes = true));
await foreach (var i in IntSequence(lf.CreateLogger("Root")))
{
    Console.WriteLine(i);
}

My expectation is

10
20
30
warn: Root[0]
      => My scope
      Log 1
warn: Root[0]
      => My scope
      Log 2
warn: Root[0]
      => My scope
      Log 3

Actual output is

10
20
30
warn: Root[0]
      => My scope
      Log 1
warn: Root[0]
      Log 2
warn: Root[0]
      Log 3

Scopes are lost for Log 2 and Log 3.

Configuration

  • .NET 5 / .NET 6.0.100-preview.1.21103.9
  • Microsoft.Extensions.Logging.Console v5.0.0

Regression?

N/A

Other information

The root cause of this issue is #47802, and LoggerFactoryScopeProvider uses AsyncLocal to keep logging scope information.

/// <summary>
/// Default implementation of <see cref="IExternalScopeProvider"/>
/// </summary>
internal class LoggerFactoryScopeProvider : IExternalScopeProvider
{
private readonly AsyncLocal<Scope> _currentScope = new AsyncLocal<Scope>();
private readonly ActivityTrackingOptions _activityTrackingOption;

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-Extensions-LoggingquestionAnswer questions and provide assistance, not an issue with source code or documentation.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions