You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何ILogger.LogError可显示于Application Insights而LogInformation不行?

问题:Azure Functions中ILogger.LogInformation日志无法在Application Insights中显示,仅LogError正常

在Azure Functions(.NET Isolated模式)中注入ILogger<MyClassName>后,调用Logger.LogInformation输出的日志能在Application Insights的**实时指标(Live Metrics)**中看到,但通过InvocationId或日志关键词搜索时找不到结果;而Logger.LogError的日志能正常在搜索结果中显示。

相关代码与配置

业务代码

public async ValueTask DeleteMessageAsync(string chatId, int messageId)
{
    Logger.LogInformation(
        "Deleting message: {chatId} {messageId}",
        chatId,
        messageId);

    try
    {
        await TelegramBotClient.DeleteMessageAsync(chatId, messageId);
    }
    catch (ApiRequestException ex)
        when (ex.ErrorCode == (int)HttpStatusCode.BadRequest)
    {
        Logger.LogError(ex, "Could not Delete message");
    }
}

host.json日志配置

"logging": {
    "applicationInsights": {
        "samplingSettings": {
            "isEnabled": true,
            "excludedTypes": "Request"
        },
        "enableLiveMetricsFilters": true
    },
    "DurableTask.AzureStorage": "Information",
    "DurableTask.Core": "Information",
    "logLevel": {
        "Default": "Information",
        "Microsoft": "Information",
        "Microsoft.Hosting.Lifetime": "Information"
    }
}

主机构建代码

IHost host = new HostBuilder()
    .AddServiceDefaults(useOtlpExporter: false, isDevelopment: true)
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.AddSingleton<ITelegramBroadcastService, TelegramBroadcastService>();
        services.AddSingleton<IAuthorizationService, AuthorizationService>();
        services.AddDurableTaskClient(x =>
        {
        });
        services.AddAzureClients(clientBuilder =>
        {
            clientBuilder.AddBlobServiceClient(Environment.GetEnvironmentVariable("AzureWebJobsStorage"));
        });
    })
    .ConfigureAppConfiguration((context, config) =>
    {
        if (context.HostingEnvironment.IsDevelopment())
            config.AddUserSecrets<Program>();
    })
    .Build();

host.Run();

AddServiceDefaults扩展代码(Aspire默认生成)

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;

namespace Microsoft.Extensions.Hosting;

public static class Extensions
{
    public static T AddServiceDefaults<T>(this T builder, bool useOtlpExporter, bool isDevelopment)
        where T : IHostBuilder
    {
        builder.ConfigureOpenTelemetry(
            useOtlpExporter: useOtlpExporter,
            isDevelopment: isDevelopment);
        builder.AddDefaultHealthChecks();
        builder.AddServiceDiscovery();
        return builder;
    }

    public static T AddServiceDiscovery<T>(this T builder)
        where T : IHostBuilder
    {
        builder.ConfigureServices(services =>
        {
            services.AddServiceDiscovery();
        });
        return builder;
    }

    public static T ConfigureHttpClientDefaults<T>(this T builder)
        where T : IHostBuilder
    {
        builder.ConfigureServices(services =>
        {
            services.ConfigureHttpClientDefaults(http =>
            {
                // Turn on resilience by default
                http.AddStandardResilienceHandler();

                // Turn on service discovery by default
                http.UseServiceDiscovery();
            });
        });
        return builder;
    }

    public static T ConfigureOpenTelemetry<T>(this T builder, bool useOtlpExporter, bool isDevelopment)
        where T : IHostBuilder
    {
        builder.ConfigureLogging(logging =>
        {
            logging.AddOpenTelemetry(telemetry =>
            {
                telemetry.IncludeFormattedMessage = true;
                telemetry.IncludeScopes = true;
            });
        });

        builder.ConfigureServices(services =>
        {
            services.AddOpenTelemetry()
                .WithMetrics(metrics =>
                {
                    metrics.AddRuntimeInstrumentation()
                           .AddBuiltInMeters();
                })
                .WithTracing(tracing =>
                {
                    if (isDevelopment)
                    {
                        // We want to view all traces in development
                        tracing.SetSampler(new AlwaysOnSampler());
                    }

                    tracing.AddAspNetCoreInstrumentation()
                           .AddGrpcClientInstrumentation()
                           .AddHttpClientInstrumentation();
                });
        });

        builder.AddOpenTelemetryExporters(useOtlpExporter);

        return builder;
    }

    private static T AddOpenTelemetryExporters<T>(this T builder, bool useOtlpExporter)
        where T : IHostBuilder
    {
        builder.ConfigureServices(services =>
        {
            if (useOtlpExporter)
            {
                services.Configure<OpenTelemetryLoggerOptions>(logging => logging.AddOtlpExporter());
                services.ConfigureOpenTelemetryMeterProvider(metrics => metrics.AddOtlpExporter());
                services.ConfigureOpenTelemetryTracerProvider(tracing => tracing.AddOtlpExporter());
            }

            // Uncomment the following lines to enable the Prometheus exporter (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)
            //services
            //    .AddOpenTelemetry();
            //    .WithMetrics(metrics => metrics.AddPrometheusExporter());

            // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.Exporter package)
            //services
            //    .AddOpenTelemetry()
            //    .UseAzureMonitor();
        });
         
        return builder;
    }

    public static T AddDefaultHealthChecks<T>(this T builder)
        where T : IHostBuilder
    {
        builder.ConfigureServices(services =>
        {
            services.AddHealthChecks()
                // Add a default liveness check to ensure app is responsive
                .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
        });
        return builder;
    }

    public static WebApplication MapDefaultHealthCheckEndpoints(this WebApplication app)
    {
        // Uncomment the following line to enable the Prometheus endpoint (requires the OpenTelemetry.Exporter.Prometheus.AspNetCore package)
        // app.MapPrometheusScrapingEndpoint();

        // All health checks must pass for app to be considered ready to accept traffic after starting
        app.MapHealthChecks("/health");

        // Only health checks tagged with the "live" tag must pass for app to be considered alive
        app.MapHealthChecks("/alive", new HealthCheckOptions
        {
            Predicate = r => r.Tags.Contains("live")
        });

        return app;
    }

    private static MeterProviderBuilder AddBuiltInMeters(this MeterProviderBuilder meterProviderBuilder) =>
        meterProviderBuilder.AddMeter(
            "Microsoft.AspNetCore.Hosting",
            "Microsoft.AspNetCore.Server.Kestrel",
            "System.Net.Http");
}

Azure门户应用设置

{
    "deployment_branch": "master",
    "SCM_TRACE_LEVEL": "Verbose",
    "SCM_COMMAND_IDLE_TIMEOUT": "60",
    "SCM_LOGSTREAM_TIMEOUT": "7200",
    "SCM_BUILD_ARGS": "",
    "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=...AccountKey=...=;EndpointSuffix=core.windows.net",
    "AzureWebJobsSecretStorageType": "Blob",
    "WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED": "1",
    "APPLICATIONINSIGHTS_CONNECTION_STRING": "InstrumentationKey=...IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/",
    "WEBSITE_SLOT_NAME": "Production",
    "SCM_USE_LIBGIT2SHARP_REPOSITORY": "0",
    "WEBSITE_SITE_NAME": "...",
    "FUNCTIONS_EXTENSION_VERSION": "~4",
    "WEBSITE_AUTH_ENABLED": "False",
    "ScmType": "None",
    "WEBSITE_RUN_FROM_PACKAGE": "1",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}

解决方案

1. 解决OpenTelemetry与Application Insights的日志路由冲突

代码同时启用了OpenTelemetry日志采集和Application Insights原生SDK,但OpenTelemetry未配置导出到Application Insights,导致持久化日志丢失。

  • 安装NuGet包:Azure.Monitor.OpenTelemetry.Exporter
  • 修改AddOpenTelemetryExporters方法,取消Azure Monitor导出器的注释:
// 启用Azure Monitor导出器
services
    .AddOpenTelemetry()
    .UseAzureMonitor();

2. 临时禁用日志采样验证

当前采样设置可能过滤了Info级日志,先禁用采样确认问题:
修改host.json中的samplingSettings:

"applicationInsights": {
  "samplingSettings": {
    "isEnabled": false,
    "excludedTypes": "Request"
  },
  "enableLiveMetricsFilters": true
}

验证正常后,可根据需求调整采样规则(如设置maxTelemetryItemsPerSecond)。

3. 配置OpenTelemetry日志级别过滤

确保OpenTelemetry采集Info及以上级别的日志,在ConfigureOpenTelemetry的日志配置中添加过滤规则:

logging.AddOpenTelemetry(telemetry =>
{
    telemetry.IncludeFormattedMessage = true;
    telemetry.IncludeScopes = true;
    // 指定你的命名空间,确保Info级日志被采集
    telemetry.AddFilter("YourNamespace.*", LogLevel.Information);
    // 设置服务名称,便于日志筛选
    telemetry.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("YourFunctionAppName"));
});

4. 调整服务注册顺序

在.NET Isolated模式下,将Application Insights服务注册移到AddServiceDefaults之前,避免日志提供者冲突:

IHost host = new HostBuilder()
    .AddApplicationInsightsTelemetryWorkerService()
    .AddServiceDefaults(useOtlpExporter: false, isDevelopment: true)
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        services.ConfigureFunctionsApplicationInsights();
        // ...其他服务注册
    })
    // ...其他配置
    .Build();

内容的提问来源于stack exchange,提问作者Peter Morris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:15:54