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

.NET 7 Isolated: Logs missing from Application Insights / Log Analytics #2059

Closed
rodolfograve opened this issue Nov 13, 2023 · 7 comments
Closed

Comments

@rodolfograve
Copy link

rodolfograve commented Nov 13, 2023

Hello.

We are running an isolated Function using the latest packages. This is the list of relevant packages:

  1. Microsoft.ApplicationInsights.WorkerService v2.21.0
  2. Microsoft.Azure.Functions.Extensions v1.1.0
  3. Microsoft.Azure.Functions.Worker v1.20.0
  4. Microsoft.Azure.Functions.Worker.ApplicationInsights v1.1.0
  5. Microsoft.Azure.Functions.Worker.Sdk v1.16.1
  6. Microsoft.Extensions.Logging v7.0.0
  7. Microsoft.Extensions.Logging.Abstractions v7.0.1
  8. Microsoft.Extensions.Logging.Configuration v7.0.0

Dependency injection configuration looks like this:

builder.ConfigureFunctionsWorkerDefaults();
builder.ConfigureServices(services =>
{
   services.AddApplicationInsightsTelemetryWorkerService();
   services.ConfigureFunctionsApplicationInsights();
})

The host.json looks like this:

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {

      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request;Exception;Trace"
      }
    },
    "logLevel": {
      "default": "Information",
      "Function": "Information",
      "Host.Aggregator": "Information",
      "Host.Results": "Information"
    }
  },
  "extensions": {
    "http": {
      "hsts": {
        "isEnabled": true
      },
      "customHeaders": {
        "X-Content-Type-Options": "nosniff"
      }
    }
  }
}

However, logs generated from my code using Logger.LogInformation do not show up. Logs generated with Logger.LogWarning do show up.

There is a lot of disperse information out there about logging in Azure Functions:

  1. Here it is assumed that everything just works, i.e. logs will show up in App Insights.
  2. Here there is mention of some more advanced configuration, but I couldn't figure out how it applies to my use case (which I hope is a common, simple use case). There is also a huge "Important" warning which I think applies to my use case, but I couldn't find any mention on what to do about it. See image 1 below.
  3. Here it mentions the configuration for ILogger logs from App Insights, but the JSON schema does not match the one in host.json. In host.json there doesn't seem to be possible to include the "LogLevel" property inside "logging.applicationInsights" (see Image 2 below)

Image 1
image

Image 2
image

I couldn't find any complete examples.

Could someone please point me to an example of how to configure an Isolate Azure Function so that any Logger.LogInformation shows up in AppInsights and Log Analytics (where Logger is an ILogger obtained via Dependency Injection).

P.S. I already checked that nothing is getting sampled away:
image

I also checked that the log entries show up in the "Log stream" of the function on the Azure Portal.

@rodolfograve rodolfograve changed the title Logs missing from Application Insights / Log Analytics .NET 7 Isolated: Logs missing from Application Insights / Log Analytics Nov 13, 2023
@gabrielweyer
Copy link

I think you're looking for this documentation:

However, by default, the Application Insights SDK adds a logging filter that instructs the logger to capture only warnings and more severe logs. If you want to disable this behavior, remove the filter rule as part of service configuration:

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .ConfigureLogging(logging =>
    {
        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();

@rodolfograve
Copy link
Author

Thank you, @gabrielweyer. This worked.

This seems like a quite fragile way of doing things, involving:

  1. A magic string, which I replaced with rule.ProviderName == typeof(Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider).FullName
  2. A hidden dependency not only on the classes of a separate package that evolves independently, but also on what that other code does at runtime.

I hope the Functions team finds a better way to wrap this up without exposing their dependency on the AppInsights SDK... perhaps a settings in their WorkerOptions?

@brettsam
Copy link
Member

Ideally, we'd like Application Insights to remove the rule themselves -- it trips up a lot of people (not just Functions users...):

But I don't believe this will happen without a major version bump from that package. We see so many people struggling with this, even with the documentation, templates, etc, that it may be worth creating our own FunctionsApplicationInsightsOptions object with some flag that does the same thing as above.

We're trying really hard not to mess with App Insights defaults as that has caused even more chaos in the past. Unfortunately, this default is causing a bit of a support issue as we get so many questions about it. We redirect customers to the App Insights (and Functions) docs that explain this, but it's still not a good experience.

BTW -- there are other ways around this filter -- see some of the links above. But we thought the best way was to show how you can remove it altogether, rather than layering more rules on top to achieve the same thing.

@Krumelur
Copy link

I tried above solution and still don't get anything below "warning". I debugged and noticed that there isn't a single rule (options.Rules is NULL), therefore there's nothing to be removed. Ideas?

@stevencreaney
Copy link

I tried above solution and still don't get anything below "warning". I debugged and noticed that there isn't a single rule (options.Rules is NULL), therefore there's nothing to be removed. Ideas?

I had a similar issue, and once I moved the ConfigureLogging to the end of the chain, it started working, maybe check that?

@joeyeng
Copy link

joeyeng commented Aug 30, 2024

I tried above solution and still don't get anything below "warning". I debugged and noticed that there isn't a single rule (options.Rules is NULL), therefore there's nothing to be removed. Ideas?

I had a similar issue, and once I moved the ConfigureLogging to the end of the chain, it started working, maybe check that?

This makes this issue even more ridiculous

@progmars
Copy link

progmars commented Nov 8, 2024

This is so convoluted.

It's good and understandable that AppInsights adds Warning level as default because we don't want it to spam too much.
However, the fact that we need to mess with AppInsights' internal filters to be able to add our own information messages for our own categories to AppInsights is just ugly.

And what would be the consequences of removing that filter? Would we start seeing more internal .net core logging information than we want? Then what is the proper way to set up AppInsights and keep all the default log levels as Warnings (as it should be) and have our own logging configured by categories, also considering that we are using isolated model?

Do we need everything of this, or is something redundant?

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;

var host = new HostBuilder()
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
                .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables();
    })
    .ConfigureLogging((hostContext, logging) =>
    {
        // need to load configs explicitly, otherwise, it ignores
        // host.json and appsettings.json  ??
        logging.AddConfiguration(hostContext.Configuration.GetSection("logging"));
        logging.AddApplicationInsights();
    })
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.AddOptions();

        // Need extra configuration because AppInsights will only log per default Warning and above.
        // https://github.com/microsoft/ApplicationInsights-dotnet/issues/2610#issuecomment-1316672650
        // So remove the default logger rule and load our own rules from appsettings.json or host.json.
        services.Configure<LoggerFilterOptions>(options =>
        {
            var toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == typeof(Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider).FullName);
            if (toRemove is not null)
            {
                options.Rules.Remove(toRemove);
            }
        });
    })
    .ConfigureFunctionsWorkerDefaults()
    .Build();

await host.RunAsync();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants