如何在ASP.NET Core中有条件地禁用Application Insights



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

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

最基本的方法是在IServiceCollection 上使用BuildServiceProvider()方法构建服务提供商后,在ConfigureServices()中服务定位IOptions设置

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

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>接口,在CCD_ 6方法。

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-新的改进答案

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

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>来满足启动中所需的条件

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

最新更新