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

Function App中自定义类无法向App Insights写入日志的问题排查

问题描述

我正在开发一个自定义日志解决方案,需要同时将日志写入Azure Data Table和Application Insights。我创建了LogService类并通过依赖注入(DI)注入,供DataManager等类调用。计划在执行LogService.LogInformation方法时,先将日志写入App Insights,再通过Service Bus消息将日志插入Azure Data Table。

目前日志已成功写入Azure Data Table,但无法传入App Insights。我已确认配置了正确的APPINSIGHTS_INTRUMENTATIONKEY,并在Function App环境变量中设置了APPLICATIONINSIGHTS_CONNECTIONSTRING,同时安装了NuGet包:

<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />

请问还缺少什么配置才能让日志成功写入App Insights?

相关配置与代码如下:

Host.json

{
  "version": "2.0",
  "functionTimeout": "-1",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": false,
        "excludedTypes": "Request"
      }
    },
    "logLevel": {
      "Function": "Debug"
    }
  }
}

Startup.cs

public override void Configure(IFunctionsHostBuilder builder)
{
    //Add other dependencies here
    builder.Services.AddTransient<ILogService, LogService>();
    builder.Services.AddTransient<IDataManager, DataManager>();
    builder.Services.AddTransient<IAuditLogManager, AuditLogManager>();
    builder.Services.AddTransient<IRecordManager, RecordManager>();
    builder.Services.AddTransient<IUtilities, Utilities>();
    builder.Services.AddTransient<IEmailManager, EmailManager>();


    var connstring = Environment.GetEnvironmentVariable("DbConnection");

    builder.Services.AddDbContext<DataContext>(options =>
    {
        options.UseSqlServer(connstring,
                            sqlServerOptions => {
                                sqlServerOptions.CommandTimeout(180);
                                sqlServerOptions.EnableRetryOnFailure();
                            });
        options.EnableSensitiveDataLogging();
    });
}

LogService.cs

public class LogService : ILogService
{
    private readonly IConfiguration _config;
    private readonly ILogger<LogService> _log;      //Use built in Logger service to send to App Insights. 

    public LogService(IConfiguration config, ILogger<LogService> log)
    {
        _config = config;
        _log = log;
    }

    public void LogDebug(string message, string logType = "DEBUG")
    {
        LogInformation(message, logType);
    }

    public void LogError(string message, string logType = "ERROR")
    {
        LogInformation(message, logType);
    }

    public async void LogInformation(string message, string logType = "INFO")
    {
        //Log to built-in ILogger for App Insights and Mezmo
        if (logType.ToUpper().Contains("ERROR"))
            _log.LogError(message);
        if (logType.ToUpper().Contains("DEBUG"))
            _log.LogDebug(message);
        else
            _log.LogInformation(message);


        //Get time in CST and convert to the RowKey format.
        var cstDateTime = GetCurrentDateTimeCST();
        var rowKey = cstDateTime.ToString("yyyyMMdd.HHmmssff");

        string sbConnectionString = _config["LoggerURL"] ?? string.Empty;
        string sbQueue = _config["LogServiceBusQueue"] ?? string.Empty;
        var LoggingPartitionKey = _config["LoggingPartitionKey"] ?? string.Empty;


        // Create a Log Message and send to Service Bus 
        var logEntity = new LogEntity();
        logEntity.PartitionKey = LoggingPartitionKey;
        logEntity.RowKey = rowKey;
        logEntity.Message = message;
        logEntity.LogType = logType;

        //Serialize log object so be able to send in the message.
        var messageBody = JsonSerializer.Serialize(logEntity);

        try
        {
            ServiceBusClient serviceBusClient = new ServiceBusClient(sbConnectionString, new ServiceBusClientOptions()
            {
                TransportType = ServiceBusTransportType.AmqpWebSockets
            });
            ServiceBusSender serviceBusSender = serviceBusClient.CreateSender(sbQueue);
            await serviceBusSender.SendMessageAsync(new ServiceBusMessage(messageBody));
        }
        catch (Exception)
        {
            throw;
        }


    }

    public DateTime GetCurrentDateTimeCST()
    {
        DateTime cstDateTime = TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"));
        return cstDateTime;
    }
}
解决方案

你需要补充以下几个关键配置和代码调整,才能让日志成功写入Application Insights:

1. 注册Application Insights Worker服务

当前Startup.cs未将Application Insights集成到DI容器中,需在Configure方法内添加:

builder.Services.AddApplicationInsightsTelemetryWorkerService();

这一步会启用App Insights的日志收集能力,让ILogger实例能将日志推送到App Insights。

2. 调整Host.json日志级别配置

当前仅配置了Function命名空间的日志级别,需确保LogService所在命名空间的日志级别未被过滤。可添加全局默认级别或指定具体命名空间:

"logLevel": {
  "Function": "Debug",
  "Default": "Information",
  "YourNamespace.LogService": "Debug" // 替换为LogService实际所在的命名空间
}

如果LogService的日志级别高于你调用的方法级别(比如默认设为Warning,但你调用了LogInformation),日志会被系统过滤。

3. 修复异步方法的async void问题

LogInformation使用async void会导致日志可能在未完成发送时就被终止,Azure Functions环境下异步服务方法应返回Task:

public async Task LogInformation(string message, string logType = "INFO")

同时修改调用它的方法:

public async Task LogDebug(string message, string logType = "DEBUG")
{
    await LogInformation(message, logType);
}

public async Task LogError(string message, string logType = "ERROR")
{
    await LogInformation(message, logType);
}

async void仅适用于事件处理程序,普通服务方法使用会引发上下文管理问题,导致日志无法正常发送。

4. 验证环境变量名称

确认App Insights连接字符串的环境变量名称为APPLICATIONINSIGHTS_CONNECTION_STRING(注意下划线),而非你当前设置的APPLICATIONINSIGHTS_CONNECTIONSTRING,名称错误会导致App Insights无法读取配置。

完成以上调整后,重新部署Function App,日志即可正常写入Application Insights。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:55:57