From fcbe3a4aac0a7f5055c460778e1df2cba90c982b Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Thu, 6 Jul 2023 16:14:56 -0700 Subject: [PATCH 1/6] Update OTLPExporter extension method --- .../OtlpMetricExporterExtensions.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs index df4f9e5be80..5cd42e12f6d 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenTelemetry.Exporter; @@ -69,6 +70,19 @@ public static MeterProviderBuilder AddOtlpExporter( } OtlpExporterOptions.RegisterOtlpExporterOptionsFactory(services); + + services.AddOptions(finalOptionsName).Configure( + (readerOptions, config) => + { + var otlpTemporalityPreference = config["OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"]; + if (!string.IsNullOrWhiteSpace(otlpTemporalityPreference)) + { + if (Enum.TryParse(otlpTemporalityPreference, ignoreCase: true, out var enumValue)) + { + readerOptions.TemporalityPreference = enumValue; + } + } + }); }); return builder.AddReader(sp => @@ -135,6 +149,19 @@ public static MeterProviderBuilder AddOtlpExporter( builder.ConfigureServices(services => { OtlpExporterOptions.RegisterOtlpExporterOptionsFactory(services); + + services.AddOptions(name).Configure( + (readerOptions, config) => + { + var otlpTemporalityPreference = config["OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"]; + if (!string.IsNullOrWhiteSpace(otlpTemporalityPreference)) + { + if (Enum.TryParse(otlpTemporalityPreference, ignoreCase: true, out var enumValue)) + { + readerOptions.TemporalityPreference = enumValue; + } + } + }); }); return builder.AddReader(sp => From f379d0665452f5252594a93c325741410e1dfb98 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Thu, 6 Jul 2023 16:22:19 -0700 Subject: [PATCH 2/6] Add InitializationAction support in DelegatingOptionsFactory. --- .../OtlpMetricExporterExtensions.cs | 23 ++++----- .../Options/ConfigurationExtensions.cs | 18 +++++++ .../Options/DelegatingOptionsFactory.cs | 49 ++++++++++++++----- 3 files changed, 66 insertions(+), 24 deletions(-) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs index 5cd42e12f6d..fc5d3bbbbfd 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs @@ -71,16 +71,15 @@ public static MeterProviderBuilder AddOtlpExporter( OtlpExporterOptions.RegisterOtlpExporterOptionsFactory(services); - services.AddOptions(finalOptionsName).Configure( + services.RegisterOptionsFactoryInitializationAction( + finalOptionsName, (readerOptions, config) => { var otlpTemporalityPreference = config["OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"]; - if (!string.IsNullOrWhiteSpace(otlpTemporalityPreference)) + if (!string.IsNullOrWhiteSpace(otlpTemporalityPreference) + && Enum.TryParse(otlpTemporalityPreference, ignoreCase: true, out var enumValue)) { - if (Enum.TryParse(otlpTemporalityPreference, ignoreCase: true, out var enumValue)) - { - readerOptions.TemporalityPreference = enumValue; - } + readerOptions.TemporalityPreference = enumValue; } }); }); @@ -149,17 +148,15 @@ public static MeterProviderBuilder AddOtlpExporter( builder.ConfigureServices(services => { OtlpExporterOptions.RegisterOtlpExporterOptionsFactory(services); - - services.AddOptions(name).Configure( + services.RegisterOptionsFactoryInitializationAction( + name, (readerOptions, config) => { var otlpTemporalityPreference = config["OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"]; - if (!string.IsNullOrWhiteSpace(otlpTemporalityPreference)) + if (!string.IsNullOrWhiteSpace(otlpTemporalityPreference) + && Enum.TryParse(otlpTemporalityPreference, ignoreCase: true, out var enumValue)) { - if (Enum.TryParse(otlpTemporalityPreference, ignoreCase: true, out var enumValue)) - { - readerOptions.TemporalityPreference = enumValue; - } + readerOptions.TemporalityPreference = enumValue; } }); }); diff --git a/src/OpenTelemetry/Internal/Options/ConfigurationExtensions.cs b/src/OpenTelemetry/Internal/Options/ConfigurationExtensions.cs index 7a00025a104..96eca3a1d76 100644 --- a/src/OpenTelemetry/Internal/Options/ConfigurationExtensions.cs +++ b/src/OpenTelemetry/Internal/Options/ConfigurationExtensions.cs @@ -132,6 +132,7 @@ public static IServiceCollection RegisterOptionsFactory( return new DelegatingOptionsFactory( (c, n) => optionsFactoryFunc!(c), sp.GetRequiredService(), + sp.GetServices.DelegatingOptionsFactoryInitializationDelegateWrapper>(), sp.GetServices>(), sp.GetServices>(), sp.GetServices>()); @@ -153,6 +154,7 @@ public static IServiceCollection RegisterOptionsFactory( return new DelegatingOptionsFactory( (c, n) => optionsFactoryFunc!(sp, c, n), sp.GetRequiredService(), + sp.GetServices.DelegatingOptionsFactoryInitializationDelegateWrapper>(), sp.GetServices>(), sp.GetServices>(), sp.GetServices>()); @@ -160,4 +162,20 @@ public static IServiceCollection RegisterOptionsFactory( return services!; } + + public static IServiceCollection RegisterOptionsFactoryInitializationAction( + this IServiceCollection services, + string name, + Action initializationAction) + where T : class, new() + { + Debug.Assert(services != null, "services was null"); + Debug.Assert(name != null, "name was null"); + Debug.Assert(initializationAction != null, "initializationAction was null"); + + return services.AddSingleton( + new DelegatingOptionsFactory.DelegatingOptionsFactoryInitializationDelegateWrapper( + name, + initializationAction)); + } } diff --git a/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs b/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs index 59fdd713434..ddb4dca88ad 100644 --- a/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs +++ b/src/OpenTelemetry/Internal/Options/DelegatingOptionsFactory.cs @@ -31,22 +31,25 @@ internal sealed class DelegatingOptionsFactory : IOptionsFactory where TOptions : class, new() { - private readonly Func optionsFactoryFunc; - private readonly IConfiguration configuration; - private readonly IConfigureOptions[] _setups; + private readonly Func _optionsFactoryFunc; + private readonly IConfiguration _configuration; + private readonly DelegatingOptionsFactoryInitializationDelegateWrapper[] _initializations; + private readonly IConfigureOptions[] _configures; 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 initialization actions to run. + /// The configuration actions to run. + /// The post configuration actions to run. /// The validations to run. public DelegatingOptionsFactory( Func optionsFactoryFunc, IConfiguration configuration, - IEnumerable> setups, + IEnumerable initializations, + IEnumerable> configures, IEnumerable> postConfigures, IEnumerable> validations) { @@ -58,9 +61,10 @@ public DelegatingOptionsFactory( 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(); + _optionsFactoryFunc = optionsFactoryFunc!; + _configuration = configuration!; + _initializations = initializations as DelegatingOptionsFactoryInitializationDelegateWrapper[] ?? new List(initializations).ToArray(); + _configures = configures as IConfigureOptions[] ?? new List>(configures).ToArray(); _postConfigures = postConfigures as IPostConfigureOptions[] ?? new List>(postConfigures).ToArray(); _validations = validations as IValidateOptions[] ?? new List>(validations).ToArray(); } @@ -74,8 +78,15 @@ public DelegatingOptionsFactory( /// 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) + TOptions options = _optionsFactoryFunc(this._configuration, name); + foreach(var initialization in _initializations) + { + if (name == initialization.Name) + { + initialization.InitializationAction(options, _configuration); + } + } + foreach (IConfigureOptions setup in _configures) { if (setup is IConfigureNamedOptions namedSetup) { @@ -110,5 +121,21 @@ public TOptions Create(string name) return options; } + + public sealed class DelegatingOptionsFactoryInitializationDelegateWrapper + { + public string Name { get; } + + public Action InitializationAction { get; } + + public DelegatingOptionsFactoryInitializationDelegateWrapper(string name, Action initializationAction) + { + Debug.Assert(name != null, "name was null"); + Debug.Assert(initializationAction != null, "initializationAction was null"); + + Name = name; + InitializationAction = initializationAction; + } + } } } From fcba29008cef85eed8410cd3032fae39fe77c09b Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:31:05 -0700 Subject: [PATCH 3/6] Use a const string --- .../OtlpMetricExporterExtensions.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs index fc5d3bbbbfd..1c17871082f 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs @@ -14,7 +14,6 @@ // limitations under the License. // -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenTelemetry.Exporter; @@ -27,6 +26,8 @@ namespace OpenTelemetry.Metrics /// public static class OtlpMetricExporterExtensions { + internal const string OtlpMetricExporterTemporalityPreferenceEnvVarKey = "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"; + /// /// Adds to the using default options. /// @@ -75,7 +76,7 @@ public static MeterProviderBuilder AddOtlpExporter( finalOptionsName, (readerOptions, config) => { - var otlpTemporalityPreference = config["OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"]; + var otlpTemporalityPreference = config[OtlpMetricExporterTemporalityPreferenceEnvVarKey]; if (!string.IsNullOrWhiteSpace(otlpTemporalityPreference) && Enum.TryParse(otlpTemporalityPreference, ignoreCase: true, out var enumValue)) { @@ -152,7 +153,7 @@ public static MeterProviderBuilder AddOtlpExporter( name, (readerOptions, config) => { - var otlpTemporalityPreference = config["OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"]; + var otlpTemporalityPreference = config[OtlpMetricExporterTemporalityPreferenceEnvVarKey]; if (!string.IsNullOrWhiteSpace(otlpTemporalityPreference) && Enum.TryParse(otlpTemporalityPreference, ignoreCase: true, out var enumValue)) { From 1a2fa11b9f95a674644c8a69ed0402c1e768a82e Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Mon, 17 Jul 2023 15:33:59 -0700 Subject: [PATCH 4/6] Add unit test --- .../OtlpMetricsExporterTests.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs index 465901e6c01..3bd5c0a8419 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs @@ -15,6 +15,8 @@ // using System.Diagnostics.Metrics; +using System.Reflection; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; using OpenTelemetry.Metrics; @@ -704,6 +706,34 @@ public void TestHistogramToOtlpMetric(string name, string description, string un Assert.Empty(dataPoint.Exemplars); } + [Theory] + [InlineData("cumulative", MetricReaderTemporalityPreference.Cumulative)] + [InlineData("Cumulative", MetricReaderTemporalityPreference.Cumulative)] + [InlineData("CUMULATIVE", MetricReaderTemporalityPreference.Cumulative)] + [InlineData("delta", MetricReaderTemporalityPreference.Delta)] + [InlineData("Delta", MetricReaderTemporalityPreference.Delta)] + [InlineData("DELTA", MetricReaderTemporalityPreference.Delta)] + public void TestTemporalityPreferenceConfiguration(string configValue, MetricReaderTemporalityPreference expectedTemporality) + { + var configData = new Dictionary { ["OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"] = configValue }; + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(configData) + .Build(); + + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .ConfigureServices(services => services.AddSingleton(configuration)) + .AddOtlpExporter() + .Build(); + + var assembly = typeof(Sdk).Assembly; + var type = assembly.GetType("OpenTelemetry.Metrics.MeterProviderSdk"); + var fieldInfo = type.GetField("reader", BindingFlags.Instance | BindingFlags.NonPublic); + var reader = fieldInfo.GetValue(meterProvider) as MetricReader; + var temporality = reader.TemporalityPreference; + + Assert.Equal(expectedTemporality, temporality); + } + private static IEnumerable> ToAttributes(object[] keysValues) { var keys = keysValues?.Where((_, index) => index % 2 == 0).ToArray(); From 21a21601e7f91aa0b4b5f2e290724eef8ce2b0e3 Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Tue, 18 Jul 2023 14:11:31 -0700 Subject: [PATCH 5/6] Code changes --- .../OtlpMetricExporterExtensions.cs | 8 +-- src/Shared/Options/ConfigurationExtensions.cs | 18 ------- .../Options/DelegatingOptionsFactory.cs | 49 +++++-------------- .../OtlpMetricsExporterTests.cs | 22 +++++++-- 4 files changed, 34 insertions(+), 63 deletions(-) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs index 1c17871082f..18b8c5b04f9 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs @@ -14,6 +14,7 @@ // limitations under the License. // +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using OpenTelemetry.Exporter; @@ -72,8 +73,7 @@ public static MeterProviderBuilder AddOtlpExporter( OtlpExporterOptions.RegisterOtlpExporterOptionsFactory(services); - services.RegisterOptionsFactoryInitializationAction( - finalOptionsName, + services.AddOptions(finalOptionsName).Configure( (readerOptions, config) => { var otlpTemporalityPreference = config[OtlpMetricExporterTemporalityPreferenceEnvVarKey]; @@ -149,8 +149,8 @@ public static MeterProviderBuilder AddOtlpExporter( builder.ConfigureServices(services => { OtlpExporterOptions.RegisterOtlpExporterOptionsFactory(services); - services.RegisterOptionsFactoryInitializationAction( - name, + + services.AddOptions(name).Configure( (readerOptions, config) => { var otlpTemporalityPreference = config[OtlpMetricExporterTemporalityPreferenceEnvVarKey]; diff --git a/src/Shared/Options/ConfigurationExtensions.cs b/src/Shared/Options/ConfigurationExtensions.cs index 96eca3a1d76..7a00025a104 100644 --- a/src/Shared/Options/ConfigurationExtensions.cs +++ b/src/Shared/Options/ConfigurationExtensions.cs @@ -132,7 +132,6 @@ public static IServiceCollection RegisterOptionsFactory( return new DelegatingOptionsFactory( (c, n) => optionsFactoryFunc!(c), sp.GetRequiredService(), - sp.GetServices.DelegatingOptionsFactoryInitializationDelegateWrapper>(), sp.GetServices>(), sp.GetServices>(), sp.GetServices>()); @@ -154,7 +153,6 @@ public static IServiceCollection RegisterOptionsFactory( return new DelegatingOptionsFactory( (c, n) => optionsFactoryFunc!(sp, c, n), sp.GetRequiredService(), - sp.GetServices.DelegatingOptionsFactoryInitializationDelegateWrapper>(), sp.GetServices>(), sp.GetServices>(), sp.GetServices>()); @@ -162,20 +160,4 @@ public static IServiceCollection RegisterOptionsFactory( return services!; } - - public static IServiceCollection RegisterOptionsFactoryInitializationAction( - this IServiceCollection services, - string name, - Action initializationAction) - where T : class, new() - { - Debug.Assert(services != null, "services was null"); - Debug.Assert(name != null, "name was null"); - Debug.Assert(initializationAction != null, "initializationAction was null"); - - return services.AddSingleton( - new DelegatingOptionsFactory.DelegatingOptionsFactoryInitializationDelegateWrapper( - name, - initializationAction)); - } } diff --git a/src/Shared/Options/DelegatingOptionsFactory.cs b/src/Shared/Options/DelegatingOptionsFactory.cs index ddb4dca88ad..59fdd713434 100644 --- a/src/Shared/Options/DelegatingOptionsFactory.cs +++ b/src/Shared/Options/DelegatingOptionsFactory.cs @@ -31,25 +31,22 @@ internal sealed class DelegatingOptionsFactory : IOptionsFactory where TOptions : class, new() { - private readonly Func _optionsFactoryFunc; - private readonly IConfiguration _configuration; - private readonly DelegatingOptionsFactoryInitializationDelegateWrapper[] _initializations; - private readonly IConfigureOptions[] _configures; + 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 initialization actions to run. - /// The configuration actions to run. - /// The post configuration actions to run. + /// The configuration actions to run. + /// The initialization actions to run. /// The validations to run. public DelegatingOptionsFactory( Func optionsFactoryFunc, IConfiguration configuration, - IEnumerable initializations, - IEnumerable> configures, + IEnumerable> setups, IEnumerable> postConfigures, IEnumerable> validations) { @@ -61,10 +58,9 @@ public DelegatingOptionsFactory( Debug.Assert(optionsFactoryFunc != null, "optionsFactoryFunc was null"); Debug.Assert(configuration != null, "configuration was null"); - _optionsFactoryFunc = optionsFactoryFunc!; - _configuration = configuration!; - _initializations = initializations as DelegatingOptionsFactoryInitializationDelegateWrapper[] ?? new List(initializations).ToArray(); - _configures = configures as IConfigureOptions[] ?? new List>(configures).ToArray(); + 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(); } @@ -78,15 +74,8 @@ public DelegatingOptionsFactory( /// The does not have a public parameterless constructor or is . public TOptions Create(string name) { - TOptions options = _optionsFactoryFunc(this._configuration, name); - foreach(var initialization in _initializations) - { - if (name == initialization.Name) - { - initialization.InitializationAction(options, _configuration); - } - } - foreach (IConfigureOptions setup in _configures) + TOptions options = this.optionsFactoryFunc(this.configuration, name); + foreach (IConfigureOptions setup in _setups) { if (setup is IConfigureNamedOptions namedSetup) { @@ -121,21 +110,5 @@ public TOptions Create(string name) return options; } - - public sealed class DelegatingOptionsFactoryInitializationDelegateWrapper - { - public string Name { get; } - - public Action InitializationAction { get; } - - public DelegatingOptionsFactoryInitializationDelegateWrapper(string name, Action initializationAction) - { - Debug.Assert(name != null, "name was null"); - Debug.Assert(initializationAction != null, "initializationAction was null"); - - Name = name; - InitializationAction = initializationAction; - } - } } } diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs index 3bd5c0a8419..8cf45f910b6 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs @@ -720,18 +720,34 @@ public void TestTemporalityPreferenceConfiguration(string configValue, MetricRea .AddInMemoryCollection(configData) .Build(); - using var meterProvider = Sdk.CreateMeterProviderBuilder() + // Check for both the code paths: + // 1. The final extension method which accepts `Action`. + // 2. The final extension method which accepts `Action`. + + // Test 1st code path + using var meterProvider1 = Sdk.CreateMeterProviderBuilder() .ConfigureServices(services => services.AddSingleton(configuration)) - .AddOtlpExporter() + .AddOtlpExporter() // This would in turn call the extension method which accepts `Action` .Build(); var assembly = typeof(Sdk).Assembly; var type = assembly.GetType("OpenTelemetry.Metrics.MeterProviderSdk"); var fieldInfo = type.GetField("reader", BindingFlags.Instance | BindingFlags.NonPublic); - var reader = fieldInfo.GetValue(meterProvider) as MetricReader; + var reader = fieldInfo.GetValue(meterProvider1) as MetricReader; var temporality = reader.TemporalityPreference; Assert.Equal(expectedTemporality, temporality); + + // Test 2nd code path + using var meterProvider2 = Sdk.CreateMeterProviderBuilder() + .ConfigureServices(services => services.AddSingleton(configuration)) + .AddOtlpExporter((_, _) => { }) // This would in turn call the extension method which accepts `Action` + .Build(); + + reader = fieldInfo.GetValue(meterProvider2) as MetricReader; + temporality = reader.TemporalityPreference; + + Assert.Equal(expectedTemporality, temporality); } private static IEnumerable> ToAttributes(object[] keysValues) From 9d3f89ae3e20103e4b083d15de83c9d85ef463d4 Mon Sep 17 00:00:00 2001 From: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> Date: Tue, 18 Jul 2023 14:50:35 -0700 Subject: [PATCH 6/6] Update CHANGELOG --- .../CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index b8ce4b2b252..44de41e6946 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +* Added support for configuring the metric exporter's temporality using the + environment variable `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` as + defined in the + [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.23.0/specification/metrics/sdk_exporters/otlp.md#additional-configuration). + ([#4667](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4667)) + ## 1.6.0-alpha.1 Released 2023-Jul-12