Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ public static IServiceCollection AddApplicationInsightsTelemetry(this IServiceCo
{
if (!IsApplicationInsightsAdded(services))
{
// Register the default configuration options to automatically read from appsettings.json
services.AddOptions<ApplicationInsightsServiceOptions>()
.Configure<IConfiguration>((options, config) =>
{
AddTelemetryConfiguration(config, options);
});

services.AddOpenTelemetry()
.WithApplicationInsights()
.UseApplicationInsightsTelemetry();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ public static IServiceCollection AddApplicationInsightsTelemetryWorkerService(th
{
if (!IsApplicationInsightsAdded(services))
{
// Register the default configuration options to automatically read from appsettings.json
services.AddOptions<ApplicationInsightsServiceOptions>()
.Configure<IConfiguration>((options, config) =>
{
AddTelemetryConfiguration(config, options);
});

services.AddOpenTelemetry()
.WithApplicationInsights()
.UseApplicationInsightsTelemetry();
Expand Down
19 changes: 0 additions & 19 deletions NETCORE/src/Shared/Extensions/ApplicationInsightsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,10 @@ public static partial class ApplicationInsightsExtensions
{
private const string VersionKeyFromConfig = "version";
private const string ConnectionStringFromConfig = "ApplicationInsights:ConnectionString";
private const string DeveloperModeFromConfig = "ApplicationInsights:TelemetryChannel:DeveloperMode";
private const string EndpointAddressFromConfig = "ApplicationInsights:TelemetryChannel:EndpointAddress";

private const string ConnectionStringEnvironmentVariable = "APPLICATIONINSIGHTS_CONNECTION_STRING";
private const string DeveloperModeForWebSites = "APPINSIGHTS_DEVELOPER_MODE";
private const string EndpointAddressForWebSites = "APPINSIGHTS_ENDPOINTADDRESS";

private const string ApplicationInsightsSectionFromConfig = "ApplicationInsights";
private const string TelemetryChannelSectionFromConfig = "ApplicationInsights:TelemetryChannel";

/// <summary>
/// Read configuration from appSettings.json, appsettings.{env.EnvironmentName}.json,
Expand All @@ -54,26 +49,12 @@ internal static void AddTelemetryConfiguration(
try
{
config.GetSection(ApplicationInsightsSectionFromConfig).Bind(serviceOptions);
config.GetSection(TelemetryChannelSectionFromConfig).Bind(serviceOptions);

if (config.TryGetValue(primaryKey: ConnectionStringEnvironmentVariable, backupKey: ConnectionStringFromConfig, value: out string connectionStringValue))
{
serviceOptions.ConnectionString = connectionStringValue;
}

if (config.TryGetValue(primaryKey: DeveloperModeForWebSites, backupKey: DeveloperModeFromConfig, value: out string developerModeValue))
{
if (bool.TryParse(developerModeValue, out bool developerMode))
{
serviceOptions.DeveloperMode = developerMode;
}
}

if (config.TryGetValue(primaryKey: EndpointAddressForWebSites, backupKey: EndpointAddressFromConfig, value: out string endpointAddress))
{
serviceOptions.EndpointAddress = endpointAddress;
}

if (config.TryGetValue(primaryKey: VersionKeyFromConfig, value: out string version))
{
serviceOptions.ApplicationVersion = version;
Expand Down
10 changes: 0 additions & 10 deletions NETCORE/src/Shared/Extensions/ApplicationInsightsServiceOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ public class ApplicationInsightsServiceOptions
/// </summary>
public string ApplicationVersion { get; set; } = Assembly.GetEntryAssembly()?.GetName().Version.ToString();

/// <summary>
/// Gets or sets a value indicating whether telemetry channel should be set to developer mode.
/// </summary>
public bool? DeveloperMode { get; set; }

/// <summary>
/// Gets or sets the endpoint address of the channel.
/// </summary>
Expand Down Expand Up @@ -117,11 +112,6 @@ public class ApplicationInsightsServiceOptions
/// <param name="target">Target instance to copy properties to.</param>
internal void CopyPropertiesTo(ApplicationInsightsServiceOptions target)
{
if (this.DeveloperMode != null)
{
target.DeveloperMode = this.DeveloperMode;
}

if (!string.IsNullOrEmpty(this.EndpointAddress))
{
target.EndpointAddress = this.EndpointAddress;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
namespace Microsoft.ApplicationInsights.WorkerService
#if AI_ASPNETCORE_WEB
namespace Microsoft.AspNetCore.Hosting
#else
namespace Microsoft.ApplicationInsights.WorkerService
#endif
{
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
#if AI_ASPNETCORE_WEB
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
#endif
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

/// <summary>
/// <see cref="IConfigureOptions&lt;ApplicationInsightsServiceOptions&gt;"/> implementation that reads options from provided IConfiguration.
/// <see cref="IConfigureOptions{ApplicationInsightsServiceOptions}"/> implementation that reads options from provided IConfiguration.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "This class is instantiated by Dependency Injection.")]
internal class DefaultApplicationInsightsServiceConfigureOptions : IConfigureOptions<ApplicationInsightsServiceOptions>
{
private readonly IConfiguration configuration;
Expand All @@ -30,11 +35,6 @@ public void Configure(ApplicationInsightsServiceOptions options)
{
ApplicationInsightsExtensions.AddTelemetryConfiguration(this.configuration, options);
}

if (Debugger.IsAttached)
{
options.DeveloperMode = true;
}
}
}
}
208 changes: 208 additions & 0 deletions NETCORE/test/IntegrationTests.Tests/AspNetCoreConfigurationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
using System;
using System.IO;
using Azure.Monitor.OpenTelemetry.Exporter;
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Xunit;
using Xunit.Abstractions;

namespace IntegrationTests.Tests
{
public class AspNetCoreConfigurationTests
{
private readonly ITestOutputHelper output;
private const string TestConnectionString = "InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=http://127.0.0.1";

public AspNetCoreConfigurationTests(ITestOutputHelper output)
{
this.output = output;
}

[Fact]
public void ReadsConnectionStringFromApplicationInsightsSectionInConfig()
{
// ARRANGE
var jsonFullPath = Path.Combine(Directory.GetCurrentDirectory(), "content", "config-connection-string.json");
this.output.WriteLine("json:" + jsonFullPath);
var config = new ConfigurationBuilder().AddJsonFile(jsonFullPath).Build();

var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(config);

// ACT
services.AddApplicationInsightsTelemetry();

// VALIDATE
IServiceProvider serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<ApplicationInsightsServiceOptions>>().Value;
Assert.Equal(TestConnectionString, options.ConnectionString);
}

[Fact]
public void ReadsEnableAdaptiveSamplingFromApplicationInsightsSectionInConfig()
{
// ARRANGE
var jsonFullPath = Path.Combine(Directory.GetCurrentDirectory(), "content", "config-all-settings-false.json");
this.output.WriteLine("json:" + jsonFullPath);
var config = new ConfigurationBuilder().AddJsonFile(jsonFullPath).Build();

var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(config);

// ACT
services.AddApplicationInsightsTelemetry();

// VALIDATE
IServiceProvider serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<ApplicationInsightsServiceOptions>>().Value;
Assert.False(options.EnableAdaptiveSampling);
}

[Fact]
public void ReadsEnableQuickPulseMetricStreamFromApplicationInsightsSectionInConfig()
{
// ARRANGE
var jsonFullPath = Path.Combine(Directory.GetCurrentDirectory(), "content", "config-all-settings-false.json");
this.output.WriteLine("json:" + jsonFullPath);
var config = new ConfigurationBuilder().AddJsonFile(jsonFullPath).Build();

var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(config);

// ACT
services.AddApplicationInsightsTelemetry();

// VALIDATE
IServiceProvider serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<ApplicationInsightsServiceOptions>>().Value;
Assert.False(options.EnableQuickPulseMetricStream);
}

[Fact]
public void ReadsApplicationVersionFromApplicationInsightsSectionInConfig()
{
// ARRANGE
var jsonFullPath = Path.Combine(Directory.GetCurrentDirectory(), "content", "config-all-settings-true.json");
this.output.WriteLine("json:" + jsonFullPath);
var config = new ConfigurationBuilder().AddJsonFile(jsonFullPath).Build();

var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(config);

// ACT
services.AddApplicationInsightsTelemetry();

// VALIDATE
IServiceProvider serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<ApplicationInsightsServiceOptions>>().Value;
Assert.Equal("1.0.0", options.ApplicationVersion);
}

[Fact]
public void ReadsRequestCollectionOptionsFromApplicationInsightsSectionInConfig()
{
// ARRANGE
var jsonFullPath = Path.Combine(Directory.GetCurrentDirectory(), "content", "config-all-settings-false.json");
this.output.WriteLine("json:" + jsonFullPath);
var config = new ConfigurationBuilder().AddJsonFile(jsonFullPath).Build();

var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(config);

// ACT
services.AddApplicationInsightsTelemetry();

// VALIDATE
IServiceProvider serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<ApplicationInsightsServiceOptions>>().Value;
Assert.False(options.RequestCollectionOptions.InjectResponseHeaders);
Assert.False(options.RequestCollectionOptions.TrackExceptions);
}

[Fact]
public void ConfigurationFlowsFromApplicationInsightsSectionToAzureMonitorExporter()
{
// ARRANGE
var jsonFullPath = Path.Combine(Directory.GetCurrentDirectory(), "content", "config-all-settings-false.json");
this.output.WriteLine("json:" + jsonFullPath);
var config = new ConfigurationBuilder().AddJsonFile(jsonFullPath).Build();

var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(config);

// ACT
services.AddApplicationInsightsTelemetry();

// VALIDATE
IServiceProvider serviceProvider = services.BuildServiceProvider();

// Verify ApplicationInsightsServiceOptions
var aiOptions = serviceProvider.GetRequiredService<IOptions<ApplicationInsightsServiceOptions>>().Value;
Assert.Equal("InstrumentationKey=22222222-2222-3333-4444-555555555555;IngestionEndpoint=http://testendpoint", aiOptions.ConnectionString);
Assert.False(aiOptions.EnableAdaptiveSampling);
Assert.False(aiOptions.EnableQuickPulseMetricStream);

// Verify AzureMonitorExporterOptions gets the values
var exporterOptions = serviceProvider.GetRequiredService<IOptions<AzureMonitorExporterOptions>>().Value;
Assert.Equal("InstrumentationKey=22222222-2222-3333-4444-555555555555;IngestionEndpoint=http://testendpoint", exporterOptions.ConnectionString);
Assert.Equal(1.0F, exporterOptions.SamplingRatio); // No sampling when EnableAdaptiveSampling is false
Assert.False(exporterOptions.EnableLiveMetrics);
}

[Fact]
public void EnvironmentVariablesTakePrecedenceOverAppSettings()
{
// ARRANGE
const string envConnectionString = "InstrumentationKey=AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE;IngestionEndpoint=http://env-endpoint";
Environment.SetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING", envConnectionString);

try
{
var jsonFullPath = Path.Combine(Directory.GetCurrentDirectory(), "content", "config-connection-string.json");
this.output.WriteLine("json:" + jsonFullPath);
var config = new ConfigurationBuilder().AddJsonFile(jsonFullPath).AddEnvironmentVariables().Build();

var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(config);

// ACT
services.AddApplicationInsightsTelemetry();

// VALIDATE
IServiceProvider serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<ApplicationInsightsServiceOptions>>().Value;
Assert.Equal(envConnectionString, options.ConnectionString);
}
finally
{
Environment.SetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING", null);
}
}

[Fact]
public void ExplicitConfigurationTakesPrecedenceOverDefaultConfiguration()
{
// ARRANGE
const string explicitConnectionString = "InstrumentationKey=CCCCCCCC-DDDD-EEEE-FFFF-111111111111;IngestionEndpoint=http://explicit-endpoint";
var jsonFullPath = Path.Combine(Directory.GetCurrentDirectory(), "content", "config-connection-string.json");
this.output.WriteLine("json:" + jsonFullPath);
var config = new ConfigurationBuilder().AddJsonFile(jsonFullPath).Build();

var services = new ServiceCollection();
services.AddSingleton<IConfiguration>(config);

// ACT - Pass explicit options
services.AddApplicationInsightsTelemetry(options =>
{
options.ConnectionString = explicitConnectionString;
});

// VALIDATE
IServiceProvider serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<ApplicationInsightsServiceOptions>>().Value;
Assert.Equal(explicitConnectionString, options.ConnectionString);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
<None Update="xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="content\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"ApplicationInsights": {
"ConnectionString": "InstrumentationKey=11111111-2222-3333-4444-555555555555;IngestionEndpoint=http://testendpoint",
"EnableAdaptiveSampling": false,
"EnableQuickPulseMetricStream": true,
"ApplicationVersion": "Version",
"RequestCollectionOptions": {
"InjectResponseHeaders": true,
"TrackExceptions": false
},
"DependencyCollectionOptions": {
"EnableLegacyCorrelationHeadersInjection": false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"ApplicationInsights": {
"ConnectionString": "InstrumentationKey=22222222-2222-3333-4444-555555555555;IngestionEndpoint=http://testendpoint",
"EnableAdaptiveSampling": false,
"EnableQuickPulseMetricStream": false,
"RequestCollectionOptions": {
"InjectResponseHeaders": false,
"TrackExceptions": false
},
"DependencyCollectionOptions": {
"EnableLegacyCorrelationHeadersInjection": false
}
}
}
Loading
Loading