Search code examples
azureazure-functionsserilogazure-log-analyticsazure-functions-isolated

HttpTrigger in Isolated Azure Function creating lots of log noise


I have a legacy in-process azure function app on .NET 6.x that I am converting over to use the isolated runtime ahead of a later migration to .NET 8. The conversion was done following the steps outlined at Migrate .NET apps from the in-process model to the isolated worker model with some minor deviations that were app specific. Our App is set up to log to azure using Serilog. Here is the relevant parts of the Program.cs file

var host = new HostBuilder()
.ConfigureServices(services =>
{

    services.AddApplicationInsightsTelemetryWorkerService();
    services.ConfigureFunctionsApplicationInsights();
}).ConfigureLogging(logBuilder => {
    //we add dispose: false for reasons I won't get into here
    logBuilder.AddSerilog(dispose: false);
})
.Build();

And here is the serilog config in the appsettings.json

"Serilog": {
  "Using": [
    "Serilog.Sinks.AzureAnalytics",
    "Serilog.Sinks.Console"
  ],
  "MinimumLevel": "Information",
  "WriteTo": [
    {
      "Name": "AzureAnalytics",
      "Args": {
        "logName": "<Redacted>",
        "workspaceId": "<Redacted>",
        "authenticationId": "<Redacted>"
      }
    },
      {
          "Name": "Console",
          "Args": {
              "logName": "<Redacted>"
          }
      }                        
  ],
  "Enrich": [
    "AppName"
  ],
  "Properties": {
    "AppName": "<Redacted>"
  }
},

The logging configuration is instantiate elsewhere for code sharing reasons but it ammounts to

var loggingConfiguration = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .ReadFrom.Configuration(configuration);

Both of those files are pretty much out of the box. After deploying the app to azure, we observed a bunch of new log noise making it to our Azure logs Azure Log noise after converting to Isolated Runtime

We would like to filter out this noise to keep our logs meaningful. It looks like all of the events we want to filter out are coming from two sources based on the out of the box SourceContext column in the log book

  • Microsoft.AspNetCore.Hosting.Diagnostics
  • Microsoft.AspNetCore.Routing.EndpointMiddleware

I found this similar question and tried adding the following to our host.json file but this didn't remove the logs.

{
    "version": "2.0",
    "logging": {
        "IncludeScopes": false,
        "LogLevel": { //added this block
            "Default": "Information",
            "System": "None",
            "Microsoft": "None"
        },
        "applicationInsights": {
            "enableDependencyTracking": true,
            "dependencyTrackingOptions": {
                "enableSqlCommandTextInstrumentation": true
            },
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request"
            }
        }
    },
    "functionTimeout": "05:00:00"
}

I assume that we're just don't have the correct entry added to the LogLevel block but additional microsoft docs I've found aren't helping me identify exactly what it should be.

This first link has as section near the bottom to disable everything except user initiated logs, but this has to be done for each individual HTTP trigger function which for our purpose is simply not maintainable.

The second link above calls out Host.Results and Functions but has a warning block noting that tweaking these two settings may remove telemetry that we do want to keep

So my specific question is how can I remove the additional log noise from our azure logs?


Solution

  • The logging configuration is instantiated elsewhere for code sharing reasons but it amounts to:

    var loggingConfiguration = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .ReadFrom.Configuration(configuration); ```
    

    I think this is adding log noise to your function, as it has been set to the minimum level to debug.

    In Azure Function, the default level is the information level, which is defined in the file host.json.

    I am using an HTTP Trigger here.

    Function1.cs:

    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Routing;
    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp3
    {
        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.LogInformation("C# HTTP trigger function processed a request.");
                return new OkObjectResult($"Welcome to Azure Functions!");
            }
        }
    }
    

    FunctionApp3.csproj:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFramework>net7.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.20.1" />
        <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.21.0" />
        <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.1.0" />
        <PackageReference Include="Serilog" Version="3.1.1" />
        <PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
        <PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
      </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>
    

    host.json:

    {
        "version": "2.0",
        "logging": {
            "applicationInsights": {
                "samplingSettings": {
                    "isEnabled": true,
                    "excludedTypes": "Request"
                },
                "enableLiveMetricsFilters": true
            }
        }
    }
    

    OUTPUT:

    Before filtering the logs for Serilog :

    Program.cs:

    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using Serilog;
    using Serilog.Events;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWebApplication()
        .ConfigureServices(services =>
        {
            services.AddApplicationInsightsTelemetryWorkerService();
            services.ConfigureFunctionsApplicationInsights();
            services.AddLogging(logbuilder =>
            {
                logbuilder.AddSerilog(new LoggerConfiguration()
                    .WriteTo.Console()
                    .CreateLogger()); ;
            });
        })
        .Build();
    
    host.Run();
    
    

    I was also getting information level noise log. local :

    Azure :

    After filtering the logs for Serilog :

    We would like to filter out this noise to keep our logs meaningful. It looks like all of the events we want to filter out are coming from two sources based on the out of the box SourceContext column in the logbook

    • Microsoft.AspNetCore.Hosting.Diagnostics
    • Microsoft.AspNetCore.Routing.EndpointMiddleware

    I have filtered these two sources

    Program.cs:

    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using Serilog;
    using Serilog.Events;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWebApplication()
        .ConfigureServices(services =>
        {
            services.AddApplicationInsightsTelemetryWorkerService();
            services.ConfigureFunctionsApplicationInsights();
            services.AddLogging(logbuilder =>
            {
                logbuilder.AddSerilog(new LoggerConfiguration()
                    .MinimumLevel.Override("Microsoft.AspNetCore.Hosting.Diagnostics", LogEventLevel.Warning)
                    .MinimumLevel.Override("Microsoft.AspNetCore.Routing.EndpointMiddleware", LogEventLevel.Warning)
                    .WriteTo.Console()
                    .CreateLogger()); ;
            });
        })
        .Build();
    
    host.Run();
    

    Local :

    Azure :