如何使用依赖项注入正确设置 Azure Functions 日志记录、实时指标和应用程序洞察

Lin*_*oxy 13 c# azure azure-application-insights azure-functions

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

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

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

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

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

  • 调用日志,即您按下“函数(只读)> [函数] > 监视器下的“监视器”链接时获得的那个,即使根据日志确实调用了这些函数,也根本没有显示任何调用。
  • 实时应用指标链接会导致默认“不可用:您的应用离线或使用旧版 SDK”以及一些动画演示图表。

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

使用新界面:

  • 监控 > 日志流除了“已连接!”这个词外什么都不显示,无论详细程度如何。
  • 监控 > 日志流 > 在实时指标中再次打开只会产生默认的“不可用:您的应用离线或使用旧版 SDK”。

使用功能 > 功能 > [单击功能] 转到新界面中的特定功能:

  • Developer > Code + Test > Test-button > Run,弹出Logs窗口,只说“Connected!” 没有别的,再次不管冗长。
  • Monitor > Invocations,这里没有注册任何调用痕迹,尽管该函数显然是根据旧的接口日志流调用的。
  • 监视器> 日志,再次,只是说“已连接!”,不管冗长。

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

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

using Microsoft.Extensions.Logging;

public class EventForwarder
{
    private readonly ILogger<EventForwarder> log;
Run Code Online (Sandbox Code Playgroud)

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

using Microsoft.Extensions.Logging;

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

应用程序洞察跟踪器也是使用此处建议的解决方法注入的依赖项,即我们的 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);
            });
Run Code Online (Sandbox Code Playgroud)

我们正在执行 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);
Run Code Online (Sandbox Code Playgroud)

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

using Microsoft.ApplicationInsights;

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

我错过了什么?

编辑#1:顺便说一下,在发布对话框中添加应用程序的见解服务依赖遗憾的是并没有解决这些问题。

编辑 #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"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*AIT 8

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

// 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);
});
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddScoped<MyService>();
    }
Run Code Online (Sandbox Code Playgroud)
  "logging": {
    "applicationInsights": {
      "samplingExcludedTypes": "Request",
      "samplingSettings": {
        "isEnabled": true
      }
    },
    "logLevel": {
      "Functions_V3_sample": "Information"
    }
  }
Run Code Online (Sandbox Code Playgroud)
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");
}

Run Code Online (Sandbox Code Playgroud)

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

执行次数

日志流

实时指标

应用程序设置