C# 如何通过依赖项注入正确设置Azure功能日志记录、实时度量和应用程序洞察

C# 如何通过依赖项注入正确设置Azure功能日志记录、实时度量和应用程序洞察,c#,azure,azure-functions,azure-application-insights,C#,Azure,Azure Functions,Azure Application Insights,大约一个月前,我注意到旧Azure Functions门户界面中的一些监控功能停止工作。我在网上写了更多关于这些问题的细节,但我的具体问题到目前为止还没有得到回答 现在,Azure功能门户界面似乎默认为新的“管理体验”,它看起来更类似于Azure的其余部分,因此,更明显的是,我们使用日志记录和跟踪的方式出了问题 我的问题是:关于如何设置Azure功能日志记录、实时度量和应用程序洞察跟踪,有人有任何代码示例吗: 与依赖项注入一起使用 与新的“管理体验”界面配合使用 目前,为了查看特定Azure函数

大约一个月前,我注意到旧Azure Functions门户界面中的一些监控功能停止工作。我在网上写了更多关于这些问题的细节,但我的具体问题到目前为止还没有得到回答

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

我的问题是:关于如何设置Azure功能日志记录、实时度量和应用程序洞察跟踪,有人有任何代码示例吗:

  • 与依赖项注入一起使用
  • 与新的“管理体验”界面配合使用
  • 目前,为了查看特定Azure函数正在做什么,我必须转到旧的Azure界面并研究日志流。这些函数确实可以工作,它们在日志流中吐出信息,但只在旧的界面中吐出信息,在监视方面似乎没有多少其他功能可以工作。使用旧界面:

    • 调用日志,即当您按下“函数(只读)>[function]>Monitor”下的“监视器”链接时得到的日志,显示根本没有调用,即使函数肯定是根据日志调用的
    • Live app metrics链接会导致默认的“不可用:您的应用程序处于脱机状态或使用较旧的SDK”以及一些动画演示图表
    一个月前,这些还不错。现在,没那么多了

    使用新界面:

    • 监控>日志流显示除“已连接!“,不管是否冗长
    • 再次监视>日志流>在Live Metrics中打开只会生成默认值“不可用:您的应用程序处于脱机状态或使用较旧的SDK”
    使用函数>函数>[单击函数]转到新界面中的特定函数:

    • 开发者>代码+测试>测试按钮>运行,日志窗口弹出,只是说“连接!“除此之外,别无他事,再也不管冗长了
    • Monitor>Invocations,这里没有注册调用跟踪,即使函数显然是根据旧接口日志流调用的
    • 监视器>日志,再一次,只是说“已连接!“,不管是否冗长
    我不明白为什么一个月前它突然停止工作,为什么这么多东西在新界面上似乎不起作用。我们函数的NuGet包都是最新的

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

    using Microsoft.Extensions.Logging;
    
    public class EventForwarder
    {
        private readonly ILogger<EventForwarder> log;
    
    app insights tracer还使用建议的解决方案注入依赖项,即我们的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);
    
    我错过了什么

    编辑#1:顺便说一句,在发布对话框中将应用程序洞察作为服务依赖项添加,不幸的是,不能解决这些问题

    编辑#2:另外,我们的函数host.json文件都是这样的:


    这就是破坏你的应用程序的原因,删除它,一切都应该正常:

    // 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);
    });
    
    我的猜测是,既然bug修复已经推出,解决方法实际上会破坏日志记录

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

    我可以通过应用上面提到的“变通方法”重现您的问题。没有它,一切都会正常进行

    全样本:

    publicMyService(ILogger记录器、遥测客户端遥测)
    {
    Logger=Logger??抛出新的ArgumentNullException(name of(Logger));
    遥测=遥测??抛出新的ArgumentNullException(nameof(遥测));
    }
    公共图书馆
    {
    Logger.LogInformation(“Foo”);
    Telemetry.TrackTrace(“BarLog”,Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information);
    遥测跟踪事件(“BarEvent”);
    }
    
    更新:我的原始答案中的host.json有问题,示例日志没有真正持久化到AppInsights,因为。我相应地更新了代码


    您好,我正在使用新的azure功能,application insights的所有功能似乎都运行良好(只需从azure门户启用application insights)。那么,我可以知道您为什么要使用DI吗?@IvanYang对于依赖注入的任何其他用例来说都是一样的,即可测试性、可模拟性、IoC,避免静态/全局上下文,并且不必在每次方法/函数调用中传递日志记录、跟踪和其他服务类。在我看来,即使将它们封装在某种类型的服务对象。从2x版本开始正式支持它:是的,今天早上确认了它。事实上,以前需要的解决方法现在正在打破除“经典体验”之外的所有日志记录“日志流。您的示例之所以有效,是因为您在MyService中使用了以函数开头的名称空间,请继续,并将其更改为类似的内容。它不会记录。您可能有这些问题,因为我的原始答案在
    host.json
    中缺少一个关键部分。我已经更新了解决方案。
    using Microsoft.ApplicationInsights;
    
    namespace EventForwarder.Static
    {
        public static class TelemetryExtensions
        {
            public static void Track(this TelemetryClient insights, string eventName)
            {
                insights.TrackEvent(eventName);
                insights.Flush();
            }
    
    {
        "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"
            }
        }
    }
    
    // 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);
    });
    
    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");
    }