From f55b94c9d382555af852ab4adf3f3d5644d7e7be Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Fri, 20 Jan 2023 10:15:20 -0800 Subject: [PATCH 1/3] Remove explicit Options v5 dependency from SDK. --- build/Common.props | 2 +- .../OpenTelemetry.Exporter.Jaeger.csproj | 2 +- .../Implementation/SdkLimitOptions.cs | 2 +- ...etry.Exporter.OpenTelemetryProtocol.csproj | 2 +- .../OpenTelemetry.Exporter.Zipkin.csproj | 2 +- .../{ => Options}/ConfigurationExtensions.cs | 29 +---- .../Options/DelegatingOptionsFactory.cs | 103 ++++++++++++++++++ src/OpenTelemetry/OpenTelemetry.csproj | 1 - 8 files changed, 110 insertions(+), 33 deletions(-) rename src/OpenTelemetry/Internal/{ => Options}/ConfigurationExtensions.cs (81%) create mode 100644 src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs diff --git a/build/Common.props b/build/Common.props index 38ce3348319..a83ec292e77 100644 --- a/build/Common.props +++ b/build/Common.props @@ -41,7 +41,7 @@ [2.1.0,) [3.1.0,) $(MicrosoftExtensionsLoggingPkgVer) - [5.0.0,) + [3.1.0,) [1.0.3,2.0) [1.1.1,2.0) [0.12.1,0.13) diff --git a/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj b/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj index 2526d6422a4..e8e3576b3e5 100644 --- a/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj +++ b/src/OpenTelemetry.Exporter.Jaeger/OpenTelemetry.Exporter.Jaeger.csproj @@ -22,8 +22,8 @@ - + diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/SdkLimitOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/SdkLimitOptions.cs index 95102517733..28503c1bdad 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/SdkLimitOptions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/SdkLimitOptions.cs @@ -31,7 +31,7 @@ internal sealed class SdkLimitOptions private int? spanLinkAttributeCountLimit; private bool spanLinkAttributeCountLimitSet; - internal SdkLimitOptions() + public SdkLimitOptions() : this(new ConfigurationBuilder().AddEnvironmentVariables().Build()) { } diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj index a40f0c284b2..6098d383f33 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OpenTelemetry.Exporter.OpenTelemetryProtocol.csproj @@ -37,8 +37,8 @@ - + diff --git a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj index 4644969ac19..f8210fe6793 100644 --- a/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj +++ b/src/OpenTelemetry.Exporter.Zipkin/OpenTelemetry.Exporter.Zipkin.csproj @@ -17,8 +17,8 @@ - + diff --git a/src/OpenTelemetry/Internal/ConfigurationExtensions.cs b/src/OpenTelemetry/Internal/Options/ConfigurationExtensions.cs similarity index 81% rename from src/OpenTelemetry/Internal/ConfigurationExtensions.cs rename to src/OpenTelemetry/Internal/Options/ConfigurationExtensions.cs index 5a07e2cb2e7..5417584f36b 100644 --- a/src/OpenTelemetry/Internal/ConfigurationExtensions.cs +++ b/src/OpenTelemetry/Internal/Options/ConfigurationExtensions.cs @@ -117,7 +117,7 @@ public static bool TryGetValue( public static IServiceCollection RegisterOptionsFactory( this IServiceCollection services, Func optionsFactoryFunc) - where T : class + where T : class, new() { Debug.Assert(services != null, "services was null"); Debug.Assert(optionsFactoryFunc != null, "optionsFactoryFunc was null"); @@ -138,7 +138,7 @@ public static IServiceCollection RegisterOptionsFactory( public static IServiceCollection RegisterOptionsFactory( this IServiceCollection services, Func optionsFactoryFunc) - where T : class + where T : class, new() { Debug.Assert(services != null, "services was null"); Debug.Assert(optionsFactoryFunc != null, "optionsFactoryFunc was null"); @@ -155,29 +155,4 @@ public static IServiceCollection RegisterOptionsFactory( return services!; } - - private sealed class DelegatingOptionsFactory : OptionsFactory - where T : class - { - private readonly Func optionsFactoryFunc; - private readonly IConfiguration configuration; - - public DelegatingOptionsFactory( - Func optionsFactoryFunc, - IConfiguration configuration, - IEnumerable> setups, - IEnumerable> postConfigures, - IEnumerable> validations) - : base(setups, postConfigures, validations) - { - Debug.Assert(optionsFactoryFunc != null, "optionsFactoryFunc was null"); - Debug.Assert(configuration != null, "configuration was null"); - - this.optionsFactoryFunc = optionsFactoryFunc!; - this.configuration = configuration!; - } - - protected override T CreateInstance(string name) - => this.optionsFactoryFunc(this.configuration, name); - } } diff --git a/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs b/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs new file mode 100644 index 00000000000..7db2e72107a --- /dev/null +++ b/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs @@ -0,0 +1,103 @@ +// +// 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.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Extensions.Configuration; + +namespace Microsoft.Extensions.Options +{ + /// + /// Implementation of . + /// + /// The type of options being requested. + internal sealed class DelegatingOptionsFactory : + IOptionsFactory + where TOptions : class, new() + { + private readonly Func optionsFactoryFunc; + private readonly IConfiguration configuration; + private readonly IConfigureOptions[] _setups; + private readonly IPostConfigureOptions[] _postConfigures; + private readonly IValidateOptions[] _validations; + + /// + /// Initializes a new instance with the specified options configurations. + /// + /// The configuration actions to run. + /// The initialization actions to run. + /// The validations to run. + public DelegatingOptionsFactory( + Func optionsFactoryFunc, + IConfiguration configuration, + IEnumerable> setups, + IEnumerable> postConfigures, + IEnumerable> validations) + { + // The default DI container uses arrays under the covers. Take advantage of this knowledge + // by checking for an array and enumerate over that, so we don't need to allocate an enumerator. + // When it isn't already an array, convert it to one, but don't use System.Linq to avoid pulling Linq in to + // small trimmed applications. + + Debug.Assert(optionsFactoryFunc != null, "optionsFactoryFunc was null"); + Debug.Assert(configuration != null, "configuration was null"); + + this.optionsFactoryFunc = optionsFactoryFunc!; + this.configuration = configuration!; + _setups = setups as IConfigureOptions[] ?? new List>(setups).ToArray(); + _postConfigures = postConfigures as IPostConfigureOptions[] ?? new List>(postConfigures).ToArray(); + _validations = validations as IValidateOptions[] ?? new List>(validations).ToArray(); + } + + /// + /// Returns a configured instance with the given . + /// + /// The name of the instance to create. + /// The created instance with the given . + /// One or more return failed when validating the instance been created. + /// The does not have a public parameterless constructor or is . + public TOptions Create(string name) + { + TOptions options = this.optionsFactoryFunc(this.configuration, name); + foreach (IConfigureOptions setup in _setups) + { + if (setup is IConfigureNamedOptions namedSetup) + { + namedSetup.Configure(name, options); + } + else if (name == Options.DefaultName) + { + setup.Configure(options); + } + } + foreach (IPostConfigureOptions post in _postConfigures) + { + post.PostConfigure(name, options); + } + + if (_validations.Length > 0) + { + var failures = new List(); + foreach (IValidateOptions validate in _validations) + { + ValidateOptionsResult result = validate.Validate(name, options); + if (result is not null && result.Failed) + { + failures.AddRange(result.Failures); + } + } + if (failures.Count > 0) + { + throw new OptionsValidationException(name, typeof(TOptions), failures); + } + } + + return options; + } + } +} diff --git a/src/OpenTelemetry/OpenTelemetry.csproj b/src/OpenTelemetry/OpenTelemetry.csproj index 3e5a2273fe8..da61fa52d6a 100644 --- a/src/OpenTelemetry/OpenTelemetry.csproj +++ b/src/OpenTelemetry/OpenTelemetry.csproj @@ -22,7 +22,6 @@ - From a6c243b0db1ab157ed91ec762f212abc03e86cd9 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Fri, 20 Jan 2023 16:00:26 -0800 Subject: [PATCH 2/3] Added note. --- .../Internal/Options/DelegatingOptionsFactory.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs b/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs index 7db2e72107a..59fdd713434 100644 --- a/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs +++ b/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs @@ -1,7 +1,18 @@ -// +// (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. +/* + Note: This class was copied from + https://github.com/dotnet/runtime/blob/e13e7388dedc6672381e61592c2e74385fe781a5/src/libraries/Microsoft.Extensions.Options/src/OptionsFactory.cs + and then modified to have delegate features needed by the SDK. In the future if + we take a dependency on Microsoft.Extensions.Options v5.0.0 (or greater), much + of this can be removed in favor of the "CreateInstance" API added in 5: + https://learn.microsoft.com/dotnet/api/microsoft.extensions.options.optionsfactory-1.createinstance?view=dotnet-plat-ext-5.0. + See https://github.com/open-telemetry/opentelemetry-dotnet/pull/4093 for an + example of how that works. +*/ + #nullable enable using System; From d55e4ecb4267c60b5b3b5cf3c0a8a36df5fea183 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Tue, 24 Jan 2023 13:31:06 -0800 Subject: [PATCH 3/3] CHANGELOG patch. --- src/OpenTelemetry/CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index 73e50fafa03..d6cd869acda 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -2,9 +2,14 @@ ## Unreleased -* Removed dependency on Microsoft.Extensions.Configuration.EnvironmentVariables +* Removed the dependency on + Microsoft.Extensions.Configuration.EnvironmentVariables ([#4092](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4092)) +* Removed the explicit reference to Microsoft.Extensions.Options version 5.0 and + reverted back to the transitive reference of version 3.1 + ([#4093](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4093)) + ## 1.4.0-rc.2 Released 2023-Jan-09