【问题标题】:How to use dependency inject for TelemetryConfiguration in Azure Function如何在 Azure Function 中为 TelemetryConfiguration 使用依赖注入
【发布时间】:2021-01-01 17:59:57
【问题描述】:

我尝试在 Azure Functions 中使用依赖注入进行 TelemetryConfiguration。在我的函数中,当我在函数构造函数中注入 TelemetryConfiguration 时,我将解决它。我想我真的不明白如何在 StartUp 中使用 TelemetryConfiguration,这就是我得到异常的原因。我将如何添加我已经配置的 TelemetryConfiguration。

到目前为止,我在这里做了一个简单的例子。

[assembly: FunctionsStartup(typeof(StartUp))]
public class StartUp : FunctionsStartup
{
    private string OmsModule { get; } = "OMS.VA";

    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.Configure<TelemetryConfiguration>(
            (o) =>
            {
                o.InstrumentationKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
                o.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
            });
    }
}

public class StopPlaceUpdateTimerTrigger
{
    private TelemetryClient _telemetryClient;
    private string _azureWebJobsStorage;

    public StopPlaceUpdateTimerTrigger(TelemetryConfiguration telemetryConfiguration)
    {
        _telemetryClient = new TelemetryClient(telemetryConfiguration);
    }

    [FunctionName("StopPlaceLoader")]
    public async Task StopPlaceLoaderMain([TimerTrigger("%CRON_EXPRESSION%", RunOnStartup = true)]TimerInfo myTimerInfo, ILogger log, ExecutionContext context)
    {
        SetConfig(context);
        var cloudTable = await GetCloudTableAsync();
        if (cloudTable == null)
        {
            //Do nothing
        }
        //Do nothing
    }

    private async Task<CloudTable> GetCloudTableAsync()
    {
        var storageAccount = CloudStorageAccount.Parse(_azureWebJobsStorage);
        var tableClient = storageAccount.CreateCloudTableClient();
        var table = tableClient.GetTableReference(nameof(StopPlaceLoaderCacheRecord));

        if (!await table.ExistsAsync())
        {
            await table.CreateIfNotExistsAsync();
        }
        return table;
    }

    private void SetConfig(ExecutionContext context)
    {
        var config = new ConfigurationBuilder()
            .SetBasePath(context.FunctionAppDirectory)
            .AddJsonFile("local.settings.json", optional: true)
            .AddEnvironmentVariables()
            .Build();
        _azureWebJobsStorage = config["AzureWebJobsStorage"];
    }
}


//local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "DefaultEndpointsProtocol...",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"EnableMSDeployAppOffline": "True",
    "CRON_EXPRESSION": "0 */5 22-3 * * *",
"APPINSIGHTS_INSTRUMENTATIONKEY": "..."
  }
}

我得到以下异常; Microsoft.Extensions.DependencyInjection.Abstractions:尝试激活“OMS.VA.RealTime.StopPlaceLoader.StopPlaceUpdateTimerTrigger”时,无法解析“Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration”类型的服务。

【问题讨论】:

  • 你如何使用 azure 函数做到这一点?
  • 不明白您的问题:-) 我在 Azure 函数中执行此操作,上面的代码与下面的 @IvanYang 更正。把你的问题说得更具体一些,我会尽量回答。

标签: azure dependency-injection azure-functions azure-application-insights telemetry


【解决方案1】:

更新:

我们可以将这行代码 var newConfig = TelemetryConfiguration.Active; 更改为 var newConfig = TelemetryConfiguration.CreateDefault(); ,因为 TelemetryConfiguration.Active 已被弃用。


请使用下面的代码进行 TelemetryConfiguration DI,我使用 blob 触发功能对其进行了测试,效果很好:

using System.IO;
using System.Linq;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

[assembly: WebJobsStartup(typeof(FunctionApp17.MyStartup))]
namespace FunctionApp17
{

    public class MyStartup : IWebJobsStartup
    {
        public void Configure(IWebJobsBuilder builder)
        {
            var configDescriptor = builder.Services.SingleOrDefault(tc => tc.ServiceType == typeof(TelemetryConfiguration));
            if (configDescriptor?.ImplementationFactory != null)
            {
                var implFactory = configDescriptor.ImplementationFactory;
                builder.Services.Remove(configDescriptor);
                builder.Services.AddSingleton(provider =>
                {
                    if (implFactory.Invoke(provider) is TelemetryConfiguration config)
                    {
                        var newConfig = TelemetryConfiguration.Active;
                        newConfig.ApplicationIdProvider = config.ApplicationIdProvider;
                        newConfig.InstrumentationKey = config.InstrumentationKey;

                        return newConfig;
                    }
                    return null;
                });
            }
        }
    }

    public class Function1
    {
        private TelemetryClient _telemetryClient;

        public Function1(TelemetryConfiguration telemetryConfiguration)
        {
            _telemetryClient = new TelemetryClient(telemetryConfiguration);
        }

        [FunctionName("Function1")]
        public void Run([BlobTrigger("samples-workitems/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, ILogger log)
        {
            log.LogInformation($"!!!!!!!!!! C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
            _telemetryClient.TrackTrace("this is a test message from DI of telemetry client !!!!!!!!!!!!!!");
        }
    }
}

测试结果如下,我可以在azure portal的应用洞察中看到日志:

还有一件事,我看到您尝试在代码中使用 ITelemetry Initializer。您可以关注此GitHub issue 以获取您的ITelemetry InitializerItelemetry Processor

【讨论】:

  • 不错的解决方案。谢谢!在我的实现中,我更改了 var newConfig = TelemetryConfiguration.Active;到 var newConfig = TelemetryConfiguration.CreateDefault();因为 ApplicationInsights SDK 2.11-beta1 已弃用 TelemetryConfiguration.Active
  • @RogerUhlin,感谢您的分享,我会在我的帖子中更新它:)
【解决方案2】:

如果您使用builder.Services.Configure&lt;TelemetryConfiguration&gt;() 进行配置,则您使用的是Options pattern in ASP.NET Core

要访问该选项,您需要执行以下操作:

public StopPlaceUpdateTimerTrigger(IOptionsMonitor<TelemetryConfiguration> telemetryConfiguration)
{
    _telemetryClient = new TelemetryClient(telemetryConfiguration.CurrentValue);
}

如果你只是想直接使用 TelemetryConfiguration 对象,你需要在服务集合中添加它:

builder.Services.AddSingleton<TelemetryConfiguration >(sp =>
{
    var telemetryConfiguration = new TelemetryConfiguration();
    telemetryConfiguration.InstrumentationKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
    telemetryConfiguration.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
    return telemetryConfiguration;
}

那么你可以:

public StopPlaceUpdateTimerTrigger(TelemetryConfiguration telemetryConfiguration)
{
    _telemetryClient = new TelemetryClient(telemetryConfiguration);
}

希望对您有所帮助。

【讨论】:

  • 巨大的帮助。尝试将函数应用程序从 2.2 迁移到 3.1,我在很多地方使用 DI 来实现 Application Insights。在文档中的任何地方都没有提到这个重大变化。谢谢!
  • 这样会丢失operation_id等相关信息吗?在 aspnetcore 应用程序中执行此操作会导致此问题,我不知道功能是否相同。
  • 我发现使用此解决方案会使 invocationId 和 cloud_RoleName 停止填充,从而导致统计信息未显示在函数仪表板上。使用 Ivan Yang 的答案似乎可以解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2023-03-03
  • 2022-01-14
  • 2020-04-15
  • 2021-06-25
  • 2021-05-30
  • 1970-01-01
  • 2020-02-20
  • 2013-01-29
相关资源
最近更新 更多