From 34d71f7646658653aec76e4217b2cd4a04e487db Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Thu, 23 Apr 2026 14:28:58 +0100 Subject: [PATCH] Remove vendored EnvironmentVariablesConfigurationProvider - Update dependencies to use Microsoft.Extensions.Configuration.EnvironmentVariables. - Add basic E2E test to validate existing ENV VAR behaviour continues to function. --- Directory.Packages.props | 4 + OpenTelemetry.slnx | 5 -- .../CHANGELOG.md | 6 ++ .../OpenTelemetry.Exporter.Zipkin.csproj | 1 - src/OpenTelemetry/CHANGELOG.md | 7 ++ src/OpenTelemetry/OpenTelemetry.csproj | 2 +- ...vironmentVariablesConfigurationProvider.cs | 85 ------------------- ...EnvironmentVariablesConfigurationSource.cs | 29 ------- .../EnvironmentVariablesExtensions.cs | 52 ------------ ...ronmentVariableResourceIntegrationTests.cs | 33 +++++++ .../Resources/OtelEnvResourceDetectorTests.cs | 2 + .../OtelServiceNameEnvVarDetectorTests.cs | 2 + .../Shared/EnvVarsCollectionDefinition.cs | 21 +++++ 13 files changed, 76 insertions(+), 173 deletions(-) delete mode 100644 src/Shared/EnvironmentVariables/EnvironmentVariablesConfigurationProvider.cs delete mode 100644 src/Shared/EnvironmentVariables/EnvironmentVariablesConfigurationSource.cs delete mode 100644 src/Shared/EnvironmentVariables/EnvironmentVariablesExtensions.cs create mode 100644 test/OpenTelemetry.Tests/Resources/EnvironmentVariableResourceIntegrationTests.cs create mode 100644 test/OpenTelemetry.Tests/Shared/EnvVarsCollectionDefinition.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index aadd1049117..c7f12acb18e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -12,6 +12,7 @@ --> + @@ -19,18 +20,21 @@ + + + diff --git a/OpenTelemetry.slnx b/OpenTelemetry.slnx index 77c4d32e9f8..82a3e7fa05d 100644 --- a/OpenTelemetry.slnx +++ b/OpenTelemetry.slnx @@ -161,11 +161,6 @@ - - - - - diff --git a/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md b/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md index 370abab604c..7c2d199b3bc 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.Zipkin/CHANGELOG.md @@ -6,6 +6,12 @@ Notes](../../RELEASENOTES.md). ## Unreleased +* Dropped the vendored `EnvironmentVariablesConfigurationProvider` copy; the + provider is now sourced transitively from the + `Microsoft.Extensions.Configuration.EnvironmentVariables` package referenced + by `OpenTelemetry`. No public API or behavioural change. + ([#7146](https://github.com/open-telemetry/opentelemetry-dotnet/pull/7146)) + ## 1.15.3 Released 2026-Apr-21 diff --git a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj index e7ae627c72f..4eb90f38be9 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj +++ b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj @@ -15,7 +15,6 @@ - diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index 2ec9532981f..0a71629630d 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -6,6 +6,13 @@ Notes](../../RELEASENOTES.md). ## Unreleased +* Replaced the vendored copy of + `EnvironmentVariablesConfigurationProvider` with a direct + `Microsoft.Extensions.Configuration.EnvironmentVariables` package dependency. + Consumers gain automatic pickup of upstream bug fixes and security patches; + no public API or behavioural change. + ([#7146](hhttps://github.com/open-telemetry/opentelemetry-dotnet/pull/7146)) + ## 1.15.3 Released 2026-Apr-21 diff --git a/src/OpenTelemetry/OpenTelemetry.csproj b/src/OpenTelemetry/OpenTelemetry.csproj index 12919a2dbee..68464bd8d38 100644 --- a/src/OpenTelemetry/OpenTelemetry.csproj +++ b/src/OpenTelemetry/OpenTelemetry.csproj @@ -8,6 +8,7 @@ + @@ -19,7 +20,6 @@ - diff --git a/src/Shared/EnvironmentVariables/EnvironmentVariablesConfigurationProvider.cs b/src/Shared/EnvironmentVariables/EnvironmentVariablesConfigurationProvider.cs deleted file mode 100644 index 8d58d641802..00000000000 --- a/src/Shared/EnvironmentVariables/EnvironmentVariablesConfigurationProvider.cs +++ /dev/null @@ -1,85 +0,0 @@ -// (Turns off StyleCop analysis in this file.) -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable enable - -using System; -using System.Collections; -using System.Collections.Generic; - -namespace Microsoft.Extensions.Configuration.EnvironmentVariables -{ - /// - /// An environment variable based . - /// - internal sealed class EnvironmentVariablesConfigurationProvider : ConfigurationProvider - { - private readonly string _prefix; - private readonly string _normalizedPrefix; - - /// - /// Initializes a new instance. - /// - public EnvironmentVariablesConfigurationProvider() - { - _prefix = string.Empty; - _normalizedPrefix = string.Empty; - } - - /// - /// Initializes a new instance with the specified prefix. - /// - /// A prefix used to filter the environment variables. - public EnvironmentVariablesConfigurationProvider(string? prefix) - { - _prefix = prefix ?? string.Empty; - _normalizedPrefix = Normalize(_prefix); - } - - /// - /// Loads the environment variables. - /// - public override void Load() => - Load(Environment.GetEnvironmentVariables()); - - /// - /// Generates a string representing this provider name and relevant details. - /// - /// The configuration name. - public override string ToString() - => $"{GetType().Name} Prefix: '{_prefix}'"; - - internal void Load(IDictionary envVariables) - { - var data = new Dictionary(StringComparer.OrdinalIgnoreCase); - - IDictionaryEnumerator e = envVariables.GetEnumerator(); - try - { - while (e.MoveNext()) - { - string key = (string)e.Entry.Key; - string? value = (string?)e.Entry.Value; - AddIfNormalizedKeyMatchesPrefix(data, Normalize(key), value); - } - } - finally - { - (e as IDisposable)?.Dispose(); - } - - Data = data; - } - - private void AddIfNormalizedKeyMatchesPrefix(Dictionary data, string normalizedKey, string? value) - { - if (normalizedKey.StartsWith(_normalizedPrefix, StringComparison.OrdinalIgnoreCase)) - { - data[normalizedKey.Substring(_normalizedPrefix.Length)] = value; - } - } - - private static string Normalize(string key) => key.Replace("__", ConfigurationPath.KeyDelimiter); - } -} diff --git a/src/Shared/EnvironmentVariables/EnvironmentVariablesConfigurationSource.cs b/src/Shared/EnvironmentVariables/EnvironmentVariablesConfigurationSource.cs deleted file mode 100644 index 2785b217475..00000000000 --- a/src/Shared/EnvironmentVariables/EnvironmentVariablesConfigurationSource.cs +++ /dev/null @@ -1,29 +0,0 @@ -// (Turns off StyleCop analysis in this file.) -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable enable - -namespace Microsoft.Extensions.Configuration.EnvironmentVariables -{ - /// - /// Represents environment variables as an . - /// - internal sealed class EnvironmentVariablesConfigurationSource : IConfigurationSource - { - /// - /// A prefix used to filter environment variables. - /// - public string? Prefix { get; set; } - - /// - /// Builds the for this source. - /// - /// The . - /// A - public IConfigurationProvider Build(IConfigurationBuilder builder) - { - return new EnvironmentVariablesConfigurationProvider(Prefix); - } - } -} diff --git a/src/Shared/EnvironmentVariables/EnvironmentVariablesExtensions.cs b/src/Shared/EnvironmentVariables/EnvironmentVariablesExtensions.cs deleted file mode 100644 index 5b97e90ce77..00000000000 --- a/src/Shared/EnvironmentVariables/EnvironmentVariablesExtensions.cs +++ /dev/null @@ -1,52 +0,0 @@ -// (Turns off StyleCop analysis in this file.) -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#nullable enable - -using System; -using Microsoft.Extensions.Configuration.EnvironmentVariables; - -namespace Microsoft.Extensions.Configuration -{ - /// - /// Extension methods for registering with . - /// - internal static class EnvironmentVariablesExtensions - { - /// - /// Adds an that reads configuration values from environment variables. - /// - /// The to add to. - /// The . - public static IConfigurationBuilder AddEnvironmentVariables(this IConfigurationBuilder configurationBuilder) - { - configurationBuilder.Add(new EnvironmentVariablesConfigurationSource()); - return configurationBuilder; - } - - /// - /// Adds an that reads configuration values from environment variables - /// with a specified prefix. - /// - /// The to add to. - /// The prefix that environment variable names must start with. The prefix will be removed from the environment variable names. - /// The . - public static IConfigurationBuilder AddEnvironmentVariables( - this IConfigurationBuilder configurationBuilder, - string? prefix) - { - configurationBuilder.Add(new EnvironmentVariablesConfigurationSource { Prefix = prefix }); - return configurationBuilder; - } - - /// - /// Adds an that reads configuration values from environment variables. - /// - /// The to add to. - /// Configures the source. - /// The . - public static IConfigurationBuilder AddEnvironmentVariables(this IConfigurationBuilder builder, Action? configureSource) - => builder.Add(configureSource); - } -} diff --git a/test/OpenTelemetry.Tests/Resources/EnvironmentVariableResourceIntegrationTests.cs b/test/OpenTelemetry.Tests/Resources/EnvironmentVariableResourceIntegrationTests.cs new file mode 100644 index 00000000000..728646226d5 --- /dev/null +++ b/test/OpenTelemetry.Tests/Resources/EnvironmentVariableResourceIntegrationTests.cs @@ -0,0 +1,33 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpenTelemetry.Tests; +using OpenTelemetry.Trace; +using Xunit; + +namespace OpenTelemetry.Resources.Tests; + +[Collection(EnvVarsCollectionDefinition.Name)] +public sealed class EnvironmentVariableResourceIntegrationTests +{ + [Fact] + public void TracerProvider_PopulatesResourceFromEnvironmentVariables() + { + // End-to-end smoke for the env-var > IConfiguration > Resource chain used by + // ResourceBuilderExtensions.AddEnvironmentVariableDetector. Drives real OTEL + // spec variables through ResourceBuilder.CreateDefault and reads the live + // Resource off the built TracerProvider. Catches any regression that breaks + // the pipeline between Environment and the SDK's exported resource. + using (new EnvironmentVariableScope("OTEL_SERVICE_NAME", "e2e-env-var-service")) + using (new EnvironmentVariableScope("OTEL_RESOURCE_ATTRIBUTES", "deployment.environment=test,region=eu-west")) + { + using var tracerProvider = Sdk.CreateTracerProviderBuilder().Build(); + + var attributes = tracerProvider.GetResource().Attributes; + + Assert.Contains(new KeyValuePair("service.name", "e2e-env-var-service"), attributes); + Assert.Contains(new KeyValuePair("deployment.environment", "test"), attributes); + Assert.Contains(new KeyValuePair("region", "eu-west"), attributes); + } + } +} diff --git a/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs b/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs index c47bc6ea517..9aab3ac66ce 100644 --- a/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs +++ b/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs @@ -2,10 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 using Microsoft.Extensions.Configuration; +using OpenTelemetry.Tests; using Xunit; namespace OpenTelemetry.Resources.Tests; +[Collection(EnvVarsCollectionDefinition.Name)] public sealed class OtelEnvResourceDetectorTests : IDisposable { public OtelEnvResourceDetectorTests() diff --git a/test/OpenTelemetry.Tests/Resources/OtelServiceNameEnvVarDetectorTests.cs b/test/OpenTelemetry.Tests/Resources/OtelServiceNameEnvVarDetectorTests.cs index e9553119ed4..e270f470a7a 100644 --- a/test/OpenTelemetry.Tests/Resources/OtelServiceNameEnvVarDetectorTests.cs +++ b/test/OpenTelemetry.Tests/Resources/OtelServiceNameEnvVarDetectorTests.cs @@ -2,10 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 using Microsoft.Extensions.Configuration; +using OpenTelemetry.Tests; using Xunit; namespace OpenTelemetry.Resources.Tests; +[Collection(EnvVarsCollectionDefinition.Name)] public sealed class OtelServiceNameEnvVarDetectorTests : IDisposable { public OtelServiceNameEnvVarDetectorTests() diff --git a/test/OpenTelemetry.Tests/Shared/EnvVarsCollectionDefinition.cs b/test/OpenTelemetry.Tests/Shared/EnvVarsCollectionDefinition.cs new file mode 100644 index 00000000000..ebc0e8a7a11 --- /dev/null +++ b/test/OpenTelemetry.Tests/Shared/EnvVarsCollectionDefinition.cs @@ -0,0 +1,21 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Xunit; + +namespace OpenTelemetry.Tests; + +/// +/// Serialization anchor for tests that mutate process-global environment +/// variables. Tests that set or clear env vars should carry +/// [Collection(EnvVarsCollectionDefinition.Name)] so they run +/// sequentially with each other, avoiding cross-class races on shared env +/// var state. +/// +[CollectionDefinition(Name, DisableParallelization = true)] +#pragma warning disable CA1515 // xUnit1027 requires [CollectionDefinition] classes to be public. +public sealed class EnvVarsCollectionDefinition +#pragma warning restore CA1515 +{ + public const string Name = "EnvVars"; +}