首页 > 解决方案 > 如何有条件地禁用 ASP.NET Core 中的 Application Insights?

问题描述

当有条件地在我的 ASP.NET Core 应用程序中包含 Application Insights 时,我试图避免 ASP.NET Core 中的服务定位器模式,原因是我想在开发过程中完全禁用 Applications Insights。

服务定位器模式(不推荐)

执行此操作的最基本方法是在使用IServiceCollection 上的方法构建服务提供者之后服务定位IOptions设置ConfigureServices()BuildServiceProvider()

(不推荐!)服务定位器模式示例:

public void ConfigureService(IServiceCollection services)
{
    // Configure the services
    services.Configure<AppSettings>(configuration.GetSection(nameof(AppSettings)));

    // Build an intermediate service provider
    var sp = services.BuildServiceProvider();

    // Resolve the settings from the service provider;
    var appSettings = sp.GetRequiredService<AppSettings>();

    // Conditionally include the service using the settings
    if (appSettings.EnableApplicationInsights) {
      services.AddApplicationInsightsTelemetry();
    }
}

这不是推荐的模式,因为它会导致创建单例服务的额外副本。但我们可以确定 Application Insights 在应用程序中完全禁用,实际上它甚至不包含在 DI 容器中。

更好的模式#1

解决依赖于其他服务的类的更好方法是使用为您提供 IServiceProvider 的 AddXXX 重载。这样您就不需要实例化中间服务提供者。

以下示例展示了如何在 AddSingleton/AddTransient 方法中使用此重载。

services.AddSingleton(serviceProvider =>
{
    var settings = serviceProvider.GetRequiredService<AppSettings>();
    var fooService = new FooService();
    fooService.Enable = settings.EnableFooService
    return fooService;
});


services.AddTransient(serviceProvider =>
{
    var settings = serviceProvider.GetRequiredService<AppSettings>();
    var barService = new BarService();
    barService.Enable = settings.EnableBarService
    return barService;
});

IServiceProvider 的重载可用于即 AddSingleton、AddScoped、AddTransient。这种模式效果很好并且易于实现,但服务通常具有AddFoo()不提供这种重载的方法,即 AddApplicationInsightsTelemetry、AddCors、AddAuthentication、AddAuthorization...

我从 Ehsan Mirsaeedi 的回答中得到灵感: https ://stackoverflow.com/a/56278027/294242

更好的模式#2

我们可以实现IConfigureOptions<TOptions>接口,在方法中注册我们的配置类 ConfigureServices

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IConfigureOptions<ApplicationInsightsServiceOptions>, ConfigureApplicationInsightsServiceOptions>();

    services.AddApplicationInsightsTelemetry();
}
    public class ConfigureApplicationInsightsServiceOptions : IConfigureOptions<ApplicationInsightsServiceOptions>
    {
        private readonly IServiceScopeFactory _serviceScopeFactory;

        public ConfigureApplicationInsightsServiceOptions(IServiceScopeFactory serviceScopeFactory)
        {
            _serviceScopeFactory = serviceScopeFactory;
        }

        public void Configure(ApplicationInsightsServiceOptions options)
        {
            using var scope = _serviceScopeFactory.CreateScope();
            var provider = scope.ServiceProvider;
            var settings = provider.GetRequiredService<AppSettings>();

            if (!settings.EnableTracking)
            {
                options.EnableQuickPulseMetricStream = false;
                options.EnablePerformanceCounterCollectionModule = false;
                options.EnableAppServicesHeartbeatTelemetryModule = false;
                options.EnableAzureInstanceMetadataTelemetryModule = false;
                options.EnableDependencyTrackingTelemetryModule = false;
                options.EnableEventCounterCollectionModule = false;
                options.EnableAdaptiveSampling = false;
                options.EnableDebugLogger = false;
                options.EnableHeartbeat = false;
                options.EnableRequestTrackingTelemetryModule = false;
                options.EnableAuthenticationTrackingJavaScript = false;
                options.EnableDiagnosticsTelemetryModule = false;
            }
        }
    }

我目前正在评估此模式,但我不确定 Application Insights 在我的应用程序中是否完全禁用。

我的灵感来自: https ://andrewlock.net/access-services-inside-options-and-startup-using-configureoptions/#the-new-improved-answer

标签: asp.net-coredependency-injectionazure-application-insights

解决方案


在基本示例中,无需构建服务提供者。大多数文档甚至都建议不要这样做。可以直接从配置中提取所需的设置。

public void ConfigureService(IServiceCollection services) {
    var section = configuration.GetSection(nameof(AppSettings));

    // Configure the services for IOptions injection
    services.Configure<AppSettings>(section);
  
    // Extract the settings from configuration explicitly as needed
    AppSettings appSettings = section.Get<AppSettings>();

    // Conditionally include the service using the settings
    if (appSettings.EnableApplicationInsights) {
        services.AddApplicationInsightsTelemetry();
    }

    //...
}

确实不需要涉及依赖类或使用自定义IConfigureOptions<TOptions>来满足 Startup 中所需的条件

参考:ASP.NET Core 中的配置 - 绑定到对象图


推荐阅读