diff --git a/test/OpenTelemetry.Tests/Metrics/MetricExporterTests.cs b/test/OpenTelemetry.Tests/Metrics/MetricExporterTests.cs index 6416551ed9b..230b53486dc 100644 --- a/test/OpenTelemetry.Tests/Metrics/MetricExporterTests.cs +++ b/test/OpenTelemetry.Tests/Metrics/MetricExporterTests.cs @@ -15,6 +15,10 @@ // using System; +using System.Collections.Generic; +using System.Diagnostics.Metrics; +using OpenTelemetry.Exporter; +using OpenTelemetry.Tests; using Xunit; namespace OpenTelemetry.Metrics.Tests @@ -65,6 +69,55 @@ public void FlushMetricExporterTest(ExportModes mode) } } + [Fact] + public void ExporterShouldNotUpdateMetricPoint() + { + var exportedItems = new List(); + var updateMetricPointExporter = new UpdateMetricPointExporter(exportedItems); + using var meter = new Meter(Utils.GetCurrentMethodName()); + using var meterProvider = Sdk.CreateMeterProviderBuilder() + .AddMeter(meter.Name) + .AddReader(new BaseExportingMetricReader(updateMetricPointExporter) { Temporality = AggregationTemporality.Delta }) + .Build(); + + var counter = meter.CreateCounter("counter"); + counter.Add(100, new KeyValuePair("key", "value")); + + meterProvider.ForceFlush(); + + Assert.Single(exportedItems); + var metricPoint = this.GetFirstMetricPointFromMetric(exportedItems[0]); + Assert.Equal(100, metricPoint.GetSumLong()); + foreach (var tag in metricPoint.Tags) + { + Assert.Equal("key", tag.Key); + Assert.Equal("value", tag.Value); + } + + exportedItems.Clear(); + + counter.Add(150, new KeyValuePair("key", "value")); + + meterProvider.ForceFlush(); + + Assert.Single(exportedItems); + metricPoint = this.GetFirstMetricPointFromMetric(exportedItems[0]); + Assert.Equal(150, metricPoint.GetSumLong()); + foreach (var tag in metricPoint.Tags) + { + Assert.Equal("key", tag.Key); + Assert.Equal("value", tag.Value); + } + } + + private ref MetricPoint GetFirstMetricPointFromMetric(Metric metric) + { + var metricPoints = metric.GetMetricPoints(); + var metricPointsEnumerator = metricPoints.GetEnumerator(); + Assert.True(metricPointsEnumerator.MoveNext()); // One MetricPoint is emitted for the Metric + return ref metricPointsEnumerator.Current; + } + [ExportModes(ExportModes.Push)] private class PushOnlyMetricExporter : BaseExporter { @@ -99,5 +152,35 @@ public override ExportResult Export(in Batch batch) return ExportResult.Success; } } + + private class UpdateMetricPointExporter : BaseExporter + { + private static int invocationCount = 1; + private readonly List exportedItems; + + public UpdateMetricPointExporter(List exportedItems) + { + this.exportedItems = exportedItems; + } + + public override ExportResult Export(in Batch batch) + { + foreach (var metric in batch) + { + if (invocationCount > 1) + { + foreach (ref var metricPoint in metric.GetMetricPoints()) + { + metricPoint = default; + } + } + + this.exportedItems.Add(metric); + } + + invocationCount++; + return ExportResult.Success; + } + } } }