Skip to content

Commit ea2cfdc

Browse files
hannahhaeringmartincostellorajkumar-rangarajKielek
authored
Fix and tests for multiple metric readers (#6458)
Co-authored-by: Martin Costello <[email protected]> Co-authored-by: Rajkumar Rangaraj <[email protected]> Co-authored-by: Piotr Kiełkowicz <[email protected]>
1 parent 5852193 commit ea2cfdc

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

src/OpenTelemetry/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Notes](../../RELEASENOTES.md).
66

77
## Unreleased
88

9+
* Added a verification to ensure that a `MetricReader` can only be registered
10+
to a single `MeterProvider`, as required by the OpenTelemetry specification.
11+
([#6458](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6458))
12+
913
* Added `FormatMessage` configuration option to self-diagnostics feature. When
1014
set to `true` (default is false), log messages will be formatted by replacing
1115
placeholders with actual parameter values for improved readability.

src/OpenTelemetry/Metrics/Reader/MetricReader.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ public void Dispose()
218218

219219
internal virtual void SetParentProvider(BaseProvider parentProvider)
220220
{
221+
if (this.parentProvider != null && this.parentProvider != parentProvider)
222+
{
223+
throw new NotSupportedException("A MetricReader must not be registered with multiple MeterProviders.");
224+
}
225+
221226
this.parentProvider = parentProvider;
222227
}
223228

test/OpenTelemetry.Tests/Metrics/MultipleReadersTests.cs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,104 @@
33

44
using System.Diagnostics.Metrics;
55
using Microsoft.Extensions.DependencyInjection;
6+
using OpenTelemetry.Exporter;
67
using OpenTelemetry.Tests;
78
using Xunit;
89

910
namespace OpenTelemetry.Metrics.Tests;
1011

1112
public class MultipleReadersTests
1213
{
14+
[Fact]
15+
public void ReaderCannotBeRegisteredMoreThanOnce()
16+
{
17+
var exportedItems = new List<Metric>();
18+
using var exporter = new InMemoryExporter<Metric>(exportedItems);
19+
using var reader = new BaseExportingMetricReader(exporter);
20+
21+
using var meter = new Meter($"{Utils.GetCurrentMethodName()}");
22+
23+
var meterProviderBuilder1 = Sdk.CreateMeterProviderBuilder()
24+
.AddMeter(meter.Name)
25+
.AddReader(reader);
26+
var meterProviderBuilder2 = Sdk.CreateMeterProviderBuilder()
27+
.AddMeter(meter.Name)
28+
.AddReader(reader);
29+
30+
using var meterProvider1 = meterProviderBuilder1.Build();
31+
Assert.Throws<NotSupportedException>(() => meterProviderBuilder2.Build());
32+
}
33+
34+
[Fact]
35+
public void MultipleReadersOneCollectsIndependently()
36+
{
37+
var exportedItems1 = new List<Metric>();
38+
var exportedItems2 = new List<Metric>();
39+
40+
using var exporter1 = new InMemoryExporter<Metric>(exportedItems1);
41+
using var exporter2 = new InMemoryExporter<Metric>(exportedItems2);
42+
using var reader1 = new BaseExportingMetricReader(exporter1);
43+
using var reader2 = new BaseExportingMetricReader(exporter2);
44+
45+
using var meter = new Meter($"{Utils.GetCurrentMethodName()}");
46+
var counter = meter.CreateCounter<long>("counter");
47+
48+
var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
49+
.AddMeter(meter.Name)
50+
.AddReader(reader1)
51+
.AddReader(reader2);
52+
53+
using var meterProvider = meterProviderBuilder.Build();
54+
55+
counter.Add(1);
56+
57+
reader1.Collect();
58+
59+
Assert.Single(exportedItems1);
60+
Assert.Empty(exportedItems2);
61+
}
62+
63+
[Fact]
64+
public void MultipleReadersDifferentTemporality()
65+
{
66+
var exportedItems1 = new List<Metric>();
67+
var exportedItems2 = new List<Metric>();
68+
69+
using var exporter1 = new InMemoryExporter<Metric>(exportedItems1);
70+
using var exporter2 = new InMemoryExporter<Metric>(exportedItems2);
71+
using var reader1 = new BaseExportingMetricReader(exporter1);
72+
using var reader2 = new BaseExportingMetricReader(exporter2);
73+
reader1.TemporalityPreference = MetricReaderTemporalityPreference.Delta;
74+
reader2.TemporalityPreference = MetricReaderTemporalityPreference.Cumulative;
75+
76+
using var meter = new Meter($"{Utils.GetCurrentMethodName()}");
77+
var counter = meter.CreateCounter<long>("counter");
78+
79+
var meterProviderBuilder = Sdk.CreateMeterProviderBuilder()
80+
.AddMeter(meter.Name)
81+
.AddReader(reader1)
82+
.AddReader(reader2);
83+
84+
using var meterProvider = meterProviderBuilder.Build();
85+
86+
counter.Add(1);
87+
88+
reader1.Collect();
89+
reader2.Collect();
90+
91+
AssertLongSumValueForMetric(exportedItems1[0], 1);
92+
AssertLongSumValueForMetric(exportedItems2[0], 1);
93+
94+
exportedItems1.Clear();
95+
96+
counter.Add(10);
97+
reader1.Collect();
98+
reader2.Collect();
99+
100+
AssertLongSumValueForMetric(exportedItems1[0], 10);
101+
AssertLongSumValueForMetric(exportedItems2[0], 11);
102+
}
103+
13104
[Theory]
14105
[InlineData(MetricReaderTemporalityPreference.Delta, false)]
15106
[InlineData(MetricReaderTemporalityPreference.Delta, true)]

0 commit comments

Comments
 (0)