Skip to content

Commit d15d4aa

Browse files
[AzureMonitorDistro] Read APPLICATIONINSIGHTS_CONNECTION_STRING from IConfiguration (Azure#45292)
* Fix: Read APPLICATIONINSIGHTS_CONNECTION_STRING from IConfiguration if not set via Action<AzureMonitorOptions> * changelog patch
1 parent 4503f47 commit d15d4aa

File tree

4 files changed

+144
-4
lines changed

4 files changed

+144
-4
lines changed

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88

99
### Bugs Fixed
1010

11+
* Fixed an issue where `APPLICATIONINSIGHTS_CONNECTION_STRING` was not read from
12+
`IConfiguration` when using the `UseAzureMonitor` overload with the
13+
`Action<AzureMonitorOptions>` parameter. If the connection string is not set
14+
using the `Action<AzureMonitorOptions>` delegate, the distro will now check if
15+
`APPLICATIONINSIGHTS_CONNECTION_STRING` is present in `IConfiguration`.
16+
([#45292](https://github.com/Azure/azure-sdk-for-net/pull/45292))
17+
1118
### Other Changes
1219

1320
## 1.3.0-beta.1 (2024-07-12)

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/src/DefaultAzureMonitorOptions.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
using System;
4+
using Azure.Monitor.OpenTelemetry.Exporter.Internals.Platform;
55
using Microsoft.Extensions.Configuration;
66
using Microsoft.Extensions.Options;
77

@@ -10,7 +10,6 @@ namespace Azure.Monitor.OpenTelemetry.AspNetCore
1010
internal class DefaultAzureMonitorOptions : IConfigureOptions<AzureMonitorOptions>
1111
{
1212
private const string AzureMonitorSectionFromConfig = "AzureMonitor";
13-
private const string ConnectionStringEnvironmentVariable = "APPLICATIONINSIGHTS_CONNECTION_STRING";
1413
private readonly IConfiguration? _configuration;
1514

1615
/// <summary>
@@ -31,15 +30,15 @@ public void Configure(AzureMonitorOptions options)
3130
_configuration.GetSection(AzureMonitorSectionFromConfig).Bind(options);
3231

3332
// IConfiguration can read from EnvironmentVariables or InMemoryCollection if configured to do so.
34-
var connectionStringFromIConfig = _configuration[ConnectionStringEnvironmentVariable];
33+
var connectionStringFromIConfig = _configuration[EnvironmentVariableConstants.APPLICATIONINSIGHTS_CONNECTION_STRING];
3534
if (!string.IsNullOrEmpty(connectionStringFromIConfig))
3635
{
3736
options.ConnectionString = connectionStringFromIConfig;
3837
}
3938
}
4039

4140
// Environment Variable should take precedence.
42-
var connectionStringFromEnvVar = Environment.GetEnvironmentVariable(ConnectionStringEnvironmentVariable);
41+
var connectionStringFromEnvVar = Environment.GetEnvironmentVariable(EnvironmentVariableConstants.APPLICATIONINSIGHTS_CONNECTION_STRING);
4342
if (!string.IsNullOrEmpty(connectionStringFromEnvVar))
4443
{
4544
options.ConnectionString = connectionStringFromEnvVar;

sdk/monitor/Azure.Monitor.OpenTelemetry.AspNetCore/src/OpenTelemetryBuilderExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,12 @@ public static OpenTelemetryBuilder UseAzureMonitor(this OpenTelemetryBuilder bui
203203
{
204204
config[EnvironmentVariableConstants.HTTPCLIENT_DISABLE_URL_QUERY_REDACTION] = Boolean.TrueString;
205205
}
206+
207+
// If connection string is not set in the options, try to get it from configuration.
208+
if (string.IsNullOrWhiteSpace(options.ConnectionString) && config[EnvironmentVariableConstants.APPLICATIONINSIGHTS_CONNECTION_STRING] != null)
209+
{
210+
options.ConnectionString = config[EnvironmentVariableConstants.APPLICATIONINSIGHTS_CONNECTION_STRING];
211+
}
206212
});
207213

208214
return builder;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
using Azure.Monitor.OpenTelemetry.Exporter;
11+
using Microsoft.Extensions.Configuration;
12+
using Microsoft.Extensions.DependencyInjection;
13+
using Microsoft.Extensions.Options;
14+
using OpenTelemetry.Trace;
15+
using Xunit;
16+
17+
namespace Azure.Monitor.OpenTelemetry.AspNetCore.Tests
18+
{
19+
public class OpenTelemetryBuilderExtensionsTests
20+
{
21+
#if !NETFRAMEWORK
22+
private const string ConnectionStringEnvironmentVariable = "APPLICATIONINSIGHTS_CONNECTION_STRING";
23+
24+
[Theory]
25+
[InlineData(false, false, false, false, false, false, null)] // If nothing set, ConnectionString will be null.
26+
[InlineData(true, false, false, false, false, false, null)] // If nothing set, ConnectionString will be null.
27+
[InlineData(false, true, false, false, false, false, "testJsonValue")] // only AzureMonitor in json
28+
[InlineData(true, true, false, false, false, false, null)] // only AzureMonitor in json
29+
[InlineData(false, false, true, false, false, false, "testJsonEnvVarValue")] // only EnvVar in json
30+
[InlineData(true, false, true, false, false, false, "testJsonEnvVarValue")] // only EnvVar in json
31+
[InlineData(false, true, true, false, false, false, "testJsonEnvVarValue")] // both AzureMonitor & EnvVar in json
32+
[InlineData(true, true, true, false, false, false, "testJsonEnvVarValue")] // both AzureMonitor & EnvVar in json
33+
[InlineData(false, false, false, true, false, false, "testInMemoryCollectionValue")] // only IConfig InMemoryCollection
34+
[InlineData(true, false, false, true, false, false, "testInMemoryCollectionValue")] // only IConfig InMemoryCollection
35+
[InlineData(false, false, false, false, true, false, null)] // only IConfig EnvVars, without EnvVar set.
36+
[InlineData(true, false, false, false, true, false, null)] // only IConfig EnvVars, without EnvVar set.
37+
[InlineData(false, false, false, false, true, true, "testEnvVarValue")] // only IConfig EnvVars, with EnvVar set.
38+
[InlineData(true, false, false, false, true, true, "testEnvVarValue")] // only IConfig EnvVars, with EnvVar set.
39+
[InlineData(false, false, false, true, true, true, "testEnvVarValue")] // both IConfig InMemoryCollection & IConfig EnvVars with EnvVar set
40+
[InlineData(true, false, false, true, true, true, "testEnvVarValue")] // both IConfig InMemoryCollection & IConfig EnvVars with EnvVar set
41+
[InlineData(false, false, false, true, true, false, "testInMemoryCollectionValue")] // both IConfig InMemoryCollection & IConfig EnvVars without EnvVar set
42+
[InlineData(true, false, false, true, true, false, "testInMemoryCollectionValue")] // both IConfig InMemoryCollection & IConfig EnvVars without EnvVar set
43+
[InlineData(false, false, false, false, false, true, "testEnvVarValue")] // only EnvironmentVariable
44+
[InlineData(true, false, false, false, false, true, "testEnvVarValue")] // only EnvironmentVariable
45+
[InlineData(false, true, true, true, true, true, "testEnvVarValue")]
46+
[InlineData(true, true, true, true, true, true, "testEnvVarValue")]
47+
public void Verify_UseAzureMonitor_SetsConnectionString(bool useConfigure, bool jsonAzureMonitor, bool jsonEnvVar, bool iconfigCollection, bool iconfigEnvVar, bool setEnvVar, string expectedConnectionStringValue)
48+
{
49+
try
50+
{
51+
Environment.SetEnvironmentVariable(ConnectionStringEnvironmentVariable, setEnvVar ? "testEnvVarValue" : null);
52+
53+
// BUILD JSON STRING
54+
var jsonString = "{";
55+
56+
if (jsonAzureMonitor)
57+
{
58+
jsonString += @"""AzureMonitor"":{ ""ConnectionString"" : ""testJsonValue"" }";
59+
}
60+
61+
if (jsonAzureMonitor && jsonEnvVar)
62+
{
63+
jsonString += ",";
64+
}
65+
66+
if (jsonEnvVar)
67+
{
68+
jsonString += @"""APPLICATIONINSIGHTS_CONNECTION_STRING"" : ""testJsonEnvVarValue""";
69+
}
70+
71+
jsonString += "}";
72+
73+
// BUILD CONFIGURATION OBJECT
74+
var configBulider = new ConfigurationBuilder();
75+
bool usesConfigBuilder = false;
76+
77+
if (jsonAzureMonitor || jsonEnvVar)
78+
{
79+
configBulider.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(jsonString)));
80+
usesConfigBuilder = true;
81+
}
82+
83+
if (iconfigCollection)
84+
{
85+
configBulider.AddInMemoryCollection(new Dictionary<string, string?> { [ConnectionStringEnvironmentVariable] = "testInMemoryCollectionValue" });
86+
usesConfigBuilder = true;
87+
}
88+
89+
if (iconfigEnvVar)
90+
{
91+
configBulider.AddEnvironmentVariables();
92+
}
93+
94+
// ACT
95+
var serviceCollection = new ServiceCollection();
96+
97+
if (usesConfigBuilder)
98+
{
99+
var configuration = configBulider.Build();
100+
serviceCollection.AddSingleton<IConfiguration>(configuration);
101+
}
102+
103+
if (useConfigure)
104+
{
105+
serviceCollection.AddOpenTelemetry().UseAzureMonitor(x => { });
106+
}
107+
else
108+
{
109+
serviceCollection.AddOpenTelemetry().UseAzureMonitor();
110+
}
111+
112+
using var serviceProvider = serviceCollection.BuildServiceProvider();
113+
114+
// ASSERT
115+
var azureMonitorOptions = serviceProvider.GetServices<IOptions<AzureMonitorOptions>>().Single().Value;
116+
Assert.Equal(expectedConnectionStringValue, azureMonitorOptions.ConnectionString);
117+
118+
var azureMonitorExporterOptions = serviceProvider.GetServices<IOptions<AzureMonitorExporterOptions>>().Single().Value;
119+
Assert.Equal(expectedConnectionStringValue, azureMonitorExporterOptions.ConnectionString);
120+
}
121+
finally
122+
{
123+
Environment.SetEnvironmentVariable(ConnectionStringEnvironmentVariable, null);
124+
}
125+
}
126+
#endif
127+
}
128+
}

0 commit comments

Comments
 (0)