【问题标题】:Why is the ILogger injected in my Azure Function v2 missing the APPINSIGHTS_INSTRUMENTATIONKEY?为什么在我的 Azure Function v2 中注入的 ILogger 缺少 APPINSIGHTS_INSTRUMENTATIONKEY?
【发布时间】:2026-01-29 11:00:01
【问题描述】:

我有一个 Azure Function v2,如下所示:

public sealed class FindAccountFunction
{
    private readonly IAccountWorkflow m_accountWorkflow;

    public FindAccountFunction(ILogger<FindAccountFunction> logger)
    {
        m_logger = logger;
    }

    [FunctionName("FindAccount")]
    public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "GET", Route = "v1/accounts/")] HttpRequest httpRequest)
    {
        // Do stuff.
        m_logger.LogInformation("Duuuddde");
    }
}

different question 中所述,正在注入记录器:

[assembly: WebJobsStartup(typeof(Startup))]

public sealed class Startup : IWebJobsStartup
{
    public void Configure(IWebJobsBuilder webJobsBuilder)
    {
        // Registers other services...

        // -- UPDATE - The AddLogging must be called here --
        webJobsBuilder.Services.AddLogging();
    }
}

然后我通过 HTTP 请求触发我的函数,并转到 Azure DevOps 上的函数门户,查看是否实际打印了日志:

我只看到表明函数运行成功的日志,但是我没有看到我的日志。

问题

为什么在我的 Azure Function v2 中注入的 ILogger 缺少 APPINSIGHTS_INSTRUMENTATIONKEY

更新

当我查看注入的ILogger 时,我可以看到 Application Insights Provider 的 InstrumentationKey 没有设置。这同样适用于注入 ILogger 的 ctor,也适用于 Run 方法中注入的 ILogger

对于我的本地测试,检测密钥在local.settings.json 文件中声明:

【问题讨论】:

    标签: c# azure logging dependency-injection azure-functions


    【解决方案1】:

    Logger 作为函数参数传递:

    public async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Function, Verbs.Get, Route = "v1/accounts/")] HttpRequest httpRequest, ILogger log)
    {
        // ...
    }
    

    【讨论】:

    • 最新的运行时 Azure Function 使 ILogger 不仅可以注入到 Function 本身,还可以注入到注入的服务中。即使我将 ILogger 添加到 Run 方法本身,我很可能也会遇到与服务相同的问题:我在哪里可以看到这些服务的日志?
    • 好的。你看过github.com/Ruard/ProcsIT.Azure.Functions.DependencyInjection 吗?我没试过。
    • 似乎与我的问题无关:它看起来像一个自定义解决方案,具有名为 Inject 的自定义属性。我正在使用 services.AddLogging();这应该完成所有这些。
    【解决方案2】:
        services.AddSingleton(context => 
            {
                var factory = context.GetRequiredService<ILoggerFactory>();
                var loggingConfiguration = <get your app insights's instrumentation key from your configuration provider>;
                var logger = new LoggerConfiguration()
                        .WriteTo
                        .ApplicationInsightsEvents(loggingConfiguration.ApplicationInsightsKey)
                        .CreateLogger();
                return factory.AddSerilog(logger).CreateLogger("MyLogger");
            });
    

    在使用您的应用洞察获取遥测数据之前,需要配置记录器。设计使用(Serilog)模式可能会有所不同,因为这只是一个需要解释的存根。

    【讨论】:

      【解决方案3】:

      我对不同的设置变体感到困惑(ILogger vs ILoggerFactory vs 其他东西)。

      在我的Startup 类中,调用AddLogging 是正确的(无论是否具有最低级别,只要在此处或host.json 文件中的某处定义)。

      using InjectionHttpClientFactory;
      using Microsoft.Azure.WebJobs;
      using Microsoft.Azure.WebJobs.Hosting;
      using Microsoft.Extensions.DependencyInjection;
      using Microsoft.Extensions.Logging;
      
      [assembly: WebJobsStartup(typeof(Startup))]
      
      namespace InjectionHttpClientFactory
      {
          public sealed class Startup : IWebJobsStartup
          {
              public void Configure(IWebJobsBuilder webJobsBuilder)
              {
                  webJobsBuilder.Services.AddLogging();
              }
          }
      }
      

      在 Azure Function 中,如果我将 HttpClient 指定为参数,则会出现错误:

      Microsoft.Extensions.DependencyInjection.Abstractions:无法 解析“Microsoft.Extensions.Logging.ILogger”类型的服务,而 尝试激活“XXX”

      但是,如果我指定 ILoggerFactory,它确实有效。不知何故,为空的检测密钥属性没有影响。

      我已更新 host.json 文件以包含具有最低严重性级别的日志记录信息以及 Application Insights 的配置信息:

      {
        "version": "2.0",
        "logging": {
          "fileLoggingMode": "debugOnly",
          "logLevel": {
            "default": "Trace"
          },
          "applicationInsights": {
              "samplingSettings": {
                "isEnabled": true,
                "maxTelemetryItemsPerSecond" : 5
              }
          }
        }
      }
      

      更新

      正如 cmets 中提到的,Microsoft 发布了一个 update,它引入了 FunctionsStartup 类,这应该是执行此操作的首选方式。

      [assembly: FunctionsStartup(typeof(MyNamespace.Startup))]
      
      namespace MyNamespace
      {
          public class Startup : FunctionsStartup
          {
              public override void Configure(IFunctionsHostBuilder builder)
              {
                  builder.Services.AddHttpClient();
                  builder.Services.AddSingleton((s) => {
                      return new CosmosClient(Environment.GetEnvironmentVariable("COSMOSDB_CONNECTIONSTRING"));
                  });
                  builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
              }
          }
      }
      

      【讨论】:

      最近更新 更多