diff --git a/CHANGELOG.md b/CHANGELOG.md index da30970e..201f5f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - [Added ability to remove any default Telemetry Module.](https://github.com/Microsoft/ApplicationInsights-aspnetcore/issues/633) - [TelemetryChannel is configured via DI, making it easier to override channel](https://github.com/Microsoft/ApplicationInsights-aspnetcore/issues/641) - [Fixed a bug which caused QuickPulse and Sampling to be enabled only if ServerTelemetryChannel was used](https://github.com/Microsoft/ApplicationInsights-aspnetcore/issues/642) +- [QuickPulseTelemetryModule is constructed via DI, make it possible for users to configure it.] (https://github.com/Microsoft/ApplicationInsights-aspnetcore/issues/639) ## Version 2.2.1 - Updated Web/Base SDK version dependency to 2.5.1 which addresses a bug. diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/Extensibility/Implementation/Tracing/AspNetEventSource.cs b/src/Microsoft.ApplicationInsights.AspNetCore/Extensibility/Implementation/Tracing/AspNetEventSource.cs index c91e53f1..38e576a4 100644 --- a/src/Microsoft.ApplicationInsights.AspNetCore/Extensibility/Implementation/Tracing/AspNetEventSource.cs +++ b/src/Microsoft.ApplicationInsights.AspNetCore/Extensibility/Implementation/Tracing/AspNetEventSource.cs @@ -140,6 +140,12 @@ public void UnableToFindModuleToConfigure(string moduleType, string appDomainNam this.WriteEvent(11, moduleType, this.ApplicationName); } + [Event(12, Message = "Unable to find QuickPulseTelemetryModule in service collection. LiveMetrics feature will not be available. Please add QuickPulseTelemetryModule to services collection in the ConfigureServices method of your application Startup class.", Level = EventLevel.Error, Keywords = Keywords.Diagnostics)] + public void UnableToFindQuickPulseModuleInDI(string appDomainName = "Incorrect") + { + this.WriteEvent(12, this.ApplicationName); + } + /// /// Keywords for the AspNetEventSource. /// diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs b/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs index 05c0018f..86c4d59a 100644 --- a/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs +++ b/src/Microsoft.ApplicationInsights.AspNetCore/Extensions/ApplicationInsightsExtensions.cs @@ -15,6 +15,7 @@ namespace Microsoft.Extensions.DependencyInjection using Microsoft.ApplicationInsights.Channel; using Microsoft.ApplicationInsights.DependencyCollector; using Microsoft.ApplicationInsights.Extensibility; + using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse; using Microsoft.ApplicationInsights.WindowsServer; using Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel; using Microsoft.AspNetCore.Hosting; @@ -164,6 +165,7 @@ public static IServiceCollection AddApplicationInsightsTelemetry(this IServiceCo #endif services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(provider => provider.GetService>().Value); services.AddSingleton(provider => new CorrelationIdLookupHelper(() => provider.GetService>().Value)); diff --git a/src/Microsoft.ApplicationInsights.AspNetCore/Implementation/TelemetryConfigurationOptionsSetup.cs b/src/Microsoft.ApplicationInsights.AspNetCore/Implementation/TelemetryConfigurationOptionsSetup.cs index 078bea54..38899475 100644 --- a/src/Microsoft.ApplicationInsights.AspNetCore/Implementation/TelemetryConfigurationOptionsSetup.cs +++ b/src/Microsoft.ApplicationInsights.AspNetCore/Implementation/TelemetryConfigurationOptionsSetup.cs @@ -75,20 +75,18 @@ public void Configure(TelemetryConfiguration configuration) foreach (ITelemetryProcessorFactory processorFactory in this.telemetryProcessorFactories) { configuration.TelemetryProcessorChainBuilder.Use(processorFactory.Create); - } - configuration.TelemetryProcessorChainBuilder.Build(); + } } + // Fallback to default channel (InMemoryChannel) created by base sdk if no channel is found in DI + configuration.TelemetryChannel = this.telemetryChannel ?? configuration.TelemetryChannel; + (configuration.TelemetryChannel as ITelemetryModule)?.Initialize(configuration); + this.AddQuickPulse(configuration); this.AddSampling(configuration); this.DisableHeartBeatIfConfigured(); - - (configuration.TelemetryChannel as ITelemetryModule)?.Initialize(configuration); - - configuration.TelemetryProcessorChainBuilder.Build(); - - // Fallback to default channel (InMemoryChannel) created by base sdk if no channel is found in DI - configuration.TelemetryChannel = this.telemetryChannel ?? configuration.TelemetryChannel; + + configuration.TelemetryProcessorChainBuilder.Build(); if (this.applicationInsightsServiceOptions.DeveloperMode != null) { @@ -121,20 +119,25 @@ public void Configure(TelemetryConfiguration configuration) } private void AddQuickPulse(TelemetryConfiguration configuration) - { + { if (this.applicationInsightsServiceOptions.EnableQuickPulseMetricStream) - { - var quickPulseModule = new QuickPulseTelemetryModule(); - quickPulseModule.Initialize(configuration); - - QuickPulseTelemetryProcessor processor = null; - configuration.TelemetryProcessorChainBuilder.Use((next) => + { + QuickPulseTelemetryModule quickPulseModule = this.modules.FirstOrDefault(((module) => module.GetType() == typeof(QuickPulseTelemetryModule))) as QuickPulseTelemetryModule; + if (quickPulseModule != null) + { + QuickPulseTelemetryProcessor processor = null; + configuration.TelemetryProcessorChainBuilder.Use((next) => + { + processor = new QuickPulseTelemetryProcessor(next); + quickPulseModule.RegisterTelemetryProcessor(processor); + return processor; + }); + } + else { - processor = new QuickPulseTelemetryProcessor(next); - quickPulseModule.RegisterTelemetryProcessor(processor); - return processor; - }); - } + AspNetCoreEventSource.Instance.UnableToFindQuickPulseModuleInDI(); + } + } } private void AddSampling(TelemetryConfiguration configuration) diff --git a/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Extensions/ApplicationInsightsExtensionsTests.cs b/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Extensions/ApplicationInsightsExtensionsTests.cs index 59533fb6..3c8cb846 100644 --- a/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Extensions/ApplicationInsightsExtensionsTests.cs +++ b/test/Microsoft.ApplicationInsights.AspNetCore.Tests/Extensions/ApplicationInsightsExtensionsTests.cs @@ -348,15 +348,24 @@ public static void RegistersTelemetryConfigurationFactoryMethodThatPopulatesItWi Assert.NotNull(modules); #if NET46 - Assert.Equal(4, modules.Count()); + Assert.Equal(5, modules.Count()); var perfCounterModule = services.FirstOrDefault(t => t.ImplementationType == typeof(PerformanceCollectorModule)); Assert.NotNull(perfCounterModule); #else - Assert.Equal(3, modules.Count()); + Assert.Equal(4, modules.Count()); #endif var dependencyModuleDescriptor = services.FirstOrDefault(t => t.ImplementationType == typeof(DependencyTrackingTelemetryModule)); - Assert.NotNull(dependencyModuleDescriptor); + Assert.NotNull(dependencyModuleDescriptor); + + var appServiceHeartBeatModuleDescriptor = services.FirstOrDefault(t => t.ImplementationType == typeof(AppServicesHeartbeatTelemetryModule)); + Assert.NotNull(appServiceHeartBeatModuleDescriptor); + + var azureMetadataHeartBeatModuleDescriptor = services.FirstOrDefault(t => t.ImplementationType == typeof(AzureInstanceMetadataTelemetryModule)); + Assert.NotNull(azureMetadataHeartBeatModuleDescriptor); + + var quickPulseModuleDescriptor = services.FirstOrDefault(t => t.ImplementationType == typeof(QuickPulseTelemetryModule)); + Assert.NotNull(quickPulseModuleDescriptor); } [Fact] public static void RegistersTelemetryConfigurationFactoryMethodThatPopulatesDependencyCollectorWithDefaultValues()