Search code examples
azure-functionsilogger

Custom ILogger scope values not working as expected


I'm missing something here as the numerous articles suggest it should work. The plan will be to create a custom logger implementation so I can store various values in a structured way.

However, for now the basics don't seem to work.

I'm trying to using scopes within ILogger to set certain values e.g. transactionId.

I'm using Azure Functions. In the startup I've added

public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddLogging();

Which works fine. In the function I'm trying this..

public class Test_Http
{
    private readonly ILogger logger;

    public Test_Http(ILogger<TestHttp> log)
    {
        this.logger = log;
    }


    [FunctionName("TestHttp")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        // This works fine, SomeId is replace.
        // When using a custom logger I can see 2 values in the state.
        logger.LogInformation("Message '{SomeId}'", "TheID");


        using (logger.BeginScope(new Dictionary<string, object>
        {
            ["SomeId"] = "SOME ID"
        }))
        {
            // SomeId is not replaced as I would expect.
            // State in a custom logger contains a single value.
            logger.LogInformation("A log from within scope {SomeId}");
        }

    }
}

What am I missing?!

Thanks.


Solution

  • As far as I know, when using a dictionary type inside logger.BeginScope method, then the key-value pair in the collection is added to the application insights telemetry as custom properties(doc is here). It will not replace the {SomeId} in your example.

    If you want to replace it, you need to explicitly add a value in logger.LogInformation method. For example:

            Dictionary<string, object> a = new Dictionary<string, object>
            {
                //SomeId only adds as a custom property for telemetry data.
                ["SomeId"] = "SOME ID"
            };
    
            using (logger.BeginScope(a))
            {
                //you need to explicitly add a value to replace {SomeId}
                logger.LogInformation("A log from within scope {SomeId}",a.Values.First());
            }