From 0f9944e67230ed162ac5b4d2bcf4c154af869a24 Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 23 Nov 2021 12:50:36 -0800 Subject: [PATCH 1/3] refactor temporality to align with the spec --- .../ConsoleExporterMetricsExtensions.cs | 2 +- .../ConsoleMetricExporter.cs | 1 - .../OtlpMetricExporter.cs | 1 - .../OtlpMetricExporterExtensions.cs | 2 +- .../.publicApi/net461/PublicAPI.Unshipped.txt | 12 +- .../netstandard2.0/PublicAPI.Unshipped.txt | 12 +- .../AggregationTemporalityAttribute.cs | 17 +- .../Metrics/BaseExportingMetricReader.cs | 3 +- src/OpenTelemetry/Metrics/MetricReader.cs | 53 ++--- src/OpenTelemetry/Metrics/MetricReaderExt.cs | 4 +- .../Metrics/MetricCollectBenchmarks.cs | 2 +- test/Benchmarks/Metrics/MetricsBenchmarks.cs | 6 +- .../OtlpMetricsExporterTests.cs | 5 +- .../MetricTests.cs | 2 +- .../HttpClientTests.netcore31.cs | 2 +- .../Metrics/InMemoryExporterTests.cs | 10 +- .../Metrics/MemoryEfficiencyTests.cs | 2 +- .../Metrics/MetricAPITest.cs | 220 ++++++++---------- .../Metrics/MultipleReadersTests.cs | 50 ++-- 19 files changed, 176 insertions(+), 230 deletions(-) diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleExporterMetricsExtensions.cs b/src/OpenTelemetry.Exporter.Console/ConsoleExporterMetricsExtensions.cs index d75a31bbee2..3a19817d054 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleExporterMetricsExtensions.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleExporterMetricsExtensions.cs @@ -42,7 +42,7 @@ public static MeterProviderBuilder AddConsoleExporter(this MeterProviderBuilder ? new BaseExportingMetricReader(exporter) : new PeriodicExportingMetricReader(exporter, options.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds); - reader.PreferredAggregationTemporality = options.AggregationTemporality; + reader.Temporality = options.AggregationTemporality; return builder.AddReader(reader); } diff --git a/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs b/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs index 3465f413143..0e3fbf59ef5 100644 --- a/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs +++ b/src/OpenTelemetry.Exporter.Console/ConsoleMetricExporter.cs @@ -22,7 +22,6 @@ namespace OpenTelemetry.Exporter { - [AggregationTemporality(AggregationTemporality.Cumulative | AggregationTemporality.Delta, AggregationTemporality.Cumulative)] public class ConsoleMetricExporter : ConsoleExporter { private Resource resource; diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporter.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporter.cs index 7ccf94f94e8..bf1317aa7f4 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporter.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporter.cs @@ -27,7 +27,6 @@ namespace OpenTelemetry.Exporter /// Exporter consuming and exporting the data using /// the OpenTelemetry protocol (OTLP). /// - [AggregationTemporality(AggregationTemporality.Cumulative | AggregationTemporality.Delta, AggregationTemporality.Cumulative)] public class OtlpMetricExporter : BaseExporter { private readonly IExportClient exportClient; diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs index 9cc3d193e53..8b314befe5a 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpMetricExporterExtensions.cs @@ -56,7 +56,7 @@ private static MeterProviderBuilder AddOtlpExporter(MeterProviderBuilder builder var metricExporter = new OtlpMetricExporter(options); var metricReader = new PeriodicExportingMetricReader(metricExporter, options.MetricExportIntervalMilliseconds); - metricReader.PreferredAggregationTemporality = options.AggregationTemporality; + metricReader.Temporality = options.AggregationTemporality; return builder.AddReader(metricReader); } } diff --git a/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt index 4d61f50b233..7e074a3c4b5 100644 --- a/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt @@ -6,10 +6,8 @@ OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporality.Cumulative = 1 -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporality.Delta = 2 -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporalityAttribute -OpenTelemetry.Metrics.AggregationTemporalityAttribute.AggregationTemporalityAttribute(OpenTelemetry.Metrics.AggregationTemporality supported) -> void -OpenTelemetry.Metrics.AggregationTemporalityAttribute.AggregationTemporalityAttribute(OpenTelemetry.Metrics.AggregationTemporality supported, OpenTelemetry.Metrics.AggregationTemporality preferred) -> void -OpenTelemetry.Metrics.AggregationTemporalityAttribute.Preferred.get -> OpenTelemetry.Metrics.AggregationTemporality -OpenTelemetry.Metrics.AggregationTemporalityAttribute.Supported.get -> OpenTelemetry.Metrics.AggregationTemporality +OpenTelemetry.Metrics.AggregationTemporalityAttribute.AggregationTemporalityAttribute(OpenTelemetry.Metrics.AggregationTemporality temporality) -> void +OpenTelemetry.Metrics.AggregationTemporalityAttribute.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.BaseExportingMetricReader OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void OpenTelemetry.Metrics.BaseExportingMetricReader.SupportedExportModes.get -> OpenTelemetry.Metrics.ExportModes @@ -65,11 +63,9 @@ OpenTelemetry.Metrics.MetricReader.Collect(int timeoutMilliseconds = -1) -> bool OpenTelemetry.Metrics.MetricReader.Dispose() -> void OpenTelemetry.Metrics.MetricReader.MetricReader() -> void OpenTelemetry.Metrics.MetricReader.ParentProvider.get -> OpenTelemetry.BaseProvider -OpenTelemetry.Metrics.MetricReader.PreferredAggregationTemporality.get -> OpenTelemetry.Metrics.AggregationTemporality -OpenTelemetry.Metrics.MetricReader.PreferredAggregationTemporality.set -> void OpenTelemetry.Metrics.MetricReader.Shutdown(int timeoutMilliseconds = -1) -> bool -OpenTelemetry.Metrics.MetricReader.SupportedAggregationTemporality.get -> OpenTelemetry.Metrics.AggregationTemporality -OpenTelemetry.Metrics.MetricReader.SupportedAggregationTemporality.set -> void +OpenTelemetry.Metrics.MetricReader.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality +OpenTelemetry.Metrics.MetricReader.Temporality.set -> void OpenTelemetry.Metrics.MetricReaderType OpenTelemetry.Metrics.MetricReaderType.Manual = 0 -> OpenTelemetry.Metrics.MetricReaderType OpenTelemetry.Metrics.MetricReaderType.Periodic = 1 -> OpenTelemetry.Metrics.MetricReaderType diff --git a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt index 4d61f50b233..7e074a3c4b5 100644 --- a/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -6,10 +6,8 @@ OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporality.Cumulative = 1 -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporality.Delta = 2 -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.AggregationTemporalityAttribute -OpenTelemetry.Metrics.AggregationTemporalityAttribute.AggregationTemporalityAttribute(OpenTelemetry.Metrics.AggregationTemporality supported) -> void -OpenTelemetry.Metrics.AggregationTemporalityAttribute.AggregationTemporalityAttribute(OpenTelemetry.Metrics.AggregationTemporality supported, OpenTelemetry.Metrics.AggregationTemporality preferred) -> void -OpenTelemetry.Metrics.AggregationTemporalityAttribute.Preferred.get -> OpenTelemetry.Metrics.AggregationTemporality -OpenTelemetry.Metrics.AggregationTemporalityAttribute.Supported.get -> OpenTelemetry.Metrics.AggregationTemporality +OpenTelemetry.Metrics.AggregationTemporalityAttribute.AggregationTemporalityAttribute(OpenTelemetry.Metrics.AggregationTemporality temporality) -> void +OpenTelemetry.Metrics.AggregationTemporalityAttribute.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality OpenTelemetry.Metrics.BaseExportingMetricReader OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter exporter) -> void OpenTelemetry.Metrics.BaseExportingMetricReader.SupportedExportModes.get -> OpenTelemetry.Metrics.ExportModes @@ -65,11 +63,9 @@ OpenTelemetry.Metrics.MetricReader.Collect(int timeoutMilliseconds = -1) -> bool OpenTelemetry.Metrics.MetricReader.Dispose() -> void OpenTelemetry.Metrics.MetricReader.MetricReader() -> void OpenTelemetry.Metrics.MetricReader.ParentProvider.get -> OpenTelemetry.BaseProvider -OpenTelemetry.Metrics.MetricReader.PreferredAggregationTemporality.get -> OpenTelemetry.Metrics.AggregationTemporality -OpenTelemetry.Metrics.MetricReader.PreferredAggregationTemporality.set -> void OpenTelemetry.Metrics.MetricReader.Shutdown(int timeoutMilliseconds = -1) -> bool -OpenTelemetry.Metrics.MetricReader.SupportedAggregationTemporality.get -> OpenTelemetry.Metrics.AggregationTemporality -OpenTelemetry.Metrics.MetricReader.SupportedAggregationTemporality.set -> void +OpenTelemetry.Metrics.MetricReader.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality +OpenTelemetry.Metrics.MetricReader.Temporality.set -> void OpenTelemetry.Metrics.MetricReaderType OpenTelemetry.Metrics.MetricReaderType.Manual = 0 -> OpenTelemetry.Metrics.MetricReaderType OpenTelemetry.Metrics.MetricReaderType.Periodic = 1 -> OpenTelemetry.Metrics.MetricReaderType diff --git a/src/OpenTelemetry/Metrics/AggregationTemporalityAttribute.cs b/src/OpenTelemetry/Metrics/AggregationTemporalityAttribute.cs index 89579fcd73f..e3d2212224b 100644 --- a/src/OpenTelemetry/Metrics/AggregationTemporalityAttribute.cs +++ b/src/OpenTelemetry/Metrics/AggregationTemporalityAttribute.cs @@ -21,22 +21,13 @@ namespace OpenTelemetry.Metrics [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public sealed class AggregationTemporalityAttribute : Attribute { - private AggregationTemporality preferredAggregationTemporality; - private AggregationTemporality supportedAggregationTemporality; + private AggregationTemporality temporality; - public AggregationTemporalityAttribute(AggregationTemporality supported) - : this(supported, supported) + public AggregationTemporalityAttribute(AggregationTemporality temporality) { + this.temporality = temporality; } - public AggregationTemporalityAttribute(AggregationTemporality supported, AggregationTemporality preferred) - { - this.supportedAggregationTemporality = supported; - this.preferredAggregationTemporality = preferred; - } - - public AggregationTemporality Preferred => this.preferredAggregationTemporality; - - public AggregationTemporality Supported => this.supportedAggregationTemporality; + public AggregationTemporality Temporality => this.temporality; } } diff --git a/src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs b/src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs index 146ea4d8100..579b92bdb59 100644 --- a/src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs +++ b/src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs @@ -38,8 +38,7 @@ public BaseExportingMetricReader(BaseExporter exporter) if (attributes.Length > 0) { var attr = (AggregationTemporalityAttribute)attributes[attributes.Length - 1]; - this.PreferredAggregationTemporality = attr.Preferred; - this.SupportedAggregationTemporality = attr.Supported; + this.Temporality = attr.Temporality; } attributes = exportorType.GetCustomAttributes(typeof(ExportModesAttribute), true); diff --git a/src/OpenTelemetry/Metrics/MetricReader.cs b/src/OpenTelemetry/Metrics/MetricReader.cs index 99c5c05c260..bf7858b5d1e 100644 --- a/src/OpenTelemetry/Metrics/MetricReader.cs +++ b/src/OpenTelemetry/Metrics/MetricReader.cs @@ -27,34 +27,36 @@ namespace OpenTelemetry.Metrics /// public abstract partial class MetricReader : IDisposable { - private const AggregationTemporality CumulativeAndDelta = AggregationTemporality.Cumulative | AggregationTemporality.Delta; + private const AggregationTemporality AggregationTemporalityUnspecified = (AggregationTemporality)0; private readonly object newTaskLock = new object(); private readonly object onCollectLock = new object(); private readonly TaskCompletionSource shutdownTcs = new TaskCompletionSource(); - private AggregationTemporality preferredAggregationTemporality = CumulativeAndDelta; - private AggregationTemporality supportedAggregationTemporality = CumulativeAndDelta; + private AggregationTemporality temporality = AggregationTemporalityUnspecified; private int shutdownCount; private TaskCompletionSource collectionTcs; public BaseProvider ParentProvider { get; private set; } - public AggregationTemporality PreferredAggregationTemporality + public AggregationTemporality Temporality { - get => this.preferredAggregationTemporality; - set + get { - ValidateAggregationTemporality(value, this.supportedAggregationTemporality); - this.preferredAggregationTemporality = value; + if (this.temporality == AggregationTemporalityUnspecified) + { + this.temporality = AggregationTemporality.Cumulative; + } + + return this.temporality; } - } - public AggregationTemporality SupportedAggregationTemporality - { - get => this.supportedAggregationTemporality; set { - ValidateAggregationTemporality(this.preferredAggregationTemporality, value); - this.supportedAggregationTemporality = value; + if (this.temporality != AggregationTemporalityUnspecified) + { + throw new NotSupportedException(); // TODO: add details + } + + this.temporality = value; } } @@ -268,28 +270,5 @@ protected virtual bool OnShutdown(int timeoutMilliseconds) protected virtual void Dispose(bool disposing) { } - - private static void ValidateAggregationTemporality(AggregationTemporality preferred, AggregationTemporality supported) - { - Guard.Zero((int)(preferred & CumulativeAndDelta), $"PreferredAggregationTemporality has an invalid value {preferred}", nameof(preferred)); - Guard.Zero((int)(supported & CumulativeAndDelta), $"SupportedAggregationTemporality has an invalid value {supported}", nameof(supported)); - - /* - | Preferred | Supported | Valid | - | ---------- | ---------- | ----- | - | Both | Both | true | - | Both | Cumulative | false | - | Both | Delta | false | - | Cumulative | Both | true | - | Cumulative | Cumulative | true | - | Cumulative | Delta | false | - | Delta | Both | true | - | Delta | Cumulative | false | - | Delta | Delta | true | - */ - string message = $"PreferredAggregationTemporality {preferred} and SupportedAggregationTemporality {supported} are incompatible"; - Guard.Zero((int)(preferred & supported), message, nameof(preferred)); - Guard.Range((int)preferred, nameof(preferred), max: (int)supported, maxName: nameof(supported), message: message); - } } } diff --git a/src/OpenTelemetry/Metrics/MetricReaderExt.cs b/src/OpenTelemetry/Metrics/MetricReaderExt.cs index 7cd50392aae..8dd322c56f8 100644 --- a/src/OpenTelemetry/Metrics/MetricReaderExt.cs +++ b/src/OpenTelemetry/Metrics/MetricReaderExt.cs @@ -55,7 +55,7 @@ internal Metric AddMetricWithNoViews(Instrument instrument) } else { - var metric = new Metric(instrument, this.preferredAggregationTemporality, metricName, instrument.Description, this.maxMetricPointsPerMetricStream); + var metric = new Metric(instrument, this.Temporality, metricName, instrument.Description, this.maxMetricPointsPerMetricStream); this.metrics[index] = metric; this.metricStreamNames.Add(metricStreamName); return metric; @@ -131,7 +131,7 @@ internal List AddMetricsListWithViews(Instrument instrument, List batch) this.reader = new BaseExportingMetricReader(metricExporter) { - PreferredAggregationTemporality = AggregationTemporality.Cumulative, + Temporality = AggregationTemporality.Cumulative, }; this.meter = new Meter(Utils.GetCurrentMethodName()); diff --git a/test/Benchmarks/Metrics/MetricsBenchmarks.cs b/test/Benchmarks/Metrics/MetricsBenchmarks.cs index 472fc8ab7f6..0fbef5a11b7 100644 --- a/test/Benchmarks/Metrics/MetricsBenchmarks.cs +++ b/test/Benchmarks/Metrics/MetricsBenchmarks.cs @@ -71,8 +71,10 @@ public void Setup() this.meter = new Meter(Utils.GetCurrentMethodName()); var exportedItems = new List(); - var reader = new PeriodicExportingMetricReader(new InMemoryExporter(exportedItems), 1000); - reader.PreferredAggregationTemporality = this.AggregationTemporality; + var reader = new PeriodicExportingMetricReader(new InMemoryExporter(exportedItems), 1000) + { + Temporality = this.AggregationTemporality, + }; this.provider = Sdk.CreateMeterProviderBuilder() .AddMeter(this.meter.Name) // All instruments from this meter are enabled. .AddReader(reader) diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs index c9ab346fae3..f19925b3a5b 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpMetricsExporterTests.cs @@ -62,7 +62,10 @@ public void ToOtlpResourceMetricsTest(bool includeServiceNameInResource) using var provider = Sdk.CreateMeterProviderBuilder() .SetResourceBuilder(resourceBuilder) .AddMeter(meter.Name) - .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) { PreferredAggregationTemporality = AggregationTemporality.Delta }) + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = AggregationTemporality.Delta, + }) .Build(); var counter = meter.CreateCounter("counter"); diff --git a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/MetricTests.cs b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/MetricTests.cs index 5fa27849d0b..b5845ca4775 100644 --- a/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/MetricTests.cs +++ b/test/OpenTelemetry.Instrumentation.AspNetCore.Tests/MetricTests.cs @@ -62,7 +62,7 @@ public async Task RequestMetricIsCaptured() var metricReader = new BaseExportingMetricReader(metricExporter) { - PreferredAggregationTemporality = AggregationTemporality.Cumulative, + Temporality = AggregationTemporality.Cumulative, }; this.meterProvider = Sdk.CreateMeterProviderBuilder() .AddAspNetCoreInstrumentation() diff --git a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.netcore31.cs b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.netcore31.cs index 0931b314c5b..a843e9fab4b 100644 --- a/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.netcore31.cs +++ b/test/OpenTelemetry.Instrumentation.Http.Tests/HttpClientTests.netcore31.cs @@ -60,7 +60,7 @@ public async Task HttpOutCallsAreCollectedSuccessfullyAsync(HttpTestData.HttpOut var metricReader = new BaseExportingMetricReader(metricExporter) { - PreferredAggregationTemporality = AggregationTemporality.Cumulative, + Temporality = AggregationTemporality.Cumulative, }; var meterProvider = Sdk.CreateMeterProviderBuilder() .AddHttpClientInstrumentation() diff --git a/test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs b/test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs index b00b8165bfa..77cbd7516b2 100644 --- a/test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs +++ b/test/OpenTelemetry.Tests/Metrics/InMemoryExporterTests.cs @@ -27,14 +27,14 @@ public class InMemoryExporterTests [Fact(Skip = "To be run after https://github.com/open-telemetry/opentelemetry-dotnet/issues/2361 is fixed")] public void InMemoryExporterShouldDeepCopyMetricPoints() { - var metrics = new List(); + var exportedItems = new List(); using var meter = new Meter(Utils.GetCurrentMethodName()); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) - .AddReader(new BaseExportingMetricReader(new InMemoryExporter(metrics)) + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) { - PreferredAggregationTemporality = AggregationTemporality.Delta, + Temporality = AggregationTemporality.Delta, }) .Build(); @@ -45,7 +45,7 @@ public void InMemoryExporterShouldDeepCopyMetricPoints() meterProvider.ForceFlush(); - var metric = metrics[0]; // Only one Metric object is added to the collection at this point + var metric = exportedItems[0]; // Only one Metric object is added to the collection at this point var metricPointsEnumerator = metric.GetMetricPoints().GetEnumerator(); Assert.True(metricPointsEnumerator.MoveNext()); // One MetricPoint is emitted for the Metric ref var metricPointForFirstExport = ref metricPointsEnumerator.Current; @@ -56,7 +56,7 @@ public void InMemoryExporterShouldDeepCopyMetricPoints() meterProvider.ForceFlush(); - metric = metrics[1]; // Second Metric object is added to the collection at this point + metric = exportedItems[1]; // Second Metric object is added to the collection at this point metricPointsEnumerator = metric.GetMetricPoints().GetEnumerator(); Assert.True(metricPointsEnumerator.MoveNext()); // One MetricPoint is emitted for the Metric var metricPointForSecondExport = metricPointsEnumerator.Current; diff --git a/test/OpenTelemetry.Tests/Metrics/MemoryEfficiencyTests.cs b/test/OpenTelemetry.Tests/Metrics/MemoryEfficiencyTests.cs index e70e5509680..c241519b95e 100644 --- a/test/OpenTelemetry.Tests/Metrics/MemoryEfficiencyTests.cs +++ b/test/OpenTelemetry.Tests/Metrics/MemoryEfficiencyTests.cs @@ -38,7 +38,7 @@ public void ExportOnlyWhenPointChanged(AggregationTemporality temporality) .AddReader( new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) { - PreferredAggregationTemporality = temporality, + Temporality = temporality, }) .Build(); diff --git a/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs b/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs index ec646ad622f..6e6a03577a9 100644 --- a/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs +++ b/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs @@ -106,17 +106,15 @@ public void ObserverCallbackExceptionTest() [InlineData(AggregationTemporality.Delta, false)] public void DuplicateInstrumentNamesFromSameMeterAreNotAllowed(AggregationTemporality temporality, bool hasView) { - var metricItems = new List(); - var metricExporter = new InMemoryExporter(metricItems); + var exportedItems = new List(); - var metricReader = new BaseExportingMetricReader(metricExporter) - { - PreferredAggregationTemporality = temporality, - }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}"); var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) - .AddReader(metricReader); + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = temporality, + }); if (hasView) { @@ -128,8 +126,8 @@ public void DuplicateInstrumentNamesFromSameMeterAreNotAllowed(AggregationTempor // Expecting one metric stream. var counterLong = meter.CreateCounter("name1"); counterLong.Add(10); - metricReader.Collect(); - Assert.Single(metricItems); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Single(exportedItems); // The following will be ignored as // metric of same name exists. @@ -137,9 +135,9 @@ public void DuplicateInstrumentNamesFromSameMeterAreNotAllowed(AggregationTempor var anotherCounterSameName = meter.CreateCounter("name1"); anotherCounterSameName.Add(10); counterLong.Add(10); - metricItems.Clear(); - metricReader.Collect(); - Assert.Single(metricItems); + exportedItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Single(exportedItems); } [Theory] @@ -149,19 +147,17 @@ public void DuplicateInstrumentNamesFromSameMeterAreNotAllowed(AggregationTempor [InlineData(AggregationTemporality.Delta, false)] public void DuplicateInstrumentNamesFromDifferentMetersAreAllowed(AggregationTemporality temporality, bool hasView) { - var metricItems = new List(); - var metricExporter = new InMemoryExporter(metricItems); + var exportedItems = new List(); - var metricReader = new BaseExportingMetricReader(metricExporter) - { - PreferredAggregationTemporality = temporality, - }; using var meter1 = new Meter($"{Utils.GetCurrentMethodName()}.1.{temporality}"); using var meter2 = new Meter($"{Utils.GetCurrentMethodName()}.2.{temporality}"); var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter1.Name) .AddMeter(meter2.Name) - .AddReader(metricReader); + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = temporality, + }); if (hasView) { @@ -173,17 +169,17 @@ public void DuplicateInstrumentNamesFromDifferentMetersAreAllowed(AggregationTem // Expecting one metric stream. var counterLong = meter1.CreateCounter("name1"); counterLong.Add(10); - metricReader.Collect(); - Assert.Single(metricItems); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Single(exportedItems); // The following will not be ignored // as it is the same metric name but different meter. var anotherCounterSameNameDiffMeter = meter2.CreateCounter("name1"); anotherCounterSameNameDiffMeter.Add(10); counterLong.Add(10); - metricItems.Clear(); - metricReader.Collect(); - Assert.Equal(2, metricItems.Count); + exportedItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Equal(2, exportedItems.Count); } [Theory] @@ -271,32 +267,29 @@ public void MeterSourcesWildcardSupportNegativeTestNoMeterAdded(bool hasView) [InlineData(false)] public void CounterAggregationTest(bool exportDelta) { - var metricItems = new List(); - var metricExporter = new InMemoryExporter(metricItems); - - var metricReader = new BaseExportingMetricReader(metricExporter) - { - PreferredAggregationTemporality = exportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative, - }; + var exportedItems = new List(); using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}"); var counterLong = meter.CreateCounter("mycounter"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) - .AddReader(metricReader) + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = exportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative, + }) .Build(); counterLong.Add(10); counterLong.Add(10); - metricReader.Collect(); - long sumReceived = GetLongSum(metricItems); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + long sumReceived = GetLongSum(exportedItems); Assert.Equal(20, sumReceived); - metricItems.Clear(); + exportedItems.Clear(); counterLong.Add(10); counterLong.Add(10); - metricReader.Collect(); - sumReceived = GetLongSum(metricItems); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + sumReceived = GetLongSum(exportedItems); if (exportDelta) { Assert.Equal(20, sumReceived); @@ -306,9 +299,9 @@ public void CounterAggregationTest(bool exportDelta) Assert.Equal(40, sumReceived); } - metricItems.Clear(); - metricReader.Collect(); - sumReceived = GetLongSum(metricItems); + exportedItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + sumReceived = GetLongSum(exportedItems); if (exportDelta) { Assert.Equal(0, sumReceived); @@ -318,11 +311,11 @@ public void CounterAggregationTest(bool exportDelta) Assert.Equal(40, sumReceived); } - metricItems.Clear(); + exportedItems.Clear(); counterLong.Add(40); counterLong.Add(20); - metricReader.Collect(); - sumReceived = GetLongSum(metricItems); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + sumReceived = GetLongSum(exportedItems); if (exportDelta) { Assert.Equal(60, sumReceived); @@ -338,37 +331,36 @@ public void CounterAggregationTest(bool exportDelta) [InlineData(false)] public void ObservableCounterAggregationTest(bool exportDelta) { - var metricItems = new List(); - var metricExporter = new InMemoryExporter(metricItems); + var exportedItems = new List(); - var metricReader = new BaseExportingMetricReader(metricExporter) - { - PreferredAggregationTemporality = exportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative, - }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}"); int i = 1; var counterLong = meter.CreateObservableCounter( - "observable-counter", - () => - { - return new List>() + "observable-counter", + () => { - new Measurement(i++ * 10), - }; - }); + return new List>() + { + new Measurement(i++ * 10), + }; + }); + using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) - .AddReader(metricReader) + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = exportDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative, + }) .Build(); - metricReader.Collect(); - long sumReceived = GetLongSum(metricItems); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + long sumReceived = GetLongSum(exportedItems); Assert.Equal(10, sumReceived); - metricItems.Clear(); - metricReader.Collect(); - sumReceived = GetLongSum(metricItems); + exportedItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + sumReceived = GetLongSum(exportedItems); if (exportDelta) { Assert.Equal(10, sumReceived); @@ -378,9 +370,9 @@ public void ObservableCounterAggregationTest(bool exportDelta) Assert.Equal(20, sumReceived); } - metricItems.Clear(); - metricReader.Collect(); - sumReceived = GetLongSum(metricItems); + exportedItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + sumReceived = GetLongSum(exportedItems); if (exportDelta) { Assert.Equal(10, sumReceived); @@ -396,12 +388,7 @@ public void ObservableCounterAggregationTest(bool exportDelta) [InlineData(AggregationTemporality.Delta)] public void TestInstrumentDisposal(AggregationTemporality temporality) { - var metricItems = new List(); - var metricExporter = new InMemoryExporter(metricItems); - var metricReader = new BaseExportingMetricReader(metricExporter) - { - PreferredAggregationTemporality = temporality, - }; + var exportedItems = new List(); var meter1 = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}.1"); var meter2 = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}.2"); @@ -410,42 +397,45 @@ public void TestInstrumentDisposal(AggregationTemporality temporality) using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter1.Name) .AddMeter(meter2.Name) - .AddReader(metricReader) + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = temporality, + }) .Build(); counter1.Add(10, new KeyValuePair("key", "value")); counter2.Add(10, new KeyValuePair("key", "value")); - metricReader.Collect(); - Assert.Equal(2, metricItems.Count); - metricItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Equal(2, exportedItems.Count); + exportedItems.Clear(); counter1.Add(10, new KeyValuePair("key", "value")); counter2.Add(10, new KeyValuePair("key", "value")); meter1.Dispose(); - metricReader.Collect(); - Assert.Equal(2, metricItems.Count); - metricItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Equal(2, exportedItems.Count); + exportedItems.Clear(); counter1.Add(10, new KeyValuePair("key", "value")); counter2.Add(10, new KeyValuePair("key", "value")); - metricReader.Collect(); - Assert.Single(metricItems); - metricItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Single(exportedItems); + exportedItems.Clear(); counter1.Add(10, new KeyValuePair("key", "value")); counter2.Add(10, new KeyValuePair("key", "value")); meter2.Dispose(); - metricReader.Collect(); - Assert.Single(metricItems); - metricItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Single(exportedItems); + exportedItems.Clear(); counter1.Add(10, new KeyValuePair("key", "value")); counter2.Add(10, new KeyValuePair("key", "value")); - metricReader.Collect(); - Assert.Empty(metricItems); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); + Assert.Empty(exportedItems); } [Theory] @@ -453,14 +443,13 @@ public void TestInstrumentDisposal(AggregationTemporality temporality) [InlineData(AggregationTemporality.Delta)] public void TestMetricPointCap(AggregationTemporality temporality) { - var metricItems = new List(); - var metricExporter = new InMemoryExporter(metricItems); + var exportedItems = new List(); int MetricPointCount() { var count = 0; - foreach (var metric in metricItems) + foreach (var metric in exportedItems) { foreach (ref var metricPoint in metric.GetMetricPoints()) { @@ -471,15 +460,14 @@ int MetricPointCount() return count; } - var metricReader = new BaseExportingMetricReader(metricExporter) - { - PreferredAggregationTemporality = temporality, - }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{temporality}"); var counterLong = meter.CreateCounter("mycounterCapTest"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) - .AddReader(metricReader) + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = temporality, + }) .Build(); // Make one Add with no tags. @@ -492,17 +480,17 @@ int MetricPointCount() counterLong.Add(10, new KeyValuePair("key", "value" + i)); } - metricReader.Collect(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Equal(MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault, MetricPointCount()); - metricItems.Clear(); + exportedItems.Clear(); counterLong.Add(10); for (int i = 0; i < MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault + 1; i++) { counterLong.Add(10, new KeyValuePair("key", "value" + i)); } - metricReader.Collect(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Equal(MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault, MetricPointCount()); counterLong.Add(10); @@ -515,27 +503,24 @@ int MetricPointCount() counterLong.Add(10, new KeyValuePair("key", "valueA")); counterLong.Add(10, new KeyValuePair("key", "valueB")); counterLong.Add(10, new KeyValuePair("key", "valueC")); - metricItems.Clear(); - metricReader.Collect(); + exportedItems.Clear(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); Assert.Equal(MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault, MetricPointCount()); } [Fact] public void MultithreadedLongCounterTest() { - var metricItems = new List(); - var metricExporter = new InMemoryExporter(metricItems); - - var metricReader = new BaseExportingMetricReader(metricExporter) - { - PreferredAggregationTemporality = AggregationTemporality.Cumulative, - }; + var exportedItems = new List(); using var meter = new Meter(Utils.GetCurrentMethodName()); var counterLong = meter.CreateCounter("mycounter"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) - .AddReader(metricReader) + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = AggregationTemporality.Cumulative, + }) .Build(); // setup args to threads. @@ -574,9 +559,9 @@ public void MultithreadedLongCounterTest() var timeTakenInMilliseconds = sw.ElapsedMilliseconds; this.output.WriteLine($"Took {timeTakenInMilliseconds} msecs. Total threads: {numberOfThreads}, each thread doing {numberOfMetricUpdateByEachThread} recordings."); - metricReader.Collect(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); - var sumReceived = GetLongSum(metricItems); + var sumReceived = GetLongSum(exportedItems); var expectedSum = deltaLongValueUpdatedByEachCall * numberOfMetricUpdateByEachThread * numberOfThreads; Assert.Equal(expectedSum, sumReceived); } @@ -584,19 +569,16 @@ public void MultithreadedLongCounterTest() [Fact] public void MultithreadedDoubleCounterTest() { - var metricItems = new List(); - var metricExporter = new InMemoryExporter(metricItems); - - var metricReader = new BaseExportingMetricReader(metricExporter) - { - PreferredAggregationTemporality = AggregationTemporality.Cumulative, - }; + var exportedItems = new List(); using var meter = new Meter(Utils.GetCurrentMethodName()); var counterDouble = meter.CreateCounter("mycounter"); using var meterProvider = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) - .AddReader(metricReader) + .AddReader(new BaseExportingMetricReader(new InMemoryExporter(exportedItems)) + { + Temporality = AggregationTemporality.Cumulative, + }) .Build(); // setup args to threads. @@ -635,9 +617,9 @@ public void MultithreadedDoubleCounterTest() var timeTakenInMilliseconds = sw.ElapsedMilliseconds; this.output.WriteLine($"Took {timeTakenInMilliseconds} msecs. Total threads: {numberOfThreads}, each thread doing {numberOfMetricUpdateByEachThread} recordings."); - metricReader.Collect(); + meterProvider.ForceFlush(MaxTimeToAllowForFlush); - var sumReceived = GetDoubleSum(metricItems); + var sumReceived = GetDoubleSum(exportedItems); var expectedSum = deltaDoubleValueUpdatedByEachCall * numberOfMetricUpdateByEachThread * numberOfThreads; var difference = Math.Abs(sumReceived - expectedSum); Assert.True(difference <= 0.0001); diff --git a/test/OpenTelemetry.Tests/Metrics/MultipleReadersTests.cs b/test/OpenTelemetry.Tests/Metrics/MultipleReadersTests.cs index ec6f250af31..f0e1b7f6593 100644 --- a/test/OpenTelemetry.Tests/Metrics/MultipleReadersTests.cs +++ b/test/OpenTelemetry.Tests/Metrics/MultipleReadersTests.cs @@ -32,18 +32,18 @@ public class MultipleReadersTests [InlineData(AggregationTemporality.Cumulative, true)] public void SdkSupportsMultipleReaders(AggregationTemporality aggregationTemporality, bool hasViews) { - var exporterdMetricItems1 = new List(); - using var deltaMetricExporter1 = new InMemoryExporter(exporterdMetricItems1); - using var deltaMetricReader1 = new BaseExportingMetricReader(deltaMetricExporter1) + var exportedItems1 = new List(); + using var deltaExporter1 = new InMemoryExporter(exportedItems1); + using var deltaReader1 = new BaseExportingMetricReader(deltaExporter1) { - PreferredAggregationTemporality = AggregationTemporality.Delta, + Temporality = AggregationTemporality.Delta, }; - var exporterdMetricItems2 = new List(); - using var deltaMetricExporter2 = new InMemoryExporter(exporterdMetricItems2); - using var deltaMetricReader2 = new BaseExportingMetricReader(deltaMetricExporter2) + var exportedItems2 = new List(); + using var deltaExporter2 = new InMemoryExporter(exportedItems2); + using var deltaReader2 = new BaseExportingMetricReader(deltaExporter2) { - PreferredAggregationTemporality = aggregationTemporality, + Temporality = aggregationTemporality, }; using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{aggregationTemporality}.{hasViews}"); @@ -56,8 +56,8 @@ public void SdkSupportsMultipleReaders(AggregationTemporality aggregationTempora var meterProviderBuilder = Sdk.CreateMeterProviderBuilder() .AddMeter(meter.Name) - .AddReader(deltaMetricReader1) - .AddReader(deltaMetricReader2); + .AddReader(deltaReader1) + .AddReader(deltaReader2); if (hasViews) { @@ -70,41 +70,41 @@ public void SdkSupportsMultipleReaders(AggregationTemporality aggregationTempora meterProvider.ForceFlush(); - Assert.Equal(2, exporterdMetricItems1.Count); - Assert.Equal(2, exporterdMetricItems2.Count); + Assert.Equal(2, exportedItems1.Count); + Assert.Equal(2, exportedItems2.Count); // Check value exported for Counter - this.AssertLongSumValueForMetric(exporterdMetricItems1[0], 10); - this.AssertLongSumValueForMetric(exporterdMetricItems2[0], 10); + this.AssertLongSumValueForMetric(exportedItems1[0], 10); + this.AssertLongSumValueForMetric(exportedItems2[0], 10); // Check value exported for Gauge - this.AssertLongSumValueForMetric(exporterdMetricItems1[1], 100); - this.AssertLongSumValueForMetric(exporterdMetricItems2[1], 200); + this.AssertLongSumValueForMetric(exportedItems1[1], 100); + this.AssertLongSumValueForMetric(exportedItems2[1], 200); - exporterdMetricItems1.Clear(); - exporterdMetricItems2.Clear(); + exportedItems1.Clear(); + exportedItems2.Clear(); counter.Add(15, new KeyValuePair("key", "value")); meterProvider.ForceFlush(); - Assert.Equal(2, exporterdMetricItems1.Count); - Assert.Equal(2, exporterdMetricItems2.Count); + Assert.Equal(2, exportedItems1.Count); + Assert.Equal(2, exportedItems2.Count); // Check value exported for Counter - this.AssertLongSumValueForMetric(exporterdMetricItems1[0], 15); + this.AssertLongSumValueForMetric(exportedItems1[0], 15); if (aggregationTemporality == AggregationTemporality.Delta) { - this.AssertLongSumValueForMetric(exporterdMetricItems2[0], 15); + this.AssertLongSumValueForMetric(exportedItems2[0], 15); } else { - this.AssertLongSumValueForMetric(exporterdMetricItems2[0], 25); + this.AssertLongSumValueForMetric(exportedItems2[0], 25); } // Check value exported for Gauge - this.AssertLongSumValueForMetric(exporterdMetricItems1[1], 300); - this.AssertLongSumValueForMetric(exporterdMetricItems2[1], 400); + this.AssertLongSumValueForMetric(exportedItems1[1], 300); + this.AssertLongSumValueForMetric(exportedItems2[1], 400); } private void AssertLongSumValueForMetric(Metric metric, long value) From bc738aa970a59dad48e2c102bc2cf84a30721ccb Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 23 Nov 2021 12:56:15 -0800 Subject: [PATCH 2/3] nit --- test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs b/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs index 6e6a03577a9..ad9d9abe40d 100644 --- a/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs +++ b/test/OpenTelemetry.Tests/Metrics/MetricAPITest.cs @@ -333,7 +333,6 @@ public void ObservableCounterAggregationTest(bool exportDelta) { var exportedItems = new List(); - using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}"); int i = 1; var counterLong = meter.CreateObservableCounter( From 924d7b4ca9da94c46884461fc2d4ef0bd355da17 Mon Sep 17 00:00:00 2001 From: Reiley Yang Date: Tue, 23 Nov 2021 13:18:12 -0800 Subject: [PATCH 3/3] changelog and error message --- src/OpenTelemetry/CHANGELOG.md | 3 +++ src/OpenTelemetry/Metrics/MetricReader.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index 77e87c2a07e..a436db3e29e 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -14,6 +14,9 @@ aggregation is not implemented yet. ([#2660](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2660)) +* Refactored temporality setting to align with the latest spec. + ([#2666](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2666)) + ## 1.2.0-beta2 Released 2021-Nov-19 diff --git a/src/OpenTelemetry/Metrics/MetricReader.cs b/src/OpenTelemetry/Metrics/MetricReader.cs index bf7858b5d1e..61947e83249 100644 --- a/src/OpenTelemetry/Metrics/MetricReader.cs +++ b/src/OpenTelemetry/Metrics/MetricReader.cs @@ -53,7 +53,7 @@ public AggregationTemporality Temporality { if (this.temporality != AggregationTemporalityUnspecified) { - throw new NotSupportedException(); // TODO: add details + throw new NotSupportedException($"The temporality cannot be modified (the current value is {this.temporality})."); } this.temporality = value;