Skip to content

Commit b754b13

Browse files
authored
[sdk-metrics] ExemplarFilter updates to match latest specification (#5404)
1 parent 42ecd73 commit b754b13

File tree

15 files changed

+322
-228
lines changed

15 files changed

+322
-228
lines changed

Diff for: docs/metrics/customizing-the-sdk/README.md

+17-37
Original file line numberDiff line numberDiff line change
@@ -412,58 +412,38 @@ exemplars.
412412

413413
#### ExemplarFilter
414414

415-
`ExemplarFilter` determines which measurements are eligible to become an
416-
Exemplar. i.e. `ExemplarFilter` determines which measurements are offered to
417-
`ExemplarReservoir`, which makes the final decision about whether the offered
418-
measurement gets stored as an exemplar. They can be used to control the noise
419-
and overhead associated with Exemplar collection.
415+
`ExemplarFilter` determines which measurements are offered to the configured
416+
`ExemplarReservoir`, which makes the final decision about whether or not the
417+
offered measurement gets recorded as an `Exemplar`. Generally `ExemplarFilter`
418+
is a mechanism to control the overhead associated with `Exemplar` offering.
420419

421-
OpenTelemetry SDK comes with the following Filters:
420+
OpenTelemetry SDK comes with the following `ExemplarFilters` (defined on
421+
`ExemplarFilterType`):
422422

423-
* `AlwaysOnExemplarFilter` - makes all measurements eligible for being an Exemplar.
424-
* `AlwaysOffExemplarFilter` - makes no measurements eligible for being an
425-
Exemplar. Using this is as good as turning off Exemplar feature, and is the current
423+
* `AlwaysOff`: Makes no measurements eligible for becoming an `Exemplar`. Using
424+
this is as good as turning off the `Exemplar` feature and is the current
426425
default.
427-
* `TraceBasedExemplarFilter` - makes those measurements eligible for being an
428-
Exemplar, which are recorded in the context of a sampled parent `Activity`
429-
(span).
426+
* `AlwaysOn`: Makes all measurements eligible for becoming an `Exemplar`.
427+
* `TraceBased`: Makes those measurements eligible for becoming an `Exemplar`
428+
which are recorded in the context of a sampled `Activity` (span).
430429

431-
`SetExemplarFilter` method on `MeterProviderBuilder` can be used to set the
432-
desired `ExemplarFilter`.
433-
434-
The snippet below shows how to set `ExemplarFilter`.
430+
The `SetExemplarFilter` extension method on `MeterProviderBuilder` can be used
431+
to set the desired `ExemplarFilterType` and enable `Exemplar` collection:
435432

436433
```csharp
437434
using OpenTelemetry;
438435
using OpenTelemetry.Metrics;
439436

440437
using var meterProvider = Sdk.CreateMeterProviderBuilder()
441438
// rest of config not shown
442-
.SetExemplarFilter(new TraceBasedExemplarFilter())
439+
.SetExemplarFilter(ExemplarFilterType.TraceBased)
443440
.Build();
444441
```
445442

446-
> [!NOTE]
447-
> As of today, there is no separate toggle for enable/disable Exemplar feature.
448-
Exemplars can be disabled by setting filter as `AlwaysOffExemplarFilter`, which
449-
is also the default (i.e Exemplar feature is disabled by default). Users can
450-
enable the feature by setting filter to anything other than
451-
`AlwaysOffExemplarFilter`. For example: `.SetExemplarFilter(new TraceBasedExemplarFilter())`.
452-
453-
If the built-in `ExemplarFilter`s are not meeting the needs, one may author
454-
custom `ExemplarFilter` as shown
455-
[here](../extending-the-sdk/README.md#exemplarfilter). A custom filter, which
456-
eliminates all un-interesting measurements from becoming Exemplar is a
457-
recommended way to control performance overhead associated with collecting
458-
Exemplars. See
459-
[benchmark](../../../test/Benchmarks/Metrics/ExemplarBenchmarks.cs) to see how
460-
much impact can `ExemplarFilter` have on performance.
461-
462443
#### ExemplarReservoir
463444

464-
`ExemplarReservoir` receives the measurements sampled in by the `ExemplarFilter`
465-
and is responsible for storing Exemplars. `ExemplarReservoir` ultimately decides
466-
which measurements get stored as exemplars. The following are the default
445+
`ExemplarReservoir` receives the measurements sampled by the `ExemplarFilter`
446+
and is responsible for recording `Exemplar`s. The following are the default
467447
reservoirs:
468448

469449
* `AlignedHistogramBucketExemplarReservoir` is the default reservoir used for
@@ -479,7 +459,7 @@ size (currently defaulting to 1) determines the maximum number of exemplars
479459
stored.
480460

481461
> [!NOTE]
482-
> Currently there is no ability to change or configure Reservoir.
462+
> Currently there is no ability to change or configure `ExemplarReservoir`.
483463
484464
### Instrumentation
485465

Diff for: docs/metrics/extending-the-sdk/README.md

+1-38
Original file line numberDiff line numberDiff line change
@@ -74,44 +74,7 @@ Not supported.
7474

7575
## ExemplarFilter
7676

77-
OpenTelemetry .NET SDK has provided the following built-in `ExemplarFilter`s:
78-
79-
* [AlwaysOnExemplarFilter](../../../src/OpenTelemetry/Metrics/Exemplar/AlwaysOnExemplarFilter.cs)
80-
* [AlwaysOffExemplarFilter](../../../src/OpenTelemetry/Metrics/Exemplar/AlwaysOffExemplarFilter.cs)
81-
* [TraceBasedExemplarFilter](../../../src/OpenTelemetry/Metrics/Exemplar/TraceBasedExemplarFilter.cs)
82-
83-
Custom exemplar filters can be implemented to achieve filtering based on other criterion:
84-
85-
* `ExemplarFilter` should derive from `OpenTelemetry.ExemplarFilter` (which
86-
belongs to the [OpenTelemetry](../../../src/OpenTelemetry/README.md) package)
87-
and implement the `ShouldSample` method.
88-
89-
One example is a filter, which filters all measurements of value lower
90-
than given threshold is given below. Such a filter prevents any measurements
91-
below the given threshold from ever becoming a `Exemplar`. Such filters could
92-
also incorporate the `TraceBasedExemplarFilter` condition as well, as storing
93-
exemplars for non-sampled traces may be undesired.
94-
95-
```csharp
96-
public sealed class HighValueFilter : ExemplarFilter
97-
{
98-
private readonly double maxValue;
99-
100-
public HighValueFilter(double maxValue)
101-
{
102-
this.maxValue = maxValue;
103-
}
104-
public override bool ShouldSample(long value, ReadOnlySpan<KeyValuePair<string, object>> tags)
105-
{
106-
return Activity.Current?.Recorded && value > this.maxValue;
107-
}
108-
109-
public override bool ShouldSample(double value, ReadOnlySpan<KeyValuePair<string, object>> tags)
110-
{
111-
return Activity.Current?.Recorded && value > this.maxValue;
112-
}
113-
}
114-
```
77+
Not supported.
11578

11679
## ExemplarReservoir
11780

Diff for: examples/AspNetCore/Program.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
builder
8686
.AddMeter(Instrumentation.MeterName)
8787
#if EXPOSE_EXPERIMENTAL_FEATURES
88-
.SetExemplarFilter(new TraceBasedExemplarFilter())
88+
.SetExemplarFilter(ExemplarFilterType.TraceBased)
8989
#endif
9090
.AddRuntimeInstrumentation()
9191
.AddHttpClientInstrumentation()

Diff for: src/OpenTelemetry/.publicApi/Experimental/PublicAPI.Unshipped.txt

+5-17
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ OpenTelemetry.Logs.LogRecord.Severity.get -> OpenTelemetry.Logs.LogRecordSeverit
55
OpenTelemetry.Logs.LogRecord.Severity.set -> void
66
OpenTelemetry.Logs.LogRecord.SeverityText.get -> string?
77
OpenTelemetry.Logs.LogRecord.SeverityText.set -> void
8-
OpenTelemetry.Metrics.AlwaysOffExemplarFilter
9-
OpenTelemetry.Metrics.AlwaysOffExemplarFilter.AlwaysOffExemplarFilter() -> void
10-
OpenTelemetry.Metrics.AlwaysOnExemplarFilter
11-
OpenTelemetry.Metrics.AlwaysOnExemplarFilter.AlwaysOnExemplarFilter() -> void
128
OpenTelemetry.Metrics.Exemplar
139
OpenTelemetry.Metrics.Exemplar.DoubleValue.get -> double
1410
OpenTelemetry.Metrics.Exemplar.Exemplar() -> void
@@ -17,8 +13,10 @@ OpenTelemetry.Metrics.Exemplar.LongValue.get -> long
1713
OpenTelemetry.Metrics.Exemplar.SpanId.get -> System.Diagnostics.ActivitySpanId
1814
OpenTelemetry.Metrics.Exemplar.Timestamp.get -> System.DateTimeOffset
1915
OpenTelemetry.Metrics.Exemplar.TraceId.get -> System.Diagnostics.ActivityTraceId
20-
OpenTelemetry.Metrics.ExemplarFilter
21-
OpenTelemetry.Metrics.ExemplarFilter.ExemplarFilter() -> void
16+
OpenTelemetry.Metrics.ExemplarFilterType
17+
OpenTelemetry.Metrics.ExemplarFilterType.AlwaysOff = 0 -> OpenTelemetry.Metrics.ExemplarFilterType
18+
OpenTelemetry.Metrics.ExemplarFilterType.AlwaysOn = 1 -> OpenTelemetry.Metrics.ExemplarFilterType
19+
OpenTelemetry.Metrics.ExemplarFilterType.TraceBased = 2 -> OpenTelemetry.Metrics.ExemplarFilterType
2220
OpenTelemetry.Metrics.ExemplarMeasurement<T>
2321
OpenTelemetry.Metrics.ExemplarMeasurement<T>.ExemplarMeasurement() -> void
2422
OpenTelemetry.Metrics.ExemplarMeasurement<T>.Tags.get -> System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>>
@@ -33,8 +31,6 @@ OpenTelemetry.Metrics.ReadOnlyExemplarCollection.Enumerator.Enumerator() -> void
3331
OpenTelemetry.Metrics.ReadOnlyExemplarCollection.Enumerator.MoveNext() -> bool
3432
OpenTelemetry.Metrics.ReadOnlyExemplarCollection.GetEnumerator() -> OpenTelemetry.Metrics.ReadOnlyExemplarCollection.Enumerator
3533
OpenTelemetry.Metrics.ReadOnlyExemplarCollection.ReadOnlyExemplarCollection() -> void
36-
OpenTelemetry.Metrics.TraceBasedExemplarFilter
37-
OpenTelemetry.Metrics.TraceBasedExemplarFilter.TraceBasedExemplarFilter() -> void
3834
OpenTelemetry.ReadOnlyFilteredTagCollection
3935
OpenTelemetry.ReadOnlyFilteredTagCollection.Enumerator
4036
OpenTelemetry.ReadOnlyFilteredTagCollection.Enumerator.Current.get -> System.Collections.Generic.KeyValuePair<string!, object?>
@@ -51,19 +47,11 @@ static OpenTelemetry.Logs.LoggerProviderBuilderExtensions.SetResourceBuilder(thi
5147
static OpenTelemetry.Logs.LoggerProviderExtensions.AddProcessor(this OpenTelemetry.Logs.LoggerProvider! provider, OpenTelemetry.BaseProcessor<OpenTelemetry.Logs.LogRecord!>! processor) -> OpenTelemetry.Logs.LoggerProvider!
5248
static OpenTelemetry.Logs.LoggerProviderExtensions.ForceFlush(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool
5349
static OpenTelemetry.Logs.LoggerProviderExtensions.Shutdown(this OpenTelemetry.Logs.LoggerProvider! provider, int timeoutMilliseconds = -1) -> bool
54-
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetExemplarFilter(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, OpenTelemetry.Metrics.ExemplarFilter! exemplarFilter) -> OpenTelemetry.Metrics.MeterProviderBuilder!
50+
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetExemplarFilter(this OpenTelemetry.Metrics.MeterProviderBuilder! meterProviderBuilder, OpenTelemetry.Metrics.ExemplarFilterType exemplarFilter = OpenTelemetry.Metrics.ExemplarFilterType.TraceBased) -> OpenTelemetry.Metrics.MeterProviderBuilder!
5551
static OpenTelemetry.OpenTelemetryBuilderSdkExtensions.WithLogging(this OpenTelemetry.IOpenTelemetryBuilder! builder) -> OpenTelemetry.IOpenTelemetryBuilder!
5652
static OpenTelemetry.OpenTelemetryBuilderSdkExtensions.WithLogging(this OpenTelemetry.IOpenTelemetryBuilder! builder, System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>! configure) -> OpenTelemetry.IOpenTelemetryBuilder!
5753
static OpenTelemetry.OpenTelemetryBuilderSdkExtensions.WithLogging(this OpenTelemetry.IOpenTelemetryBuilder! builder, System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>? configureBuilder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configureOptions) -> OpenTelemetry.IOpenTelemetryBuilder!
5854
static OpenTelemetry.Sdk.CreateLoggerProviderBuilder() -> OpenTelemetry.Logs.LoggerProviderBuilder!
59-
abstract OpenTelemetry.Metrics.ExemplarFilter.ShouldSample(double value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
60-
abstract OpenTelemetry.Metrics.ExemplarFilter.ShouldSample(long value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
61-
override OpenTelemetry.Metrics.AlwaysOffExemplarFilter.ShouldSample(double value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
62-
override OpenTelemetry.Metrics.AlwaysOffExemplarFilter.ShouldSample(long value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
63-
override OpenTelemetry.Metrics.AlwaysOnExemplarFilter.ShouldSample(double value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
64-
override OpenTelemetry.Metrics.AlwaysOnExemplarFilter.ShouldSample(long value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
65-
override OpenTelemetry.Metrics.TraceBasedExemplarFilter.ShouldSample(double value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
66-
override OpenTelemetry.Metrics.TraceBasedExemplarFilter.ShouldSample(long value, System.ReadOnlySpan<System.Collections.Generic.KeyValuePair<string!, object?>> tags) -> bool
6755
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.UseOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder) -> Microsoft.Extensions.Logging.ILoggingBuilder!
6856
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.UseOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>! configure) -> Microsoft.Extensions.Logging.ILoggingBuilder!
6957
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.UseOpenTelemetry(this Microsoft.Extensions.Logging.ILoggingBuilder! builder, System.Action<OpenTelemetry.Logs.LoggerProviderBuilder!>? configureBuilder, System.Action<OpenTelemetry.Logs.OpenTelemetryLoggerOptions!>? configureOptions) -> Microsoft.Extensions.Logging.ILoggingBuilder!

Diff for: src/OpenTelemetry/CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@
5555
API.
5656
([#5396](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5396))
5757

58+
* **Experimental (pre-release builds only):** Removed the `ExemplarFilter`,
59+
`AlwaysOffExemplarFilter`, `AlwaysOnExemplarFilter`, and
60+
`TraceBasedExemplarFilter` APIs. The `MeterProviderBuilder.SetExemplarFilter`
61+
extension method now accepts an `ExemplarFilterType` enumeration (which
62+
contains definitions for the supported filter types `AlwaysOff`, `AlwaysOn`,
63+
and `TraceBased`) instead of an `ExemplarFilter` instance. This was done in
64+
response to changes made to the [OpenTelemetry Metrics SDK
65+
Specification](https://github.com/open-telemetry/opentelemetry-specification/pull/3820).
66+
([#5404](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5404))
67+
5868
## 1.7.0
5969

6070
Released 2023-Dec-08

Diff for: src/OpenTelemetry/Metrics/Builder/MeterProviderBuilderExtensions.cs

+35-17
Original file line numberDiff line numberDiff line change
@@ -319,36 +319,54 @@ public static MeterProvider Build(this MeterProviderBuilder meterProviderBuilder
319319

320320
#if EXPOSE_EXPERIMENTAL_FEATURES
321321
/// <summary>
322-
/// Sets the <see cref="ExemplarFilter"/> to be used for this provider.
323-
/// This is applied to all the metrics from this provider.
322+
/// Sets the <see cref="ExemplarFilterType"/> to be used for this provider
323+
/// which controls how measurements will be offered to exemplar reservoirs.
324+
/// Default provider configuration: <see
325+
/// cref="ExemplarFilterType.AlwaysOff"/>.
324326
/// </summary>
325-
/// <remarks><inheritdoc cref="Exemplar" path="/remarks/para[@experimental-warning='true']"/></remarks>
326-
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
327-
/// <param name="exemplarFilter"><see cref="ExemplarFilter"/> ExemplarFilter to use.</param>
328-
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
327+
/// <remarks>
328+
/// <inheritdoc cref="Exemplar"
329+
/// path="/remarks/para[@experimental-warning='true']"/>
330+
/// <para>Note: Use <see cref="ExemplarFilterType.TraceBased"/> or <see
331+
/// cref="ExemplarFilterType.AlwaysOn"/> to enable exemplars.</para>
332+
/// <para>Specification: <see
333+
/// href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#exemplarfilter"/>.</para>
334+
/// </remarks>
335+
/// <param name="meterProviderBuilder"><see
336+
/// cref="MeterProviderBuilder"/>.</param>
337+
/// <param name="exemplarFilter"><see cref="ExemplarFilterType"/> to
338+
/// use.</param>
339+
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for
340+
/// chaining.</returns>
329341
#if NET8_0_OR_GREATER
330342
[Experimental(DiagnosticDefinitions.ExemplarExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)]
331343
#endif
332344
public
333345
#else
334-
/// <summary>
335-
/// Sets the <see cref="ExemplarFilter"/> to be used for this provider.
336-
/// This is applied to all the metrics from this provider.
337-
/// </summary>
338-
/// <param name="meterProviderBuilder"><see cref="MeterProviderBuilder"/>.</param>
339-
/// <param name="exemplarFilter"><see cref="ExemplarFilter"/> ExemplarFilter to use.</param>
340-
/// <returns>The supplied <see cref="MeterProviderBuilder"/> for chaining.</returns>
341346
internal
342347
#endif
343-
static MeterProviderBuilder SetExemplarFilter(this MeterProviderBuilder meterProviderBuilder, ExemplarFilter exemplarFilter)
348+
static MeterProviderBuilder SetExemplarFilter(
349+
this MeterProviderBuilder meterProviderBuilder,
350+
ExemplarFilterType exemplarFilter = ExemplarFilterType.TraceBased)
344351
{
345-
Guard.ThrowIfNull(exemplarFilter);
346-
347352
meterProviderBuilder.ConfigureBuilder((sp, builder) =>
348353
{
349354
if (builder is MeterProviderBuilderSdk meterProviderBuilderSdk)
350355
{
351-
meterProviderBuilderSdk.SetExemplarFilter(exemplarFilter);
356+
switch (exemplarFilter)
357+
{
358+
case ExemplarFilterType.AlwaysOn:
359+
meterProviderBuilderSdk.SetExemplarFilter(new AlwaysOnExemplarFilter());
360+
break;
361+
case ExemplarFilterType.AlwaysOff:
362+
meterProviderBuilderSdk.SetExemplarFilter(new AlwaysOffExemplarFilter());
363+
break;
364+
case ExemplarFilterType.TraceBased:
365+
meterProviderBuilderSdk.SetExemplarFilter(new TraceBasedExemplarFilter());
366+
break;
367+
default:
368+
throw new NotSupportedException($"SdkExemplarFilter '{exemplarFilter}' is not supported.");
369+
}
352370
}
353371
});
354372

Diff for: src/OpenTelemetry/Metrics/Exemplar/AlwaysOffExemplarFilter.cs

+1-15
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,17 @@
11
// Copyright The OpenTelemetry Authors
22
// SPDX-License-Identifier: Apache-2.0
33

4-
#if EXPOSE_EXPERIMENTAL_FEATURES && NET8_0_OR_GREATER
5-
using System.Diagnostics.CodeAnalysis;
6-
using OpenTelemetry.Internal;
7-
#endif
8-
94
namespace OpenTelemetry.Metrics;
105

11-
#if EXPOSE_EXPERIMENTAL_FEATURES
126
/// <summary>
137
/// An <see cref="ExemplarFilter"/> implementation which makes no measurements
148
/// eligible for becoming an <see cref="Exemplar"/>.
159
/// </summary>
1610
/// <remarks>
17-
/// <inheritdoc cref="Exemplar" path="/remarks/para[@experimental-warning='true']"/>
1811
/// Specification: <see
1912
/// href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#alwaysoff"/>.
2013
/// </remarks>
21-
#if NET8_0_OR_GREATER
22-
[Experimental(DiagnosticDefinitions.ExemplarExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)]
23-
#endif
24-
public
25-
#else
26-
internal
27-
#endif
28-
sealed class AlwaysOffExemplarFilter : ExemplarFilter
14+
internal sealed class AlwaysOffExemplarFilter : ExemplarFilter
2915
{
3016
/// <inheritdoc/>
3117
public override bool ShouldSample(long value, ReadOnlySpan<KeyValuePair<string, object?>> tags)

Diff for: src/OpenTelemetry/Metrics/Exemplar/AlwaysOnExemplarFilter.cs

+1-18
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,17 @@
11
// Copyright The OpenTelemetry Authors
22
// SPDX-License-Identifier: Apache-2.0
33

4-
#if EXPOSE_EXPERIMENTAL_FEATURES && NET8_0_OR_GREATER
5-
using System.Diagnostics.CodeAnalysis;
6-
using OpenTelemetry.Internal;
7-
#endif
8-
94
namespace OpenTelemetry.Metrics;
105

11-
#if EXPOSE_EXPERIMENTAL_FEATURES
126
/// <summary>
137
/// An <see cref="ExemplarFilter"/> implementation which makes all measurements
148
/// eligible for becoming an <see cref="Exemplar"/>.
159
/// </summary>
1610
/// <remarks>
17-
/// <inheritdoc cref="Exemplar" path="/remarks/para[@experimental-warning='true']"/>
1811
/// Specification: <see
1912
/// href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#alwayson"/>.
2013
/// </remarks>
21-
#if NET8_0_OR_GREATER
22-
[Experimental(DiagnosticDefinitions.ExemplarExperimentalApi, UrlFormat = DiagnosticDefinitions.ExperimentalApiUrlFormat)]
23-
#endif
24-
public
25-
#else
26-
/// <summary>
27-
/// An ExemplarFilter which makes all measurements eligible for being an Exemplar.
28-
/// </summary>
29-
internal
30-
#endif
31-
sealed class AlwaysOnExemplarFilter : ExemplarFilter
14+
internal sealed class AlwaysOnExemplarFilter : ExemplarFilter
3215
{
3316
/// <inheritdoc/>
3417
public override bool ShouldSample(long value, ReadOnlySpan<KeyValuePair<string, object?>> tags)

0 commit comments

Comments
 (0)