首页 > 解决方案 > 如何使用依赖注入正确设置 Azure Functions 日志记录、实时指标和应用洞察

问题描述

大约一个月前,我注意到旧 Azure Functions 门户界面中的一些监视功能停止工作。我在Azure Functions Host GitHub上写了有关这些问题的更多详细信息,但我的特定问题尚未得到解答。

现在,Azure Functions 门户界面似乎默认为新的“管理体验”,看起来与 Azure 的其他部分更相似,因此,更明显的是,我们使用日志记录和跟踪的方式出现了问题。

我的问题是:是否有人有关于如何设置 Azure 函数日志记录、实时指标和应用程序洞察跟踪的代码示例,以便它:

  1. 使用依赖注入
  2. 与新的“管理体验”界面配合使用

目前,为了查看特定的 Azure Function 正在做什么,我必须转到旧的 Azure 界面并研究日志流。函数确实有效,它们在日志流中输出信息,但仅在旧界面中,并且在监控方面似乎没有太多其他工作。使用旧界面:

这些在一个月前工作得很好。现在,没有那么多。

使用新界面:

使用 Functions > Functions > [click on a function] 转到新界面中的特定功能:

我不明白为什么它在一个月前突然停止工作,以及为什么这么多东西似乎不适用于新界面。我们的 Functions 的 NuGet 包都是最新的。

在日志记录方面,记录器是依赖注入的,因此我们可以在多个类中使用它,而不仅仅是在默认的 Functions.cs 类中:

using Microsoft.Extensions.Logging;

public class EventForwarder
{
    private readonly ILogger<EventForwarder> log;

我们通过使用扩展方法记录,真的没什么特别的:

using Microsoft.Extensions.Logging;

public static class LoggerExtensions
{
    public static void Info(this ILogger log, string msg) => log.LogInformation(msg);

应用程序洞察跟踪器也使用此处建议的解决方法注入依赖项,即我们的 Startup.cs 看起来很精简:

using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(EventForwarder.Startup))]
namespace EventForwarder
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            // https://github.com/Azure/azure-functions-host/issues/5353
            builder.Services.AddSingleton(sp =>
            {
                var key = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
                return string.IsNullOrWhiteSpace(key) ? new TelemetryConfiguration() : new TelemetryConfiguration(key);
            });

我们正在执行 Http 重试跟踪,除其他外,如下所示:

public class HttpRetryPolicyService
{
    private readonly ILogger<HttpRetryPolicyService> log;
    private readonly TelemetryClient insights;

    public HttpRetryPolicyService(ILogger<HttpRetryPolicyService> log,
        TelemetryConfiguration insightsConfig)
    {
        this.log = log;
        insights = new TelemetryClient(insightsConfig);
    }
...
private void LogRetry(DelegateResult<HttpResponseMessage> message, TimeSpan delay, int attempt, Context context)
{
    if (message.Exception != null)
    {
        log.Warn($"Exception details: {message.Exception}");
        insights.Track(message.Exception);

我们正在使用扩展方法进行跟踪,如下所示:

using Microsoft.ApplicationInsights;

namespace EventForwarder.Static
{
    public static class TelemetryExtensions
    {
        public static void Track(this TelemetryClient insights, string eventName)
        {
            insights.TrackEvent(eventName);
            insights.Flush();
        }

我错过了什么?

编辑 #1:顺便说一句,不幸的是,在“发布”对话框中添加 Application Insights 作为服务依赖项并不能解决这些问题。

编辑#2:此外,我们的 Functions host.json 文件都看起来像这样:

{
    "version": "2.0",
    "healthMonitor": {
        "enabled": true,
        "healthCheckInterval": "00:00:10",
        "healthCheckWindow": "00:02:00",
        "healthCheckThreshold": 6,
        "counterThreshold": 0.80
    },
    "logging": {
        "fileLoggingMode": "always",
        "applicationInsights": {
            "enableLiveMetrics": true,
            "samplingSettings": {
                "isEnabled": true
            }
        },
        "logLevel": {
            "EventForwarder": "Information"
        }
    }
}

标签: c#azureazure-functionsazure-application-insights

解决方案


这就是破坏您的应用程序的原因,将其删除,一切正常:

// https://github.com/Azure/azure-functions-host/issues/5353
builder.Services.AddSingleton(sp =>
{
    var key = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
    return string.IsNullOrWhiteSpace(key) ? new TelemetryConfiguration() : new TelemetryConfiguration(key);
});

我的猜测是,既然已经推出了错误修复,解决方法实际上会破坏日志记录。

我创建了一个示例应用程序,其中日志记录和日志流工作得非常好,也有依赖注入。我使用 Windows 和 Linux 消费计划对其进行了测试。函数应用是使用 Azure 门户中的向导创建的,选择 .NET Core 3.1。请注意,TrackEvent它不会显示在函数的日志流中。它显示在 Application Insights Live Metrics 中。在显示“已连接”后,最长可能需要 30 秒才能显示实际日志。Live Metrics 视图效果更好,尤其是当您直接从应用程序洞察中打开时。

通过应用上述“解决方法”,我能够重现您的问题。没有它,一切正常。

完整示例:https ://github.com/LXBdev/Functions-V3-sample

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddScoped<MyService>();
    }
  "logging": {
    "applicationInsights": {
      "samplingExcludedTypes": "Request",
      "samplingSettings": {
        "isEnabled": true
      }
    },
    "logLevel": {
      "Functions_V3_sample": "Information"
    }
  }
public MyService(ILogger<MyService> logger, TelemetryClient telemetry)
{
    Logger = logger ?? throw new ArgumentNullException(nameof(logger));
    Telemetry = telemetry ?? throw new ArgumentNullException(nameof(telemetry));
}

public void Foo()
{
    Logger.LogInformation("Foo");
    Telemetry.TrackTrace("BarLog", Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
    Telemetry.TrackEvent("BarEvent");
}

更新:我的原始答案和示例中的 host.json 存在问题 - 由于https://github.com/Azure/azure-functions-host/issues/4345,日志并没有真正保留到 AppInsights 。我相应地更新了代码。

执行次数

日志流

实时指标

应用设置


推荐阅读