Skip to content

Commit ca29142

Browse files
authored
Add support for multiple readers (#2596)
1 parent 03313e7 commit ca29142

File tree

12 files changed

+719
-243
lines changed

12 files changed

+719
-243
lines changed

src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ static OpenTelemetry.Metrics.MetricTypeExtensions.IsGauge(this OpenTelemetry.Met
121121
static OpenTelemetry.Metrics.MetricTypeExtensions.IsHistogram(this OpenTelemetry.Metrics.MetricType self) -> bool
122122
static OpenTelemetry.Metrics.MetricTypeExtensions.IsLong(this OpenTelemetry.Metrics.MetricType self) -> bool
123123
static OpenTelemetry.Metrics.MetricTypeExtensions.IsSum(this OpenTelemetry.Metrics.MetricType self) -> bool
124-
static OpenTelemetry.ProviderExtensions.GetMetricCollect(this OpenTelemetry.BaseProvider baseProvider) -> System.Func<OpenTelemetry.Batch<OpenTelemetry.Metrics.Metric>>
125124
static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder
126125
static readonly OpenTelemetry.Metrics.MetricStreamConfiguration.Drop -> OpenTelemetry.Metrics.MetricStreamConfiguration
127126
virtual OpenTelemetry.BaseExporter<T>.OnForceFlush(int timeoutMilliseconds) -> bool

src/OpenTelemetry/.publicApi/netstandard2.0/PublicAPI.Unshipped.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ static OpenTelemetry.Metrics.MetricTypeExtensions.IsGauge(this OpenTelemetry.Met
121121
static OpenTelemetry.Metrics.MetricTypeExtensions.IsHistogram(this OpenTelemetry.Metrics.MetricType self) -> bool
122122
static OpenTelemetry.Metrics.MetricTypeExtensions.IsLong(this OpenTelemetry.Metrics.MetricType self) -> bool
123123
static OpenTelemetry.Metrics.MetricTypeExtensions.IsSum(this OpenTelemetry.Metrics.MetricType self) -> bool
124-
static OpenTelemetry.ProviderExtensions.GetMetricCollect(this OpenTelemetry.BaseProvider baseProvider) -> System.Func<OpenTelemetry.Batch<OpenTelemetry.Metrics.Metric>>
125124
static OpenTelemetry.Sdk.CreateMeterProviderBuilder() -> OpenTelemetry.Metrics.MeterProviderBuilder
126125
static readonly OpenTelemetry.Metrics.MetricStreamConfiguration.Drop -> OpenTelemetry.Metrics.MetricStreamConfiguration
127126
virtual OpenTelemetry.BaseExporter<T>.OnForceFlush(int timeoutMilliseconds) -> bool

src/OpenTelemetry/CHANGELOG.md

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,33 @@
2626
([#2542](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2542))
2727

2828
* Added wildcard support for AddMeter.
29-
([#2459](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2459))
29+
([#2459](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2459))
30+
31+
* Add support for multiple Metric readers
32+
([#2596](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2596))
3033

3134
## 1.2.0-beta1
3235

3336
Released 2021-Oct-08
3437

35-
* Exception from Observable instrument callbacks does not
36-
result in entire metrics being lost.
38+
* Exception from Observable instrument callbacks does not result in entire
39+
metrics being lost.
3740

38-
* SDK is allocation-free on recording of measurements with
39-
upto 8 tags.
41+
* SDK is allocation-free on recording of measurements with upto 8 tags.
4042

4143
* TracerProviderBuilder.AddLegacySource now supports wildcard activity names.
4244
([#2183](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2183))
4345

44-
* Instrument and View names are validated
45-
[according with the spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument).
46+
* Instrument and View names are validated [according with the
47+
spec](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument).
4648
([#2470](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2470))
4749

4850
## 1.2.0-alpha4
4951

5052
Released 2021-Sep-23
5153

52-
* `BatchExportProcessor.OnShutdown` will now log the count of dropped telemetry items.
54+
* `BatchExportProcessor.OnShutdown` will now log the count of dropped telemetry
55+
items.
5356
([#2331](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2331))
5457
* Changed `CompositeProcessor<T>.OnForceFlush` to meet with the spec
5558
requirement. Now the SDK will invoke `ForceFlush` on all registered
@@ -60,36 +63,39 @@ Released 2021-Sep-23
6063

6164
Released 2021-Sep-13
6265

63-
* Metrics perf improvements, bug fixes.
64-
Replace MetricProcessor with MetricReader.
66+
* Metrics perf improvements, bug fixes. Replace MetricProcessor with
67+
MetricReader.
6568
([#2306](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2306))
6669

67-
* Add `BatchExportActivityProcessorOptions` which supports field value overriding
68-
using `OTEL_BSP_SCHEDULE_DELAY`, `OTEL_BSP_EXPORT_TIMEOUT`,
69-
`OTEL_BSP_MAX_QUEUE_SIZE`, `OTEL_BSP_MAX_EXPORT_BATCH_SIZE`
70-
envionmental variables as defined in the
70+
* Add `BatchExportActivityProcessorOptions` which supports field value
71+
overriding using `OTEL_BSP_SCHEDULE_DELAY`, `OTEL_BSP_EXPORT_TIMEOUT`,
72+
`OTEL_BSP_MAX_QUEUE_SIZE`, `OTEL_BSP_MAX_EXPORT_BATCH_SIZE` envionmental
73+
variables as defined in the
7174
[specification](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.5.0/specification/sdk-environment-variables.md#batch-span-processor).
7275
([#2219](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2219))
7376

7477
## 1.2.0-alpha2
7578

7679
Released 2021-Aug-24
7780

78-
* More Metrics features. All instrument types, push/pull
79-
exporters, Delta/Cumulative temporality supported.
81+
* More Metrics features. All instrument types, push/pull exporters,
82+
Delta/Cumulative temporality supported.
8083

81-
* `ResourceBuilder.CreateDefault` has detectors for
82-
`OTEL_RESOURCE_ATTRIBUTES`, `OTEL_SERVICE_NAME` environment variables
83-
so that explicit `AddEnvironmentVariableDetector` call is not needed. ([#2247](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2247))
84+
* `ResourceBuilder.CreateDefault` has detectors for `OTEL_RESOURCE_ATTRIBUTES`,
85+
`OTEL_SERVICE_NAME` environment variables so that explicit
86+
`AddEnvironmentVariableDetector` call is not needed.
87+
([#2247](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2247))
8488

8589
* `ResourceBuilder.AddEnvironmentVariableDetector` handles `OTEL_SERVICE_NAME`
86-
environmental variable. ([#2209](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2209))
90+
environmental variable.
91+
([#2209](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2209))
8792

88-
* Removes upper constraint for Microsoft.Extensions.Logging
89-
dependencies. ([#2179](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2179))
93+
* Removes upper constraint for Microsoft.Extensions.Logging dependencies.
94+
([#2179](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2179))
9095

91-
* OpenTelemetryLogger modified to not throw, when the
92-
formatter supplied in ILogger.Log call is null. ([#2200](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2200))
96+
* OpenTelemetryLogger modified to not throw, when the formatter supplied in
97+
ILogger.Log call is null.
98+
([#2200](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2200))
9399

94100
## 1.2.0-alpha1
95101

@@ -100,7 +106,8 @@ Released 2021-Jul-23
100106
([#2174](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2174))
101107

102108
* Removes .NET Framework 4.5.2, .NET 4.6 support. The minimum .NET Framework
103-
version supported is .NET 4.6.1. ([#2138](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2138))
109+
version supported is .NET 4.6.1.
110+
([#2138](https://github.com/open-telemetry/opentelemetry-dotnet/issues/2138))
104111

105112
## 1.1.0
106113

@@ -137,8 +144,8 @@ Released 2021-May-11
137144
Released 2021-Apr-23
138145

139146
* Use `AssemblyFileVersionAttribute` instead of `FileVersionInfo.GetVersionInfo`
140-
to get the SDK version attribute to ensure that it works when the assembly
141-
is not loaded directly from a file on disk
147+
to get the SDK version attribute to ensure that it works when the assembly is
148+
not loaded directly from a file on disk
142149
([#1908](https://github.com/open-telemetry/opentelemetry-dotnet/issues/1908))
143150

144151
## 1.1.0-beta1

src/OpenTelemetry/Metrics/CompositeMetricReader.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@
2222

2323
namespace OpenTelemetry.Metrics
2424
{
25-
internal sealed class CompositeMetricReader : MetricReader
25+
/// <summary>
26+
/// CompositeMetricReader that does not deal with adding metrics and recording measurements.
27+
/// </summary>
28+
internal sealed partial class CompositeMetricReader : MetricReader
2629
{
2730
private readonly DoublyLinkedListNode head;
2831
private DoublyLinkedListNode tail;
2932
private bool disposed;
33+
private int count;
3034

3135
public CompositeMetricReader(IEnumerable<MetricReader> readers)
3236
{
@@ -40,6 +44,7 @@ public CompositeMetricReader(IEnumerable<MetricReader> readers)
4044

4145
this.head = new DoublyLinkedListNode(iter.Current);
4246
this.tail = this.head;
47+
this.count++;
4348

4449
while (iter.MoveNext())
4550
{
@@ -57,6 +62,7 @@ public CompositeMetricReader AddReader(MetricReader reader)
5762
};
5863
this.tail.Next = node;
5964
this.tail = node;
65+
this.count++;
6066

6167
return this;
6268
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// <copyright file="CompositeMetricReaderExt.cs" company="OpenTelemetry Authors">
2+
// Copyright The OpenTelemetry Authors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// </copyright>
16+
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Diagnostics;
20+
using System.Diagnostics.Metrics;
21+
22+
namespace OpenTelemetry.Metrics
23+
{
24+
/// <summary>
25+
/// CompositeMetricReader that deals with adding metrics and recording measurements.
26+
/// </summary>
27+
internal sealed partial class CompositeMetricReader
28+
{
29+
internal List<Metric> AddMetricsWithNoViews(Instrument instrument)
30+
{
31+
var metrics = new List<Metric>(this.count);
32+
for (var cur = this.head; cur != null; cur = cur.Next)
33+
{
34+
var metric = cur.Value.AddMetricWithNoViews(instrument);
35+
metrics.Add(metric);
36+
}
37+
38+
return metrics;
39+
}
40+
41+
internal void RecordSingleStreamLongMeasurements(List<Metric> metrics, long value, ReadOnlySpan<KeyValuePair<string, object>> tags)
42+
{
43+
Debug.Assert(metrics.Count == this.count, "The count of metrics to be updated for a CompositeReader must match the number of individual readers.");
44+
45+
int index = 0;
46+
for (var cur = this.head; cur != null; cur = cur.Next)
47+
{
48+
if (metrics[index] != null)
49+
{
50+
cur.Value.RecordSingleStreamLongMeasurement(metrics[index], value, tags);
51+
}
52+
53+
index++;
54+
}
55+
}
56+
57+
internal void RecordSingleStreamDoubleMeasurements(List<Metric> metrics, double value, ReadOnlySpan<KeyValuePair<string, object>> tags)
58+
{
59+
Debug.Assert(metrics.Count == this.count, "The count of metrics to be updated for a CompositeReader must match the number of individual readers.");
60+
61+
int index = 0;
62+
for (var cur = this.head; cur != null; cur = cur.Next)
63+
{
64+
if (metrics[index] != null)
65+
{
66+
cur.Value.RecordSingleStreamDoubleMeasurement(metrics[index], value, tags);
67+
}
68+
69+
index++;
70+
}
71+
}
72+
73+
internal List<List<Metric>> AddMetricsSuperListWithViews(Instrument instrument, List<MetricStreamConfiguration> metricStreamConfigs)
74+
{
75+
var metricsSuperList = new List<List<Metric>>(this.count);
76+
for (var cur = this.head; cur != null; cur = cur.Next)
77+
{
78+
var metrics = cur.Value.AddMetricsListWithViews(instrument, metricStreamConfigs);
79+
metricsSuperList.Add(metrics);
80+
}
81+
82+
return metricsSuperList;
83+
}
84+
85+
internal void RecordLongMeasurements(List<List<Metric>> metricsSuperList, long value, ReadOnlySpan<KeyValuePair<string, object>> tags)
86+
{
87+
Debug.Assert(metricsSuperList.Count == this.count, "The count of metrics to be updated for a CompositeReader must match the number of individual readers.");
88+
89+
int index = 0;
90+
for (var cur = this.head; cur != null; cur = cur.Next)
91+
{
92+
if (metricsSuperList[index].Count > 0)
93+
{
94+
cur.Value.RecordLongMeasurement(metricsSuperList[index], value, tags);
95+
}
96+
97+
index++;
98+
}
99+
}
100+
101+
internal void RecordDoubleMeasurements(List<List<Metric>> metricsSuperList, double value, ReadOnlySpan<KeyValuePair<string, object>> tags)
102+
{
103+
Debug.Assert(metricsSuperList.Count == this.count, "The count of metrics to be updated for a CompositeReader must match the number of individual readers.");
104+
105+
int index = 0;
106+
for (var cur = this.head; cur != null; cur = cur.Next)
107+
{
108+
if (metricsSuperList[index].Count > 0)
109+
{
110+
cur.Value.RecordDoubleMeasurement(metricsSuperList[index], value, tags);
111+
}
112+
113+
index++;
114+
}
115+
}
116+
117+
internal void CompleteSingleStreamMeasurements(List<Metric> metrics)
118+
{
119+
Debug.Assert(metrics.Count == this.count, "The count of metrics to be updated for a CompositeReader must match the number of individual readers.");
120+
121+
int index = 0;
122+
for (var cur = this.head; cur != null; cur = cur.Next)
123+
{
124+
if (metrics[index] != null)
125+
{
126+
cur.Value.CompleteSingleStreamMeasurement(metrics[index]);
127+
}
128+
129+
index++;
130+
}
131+
}
132+
133+
internal void CompleteMesaurements(List<List<Metric>> metricsSuperList)
134+
{
135+
Debug.Assert(metricsSuperList.Count == this.count, "The count of metrics to be updated for a CompositeReader must match the number of individual readers.");
136+
137+
int index = 0;
138+
for (var cur = this.head; cur != null; cur = cur.Next)
139+
{
140+
if (metricsSuperList[index].Count > 0)
141+
{
142+
cur.Value.CompleteMeasurement(metricsSuperList[index]);
143+
}
144+
145+
index++;
146+
}
147+
}
148+
}
149+
}

src/OpenTelemetry/Metrics/MeterProviderBuilderBase.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,6 @@ public override MeterProviderBuilder AddMeter(params string[] names)
7171

7272
internal MeterProviderBuilder AddReader(MetricReader reader)
7373
{
74-
if (this.MetricReaders.Count >= 1)
75-
{
76-
throw new InvalidOperationException("Only one Metricreader is allowed.");
77-
}
78-
7974
this.MetricReaders.Add(reader);
8075
return this;
8176
}

0 commit comments

Comments
 (0)