4

I am writing Azure functions in dotnet 8 using v4 dotnet-isolated.

When Deployed to Azure I want to log custom trace messages at level "Debug" and above to application insights. When debugging locally I want to see all my custom logs at level 'Trace' and above.

I would also like the deployed log level to be changeable through configuration so that once the function has been deployed a while it can be easily changed to Information and then Warning.

I will include my code further down, but here is a summary of what I have done so far:

  • Set the log level for "function" in the host.json file to "Debug"
  • Turned off sampling
  • Removed the default "Warning" filter in Program.cs
  • Called SetMinimumLevel(LogLevel.Trace) in Program.cs
  • In local.settings.json I have set "AzureFunctionsJobHost__logging__logLevel__function": "Trace" to enable local trace messages.

This all works very well when running locally. I get trace messages coming through in the console. I can change the value in local.settings.json and the logs are filtered as expected. I can remove the local settings entry and then I get Debug and above locally and I can also change the level in host.json and logs are filtered as expected.

It becomes a problem when I actually publish to azure. In azure I get all logs, including trace always. Adding AzureFunctionsJobHost__logging__logLevel__function has no effect, nor does changing the logging values in host.json. host.json with a log level of "Error" still logs Trace to Critical in application insights.

I've checked the host.json file and the correct one is deployed.

The only thing that seems to effect log levels once deployed is the logger.SetMinimumLevel() The deployed code in azure always logs to that level and above.

Why?

host.json

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "function": "Debug"
    },
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": false,
        "excludedTypes": "Request"
      },
      "enableLiveMetricsFilters": true
    }
  }
}

Program.cs



using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })

     .ConfigureLogging(logging =>
    {
        logging.SetMinimumLevel(LogLevel.Trace);  //this controls the minimum log level allowed in config (you still need to set in config, usually to Information)
        logging.Services.Configure<LoggerFilterOptions>(options =>
        {
             LoggerFilterRule? defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
            if (defaultRule is not null)
             {
                 options.Rules.Remove(defaultRule);
             }
        });
    })
    .Build();

host.Run();

the function


using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
 
namespace Basl
{
    public class TestLogging
    {
        private readonly ILogger<TestLogging> _logger;
 
        public TestLogging(ILogger<TestLogging> logger)
        {
            _logger = logger;
        }
 
        [Function("TestLogging")]
        public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
        {
            _logger.LogTrace("This is a TRACE log message");
            _logger.LogDebug("This is a DEBUG log message");
            _logger.LogInformation("This is a INFORMATION log message");
            _logger.LogWarning("This is a WARNING log message");
            _logger.LogError("This is a ERROR log message");
            _logger.LogCritical("This is a CRITICAL log message");
            return new  OkObjectResult($"Log Messages tested at {DateTime.UtcNow.ToString()}");
        }
    }
}

project file csproj

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.4" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
</ItemGroup>
</Project>

2 Answers 2

1

host.json with a log level of "Error" still logs Trace to Critical in application insights.

By using below code and configuration getting logs below log level which mentioned in host.json.

  • I have created Http trigger function with runtime stack .NET 8.0 isolated.
  • The logs which trying to get particular function loglevel set in host.json like below:

host.json:

{
  "version": "2.0",
  "logging": {
    "logLevel": {
      "Function.Function1": "Debug"
    },
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"

      },
      "enableLiveMetricsFilters": true
    }
  }
}

Function1.cs:

public class Function1
{
    private readonly ILogger<Function1> _logger;

    public Function1(ILogger<Function1> logger)
    {
        _logger = logger;
    }

    [Function("Function1")]
    public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
    {
        _logger.LogTrace("This is a TRACE log message");
        _logger.LogDebug("This is a DEBUG log message");
        _logger.LogInformation("This is a INFORMATION log message");
        _logger.LogWarning("This is a WARNING log message");
        _logger.LogError("This is a ERROR log message");
        _logger.LogCritical("This is a CRITICAL log message");
        _logger.LogInformation("C# HTTP trigger function processed a request.");
        return new OkObjectResult("Welcome to Azure Functions!");
    }
}

Program.cs:

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.Configure<LoggerFilterOptions>(options =>
        {
            LoggerFilterRule toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

            if (toRemove is not null)
            {
                options.Rules.Remove(toRemove);
            }
        });
    })
    .ConfigureAppConfiguration((hostContext, config) =>
    {
        config.AddJsonFile("host.json", optional: true);
    })
    .ConfigureLogging((hostingContext, logging) =>
    {
        logging.AddApplicationInsights(console =>
        {
            console.IncludeScopes = true;
        });

        logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
    })
    .Build();

host.Run();

enter image description here

  • I have published the function into azure portal.

enter image description here

  • I have ran the function and got expected logs in azure portal as well. check below:

enter image description here

Output:

enter image description here

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

You haven't got the "Trace" or "Debug" message locally or "Debug" message when deployed. It cuts off a Information. Also I want to avoid naming each individual function in hosts as its difficult to manage when you have lots of projects each with lots of functions inside.
I haven't get trace logs because trace log level is lower than debug and also if need debug also we need to mention "default":"none" in host.json. if we don't need to specify particular function name in log level need to mention "Function":"Debug" (F should be capital) . For this refer this DOC
Thanks for taking the time to answer, I really appreciate it, I just think you are maybe misunderstanding my issue which is that the configuration in host.json is not being respected once deployed. In your example you have "Debug" set in config but are actually getting "information". which is the default min log level. If you lower the default level to trace you will see that debug in your hosts will take effect locally but not when deployed. add logging.SetMinimumLevel(LogLevel.Trace) in program cs
if add the "default": "Debug" in host.json log level will get debug logs also. please check this configuration. Refer this DOC for log levels.
0

I have just had the same issue and found that the solution by Pavan above got me most of the way. I did also have to modify the host.json file. Rather than using Function in my host.json to set the logging level for my function when I put in my project namespace then that was recognised as the category by azure and started logging to application insights from that level above. I came accross this in docs and that explains it. https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-class-library?tabs=v4%2Ccmd#ilogger

Categories prefixed with Function assume you're using an ILogger instance. If you choose to instead use an ILogger, the category name may instead be based on T.

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      },
      "enableLiveMetricsFilters": true
    },
    "logLevel": {
      "default": "Debug",
      "MyProjectNamespace": "Warning"
    }
  }
} 

With Warning level logged to ApplicationInsights. Application insights with warning logging level

I changed the logging level to debug: Application insights with debug logging level

Program.cs

 .ConfigureServices(services =>
 {
     services.AddApplicationInsightsTelemetryWorkerService();
     services.ConfigureFunctionsApplicationInsights();
     services.Configure<LoggerFilterOptions>(options =>
     {
        
         // The Application Insights SDK adds a default logging filter that instructs ILogger to capture only Warning and more severe logs.
         // Application Insights requires an explicit override.
         // Log levels can also be configured using appsettings.json.
         // For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service#ilogger-logs
         LoggerFilterRule defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
             == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

         if (defaultRule is not null)
         {
             options.Rules.Remove(defaultRule);
         }
     });
 })
  .ConfigureAppConfiguration((hostContext, config) =>
  {
      config.AddJsonFile("host.json", optional: true);
  })
.ConfigureLogging((hostingContext, logging) =>
{

    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.