Skip to content

Commit 112e17f

Browse files
authored
[sdk-metrics] Stablize MetricPoint reclaim feature for delta aggregation (open-telemetry#5956)
1 parent 1e1201a commit 112e17f

File tree

13 files changed

+40
-209
lines changed

13 files changed

+40
-209
lines changed

docs/metrics/README.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -402,14 +402,10 @@ is used, it is possible to choose a smaller cardinality limit by allowing the
402402
SDK to reclaim unused metric points.
403403

404404
> [!NOTE]
405-
> Reclaim unused metric points feature was introduced in OpenTelemetry .NET
406-
[1.7.0-alpha.1](../../src/OpenTelemetry/CHANGELOG.md#170-alpha1). It is
407-
currently an experimental feature which can be turned on by setting the
408-
environment variable
409-
`OTEL_DOTNET_EXPERIMENTAL_METRICS_RECLAIM_UNUSED_METRIC_POINTS=true`. Once the
410-
[OpenTelemetry
411-
Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#overflow-attribute)
412-
become stable, this feature will be turned on by default.
405+
> Metric points reclaim is the default and only behavior for Delta Aggregation
406+
Temporality starting with version 1.10.0. In version 1.7.0 - 1.9.0, it was an
407+
experimental feature that could be enabled by setting the environment variable
408+
`OTEL_DOTNET_EXPERIMENTAL_METRICS_RECLAIM_UNUSED_METRIC_POINTS=true`.
413409

414410
### Memory Preallocation
415411

src/OpenTelemetry/CHANGELOG.md

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

77
## Unreleased
88

9+
* Promote MetricPoint reclaim feature for delta aggregation from experimental to
10+
stable.
11+
Previously, it is an experimental feature which can be turned on by setting
12+
the environment variable
13+
`OTEL_DOTNET_EXPERIMENTAL_METRICS_RECLAIM_UNUSED_METRIC_POINTS=true`.
14+
Now that the [OpenTelemetry
15+
Specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#overflow-attribute)
16+
has become stable. The feature is the default and the only allowed behavior
17+
without the need to set an environment variable.
18+
([#5956](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5956))
19+
920
## 1.10.0-rc.1
1021

1122
Released 2024-Nov-01

src/OpenTelemetry/Metrics/AggregatorStore.cs

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ internal sealed class AggregatorStore
2020
internal readonly HashSet<string>? TagKeysInteresting;
2121
#endif
2222
internal readonly bool OutputDelta;
23-
internal readonly bool OutputDeltaWithUnusedMetricPointReclaimEnabled;
2423
internal readonly int NumberOfMetricPoints;
2524
internal readonly ConcurrentDictionary<Tags, LookupData>? TagsToMetricPointIndexDictionaryDelta;
2625
internal readonly Func<ExemplarReservoir?>? ExemplarReservoirFactory;
@@ -61,7 +60,6 @@ internal AggregatorStore(
6160
AggregationType aggType,
6261
AggregationTemporality temporality,
6362
int cardinalityLimit,
64-
bool shouldReclaimUnusedMetricPoints,
6563
ExemplarFilterType? exemplarFilter = null,
6664
Func<ExemplarReservoir?>? exemplarReservoirFactory = null)
6765
{
@@ -110,9 +108,8 @@ internal AggregatorStore(
110108
// Newer attributes should be added starting at the index: 2
111109
this.metricPointIndex = 1;
112110

113-
this.OutputDeltaWithUnusedMetricPointReclaimEnabled = shouldReclaimUnusedMetricPoints && this.OutputDelta;
114-
115-
if (this.OutputDeltaWithUnusedMetricPointReclaimEnabled)
111+
// Always reclaim unused MetricPoints for Delta aggregation temporality
112+
if (this.OutputDelta)
116113
{
117114
this.availableMetricPoints = new Queue<int>(cardinalityLimit);
118115

@@ -184,15 +181,10 @@ internal void Update(double value, ReadOnlySpan<KeyValuePair<string, object?>> t
184181
internal int Snapshot()
185182
{
186183
this.batchSize = 0;
187-
if (this.OutputDeltaWithUnusedMetricPointReclaimEnabled)
184+
if (this.OutputDelta)
188185
{
189186
this.SnapshotDeltaWithMetricPointReclaim();
190187
}
191-
else if (this.OutputDelta)
192-
{
193-
var indexSnapshot = Math.Min(this.metricPointIndex, this.NumberOfMetricPoints - 1);
194-
this.SnapshotDelta(indexSnapshot);
195-
}
196188
else
197189
{
198190
var indexSnapshot = Math.Min(this.metricPointIndex, this.NumberOfMetricPoints - 1);
@@ -203,28 +195,6 @@ internal int Snapshot()
203195
return this.batchSize;
204196
}
205197

206-
internal void SnapshotDelta(int indexSnapshot)
207-
{
208-
for (int i = 0; i <= indexSnapshot; i++)
209-
{
210-
ref var metricPoint = ref this.metricPoints[i];
211-
if (metricPoint.MetricPointStatus == MetricPointStatus.NoCollectPending)
212-
{
213-
continue;
214-
}
215-
216-
this.TakeMetricPointSnapshot(ref metricPoint, outputDelta: true);
217-
218-
this.currentMetricPointBatch[this.batchSize] = i;
219-
this.batchSize++;
220-
}
221-
222-
if (this.EndTimeInclusive != default)
223-
{
224-
this.StartTimeExclusive = this.EndTimeInclusive;
225-
}
226-
}
227-
228198
internal void SnapshotDeltaWithMetricPointReclaim()
229199
{
230200
// Index = 0 is reserved for the case where no dimensions are provided.

src/OpenTelemetry/Metrics/MeterProviderSdk.cs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@ namespace OpenTelemetry.Metrics;
1313

1414
internal sealed class MeterProviderSdk : MeterProvider
1515
{
16-
internal const string ReclaimUnusedMetricPointsConfigKey = "OTEL_DOTNET_EXPERIMENTAL_METRICS_RECLAIM_UNUSED_METRIC_POINTS";
1716
internal const string ExemplarFilterConfigKey = "OTEL_METRICS_EXEMPLAR_FILTER";
1817
internal const string ExemplarFilterHistogramsConfigKey = "OTEL_DOTNET_EXPERIMENTAL_METRICS_EXEMPLAR_FILTER_HISTOGRAMS";
1918

2019
internal readonly IServiceProvider ServiceProvider;
2120
internal readonly IDisposable? OwnedServiceProvider;
2221
internal int ShutdownCount;
2322
internal bool Disposed;
24-
internal bool ReclaimUnusedMetricPoints;
2523
internal ExemplarFilterType? ExemplarFilter;
2624
internal ExemplarFilterType? ExemplarFilterForHistograms;
2725
internal Action? OnCollectObservableInstruments;
@@ -73,7 +71,7 @@ internal MeterProviderSdk(
7371
this.viewConfigs = state.ViewConfigs;
7472

7573
OpenTelemetrySdkEventSource.Log.MeterProviderSdkEvent(
76-
$"MeterProvider configuration: {{MetricLimit={state.MetricLimit}, CardinalityLimit={state.CardinalityLimit}, ReclaimUnusedMetricPoints={this.ReclaimUnusedMetricPoints}, ExemplarFilter={this.ExemplarFilter}, ExemplarFilterForHistograms={this.ExemplarFilterForHistograms}}}.");
74+
$"MeterProvider configuration: {{MetricLimit={state.MetricLimit}, CardinalityLimit={state.CardinalityLimit}, ExemplarFilter={this.ExemplarFilter}, ExemplarFilterForHistograms={this.ExemplarFilterForHistograms}}}.");
7775

7876
foreach (var reader in state.Readers)
7977
{
@@ -84,7 +82,6 @@ internal MeterProviderSdk(
8482
reader.ApplyParentProviderSettings(
8583
state.MetricLimit,
8684
state.CardinalityLimit,
87-
this.ReclaimUnusedMetricPoints,
8885
this.ExemplarFilter,
8986
this.ExemplarFilterForHistograms);
9087

@@ -483,11 +480,6 @@ protected override void Dispose(bool disposing)
483480

484481
private void ApplySpecificationConfigurationKeys(IConfiguration configuration)
485482
{
486-
if (configuration.TryGetBoolValue(OpenTelemetrySdkEventSource.Log, ReclaimUnusedMetricPointsConfigKey, out this.ReclaimUnusedMetricPoints))
487-
{
488-
OpenTelemetrySdkEventSource.Log.MeterProviderSdkEvent("Reclaim unused metric point feature enabled via configuration.");
489-
}
490-
491483
var hasProgrammaticExemplarFilterValue = this.ExemplarFilter.HasValue;
492484

493485
if (configuration.TryGetStringValue(ExemplarFilterConfigKey, out var configValue))

src/OpenTelemetry/Metrics/Metric.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ internal Metric(
7070
MetricStreamIdentity instrumentIdentity,
7171
AggregationTemporality temporality,
7272
int cardinalityLimit,
73-
bool shouldReclaimUnusedMetricPoints,
7473
ExemplarFilterType? exemplarFilter = null,
7574
Func<ExemplarReservoir?>? exemplarReservoirFactory = null)
7675
{
@@ -192,7 +191,6 @@ internal Metric(
192191
aggType,
193192
temporality,
194193
cardinalityLimit,
195-
shouldReclaimUnusedMetricPoints,
196194
exemplarFilter,
197195
exemplarReservoirFactory);
198196
this.Temporality = temporality;

src/OpenTelemetry/Metrics/MetricPoint/MetricPoint.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ internal MetricPoint(
4646
{
4747
Debug.Assert(aggregatorStore != null, "AggregatorStore was null.");
4848
Debug.Assert(histogramExplicitBounds != null, "Histogram explicit Bounds was null.");
49-
Debug.Assert(!aggregatorStore!.OutputDeltaWithUnusedMetricPointReclaimEnabled || lookupData != null, "LookupData was null.");
49+
Debug.Assert(!aggregatorStore!.OutputDelta || lookupData != null, "LookupData was null.");
5050

5151
this.aggType = aggType;
5252
this.Tags = new ReadOnlyTagCollection(tagKeysAndValues);
@@ -1086,7 +1086,7 @@ private void CompleteUpdate()
10861086
[MethodImpl(MethodImplOptions.AggressiveInlining)]
10871087
private void CompleteUpdateWithoutMeasurement()
10881088
{
1089-
if (this.aggregatorStore.OutputDeltaWithUnusedMetricPointReclaimEnabled)
1089+
if (this.aggregatorStore.OutputDelta)
10901090
{
10911091
Interlocked.Decrement(ref this.ReferenceCount);
10921092
}

src/OpenTelemetry/Metrics/Reader/MetricReaderExt.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public abstract partial class MetricReader
2222
private Metric?[]? metrics;
2323
private Metric[]? metricsCurrentBatch;
2424
private int metricIndex = -1;
25-
private bool reclaimUnusedMetricPoints;
2625
private ExemplarFilterType? exemplarFilter;
2726
private ExemplarFilterType? exemplarFilterForHistograms;
2827

@@ -81,7 +80,6 @@ internal virtual List<Metric> AddMetricWithNoViews(Instrument instrument)
8180
metricStreamIdentity,
8281
this.GetAggregationTemporality(metricStreamIdentity.InstrumentType),
8382
this.cardinalityLimit,
84-
this.reclaimUnusedMetricPoints,
8583
exemplarFilter);
8684
}
8785
catch (NotSupportedException nse)
@@ -162,7 +160,6 @@ internal virtual List<Metric> AddMetricWithViews(Instrument instrument, List<Met
162160
metricStreamIdentity,
163161
this.GetAggregationTemporality(metricStreamIdentity.InstrumentType),
164162
metricStreamConfig?.CardinalityLimit ?? this.cardinalityLimit,
165-
this.reclaimUnusedMetricPoints,
166163
exemplarFilter,
167164
metricStreamConfig?.ExemplarReservoirFactory);
168165

@@ -181,15 +178,13 @@ internal virtual List<Metric> AddMetricWithViews(Instrument instrument, List<Met
181178
internal void ApplyParentProviderSettings(
182179
int metricLimit,
183180
int cardinalityLimit,
184-
bool reclaimUnusedMetricPoints,
185181
ExemplarFilterType? exemplarFilter,
186182
ExemplarFilterType? exemplarFilterForHistograms)
187183
{
188184
this.metricLimit = metricLimit;
189185
this.metrics = new Metric[metricLimit];
190186
this.metricsCurrentBatch = new Metric[metricLimit];
191187
this.cardinalityLimit = cardinalityLimit;
192-
this.reclaimUnusedMetricPoints = reclaimUnusedMetricPoints;
193188
this.exemplarFilter = exemplarFilter;
194189
this.exemplarFilterForHistograms = exemplarFilterForHistograms;
195190
}

test/OpenTelemetry.Tests/Metrics/AggregatorTestsBase.cs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,11 @@ public abstract class AggregatorTestsBase
1616
private static readonly ExplicitBucketHistogramConfiguration HistogramConfiguration = new() { Boundaries = Metric.DefaultHistogramBounds };
1717
private static readonly MetricStreamIdentity MetricStreamIdentity = new(Instrument, HistogramConfiguration);
1818

19-
private readonly bool shouldReclaimUnusedMetricPoints;
2019
private readonly AggregatorStore aggregatorStore;
2120

22-
protected AggregatorTestsBase(bool shouldReclaimUnusedMetricPoints)
21+
protected AggregatorTestsBase()
2322
{
24-
this.shouldReclaimUnusedMetricPoints = shouldReclaimUnusedMetricPoints;
25-
26-
this.aggregatorStore = new(MetricStreamIdentity, AggregationType.HistogramWithBuckets, AggregationTemporality.Cumulative, 1024, this.shouldReclaimUnusedMetricPoints);
23+
this.aggregatorStore = new(MetricStreamIdentity, AggregationType.HistogramWithBuckets, AggregationTemporality.Cumulative, 1024);
2724
}
2825

2926
[Fact]
@@ -250,8 +247,7 @@ public void HistogramBucketsDefaultUpdatesForSecondsTest(string meterName, strin
250247
metricStreamIdentity,
251248
AggregationType.Histogram,
252249
AggregationTemporality.Cumulative,
253-
cardinalityLimit: 1024,
254-
this.shouldReclaimUnusedMetricPoints);
250+
cardinalityLimit: 1024);
255251

256252
KnownHistogramBuckets actualHistogramBounds = KnownHistogramBuckets.Default;
257253
if (aggregatorStore.HistogramBounds == Metric.DefaultHistogramBoundsShortSeconds)
@@ -327,7 +323,6 @@ internal void ExponentialHistogramTests(AggregationType aggregationType, Aggrega
327323
aggregationType,
328324
aggregationTemporality,
329325
cardinalityLimit: 1024,
330-
this.shouldReclaimUnusedMetricPoints,
331326
exemplarsEnabled ? ExemplarFilterType.AlwaysOn : null);
332327

333328
var expectedHistogram = new Base2ExponentialBucketHistogram();
@@ -435,8 +430,7 @@ internal void ExponentialMaxScaleConfigWorks(int? maxScale)
435430
metricStreamIdentity,
436431
AggregationType.Base2ExponentialHistogram,
437432
AggregationTemporality.Cumulative,
438-
cardinalityLimit: 1024,
439-
this.shouldReclaimUnusedMetricPoints);
433+
cardinalityLimit: 1024);
440434

441435
aggregatorStore.Update(10, Array.Empty<KeyValuePair<string, object?>>());
442436

@@ -520,15 +514,7 @@ public ThreadArguments(MetricPoint histogramPoint, ManualResetEvent mreToEnsureA
520514
public class AggregatorTests : AggregatorTestsBase
521515
{
522516
public AggregatorTests()
523-
: base(shouldReclaimUnusedMetricPoints: false)
524-
{
525-
}
526-
}
527-
528-
public class AggregatorTestsWithReclaimAttribute : AggregatorTestsBase
529-
{
530-
public AggregatorTestsWithReclaimAttribute()
531-
: base(shouldReclaimUnusedMetricPoints: true)
517+
: base()
532518
{
533519
}
534520
}

test/OpenTelemetry.Tests/Metrics/MetricApiTestsBase.cs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ public abstract class MetricApiTestsBase : MetricTestsBase
2323
private static readonly int NumberOfMetricUpdateByEachThread = 100000;
2424
private readonly ITestOutputHelper output;
2525

26-
protected MetricApiTestsBase(ITestOutputHelper output, bool shouldReclaimUnusedMetricPoints)
27-
: base(BuildConfiguration(shouldReclaimUnusedMetricPoints))
26+
protected MetricApiTestsBase(ITestOutputHelper output)
27+
: base(BuildConfiguration())
2828
{
2929
this.output = output;
3030
}
@@ -1703,15 +1703,9 @@ public void GaugeHandlesNoNewMeasurementsCorrectlyWithTemporality(MetricReaderTe
17031703
}
17041704
}
17051705

1706-
internal static IConfiguration BuildConfiguration(bool shouldReclaimUnusedMetricPoints)
1706+
internal static IConfiguration BuildConfiguration()
17071707
{
17081708
var configurationData = new Dictionary<string, string?>();
1709-
1710-
if (shouldReclaimUnusedMetricPoints)
1711-
{
1712-
configurationData[ReclaimUnusedMetricPointsConfigKey] = "true";
1713-
}
1714-
17151709
return new ConfigurationBuilder()
17161710
.AddInMemoryCollection(configurationData)
17171711
.Build();
@@ -1888,15 +1882,7 @@ public UpdateThreadArguments(ManualResetEvent mreToBlockUpdateThread, ManualRese
18881882
public class MetricApiTest : MetricApiTestsBase
18891883
{
18901884
public MetricApiTest(ITestOutputHelper output)
1891-
: base(output, shouldReclaimUnusedMetricPoints: false)
1892-
{
1893-
}
1894-
}
1895-
1896-
public class MetricApiTestWithReclaimAttribute : MetricApiTestsBase
1897-
{
1898-
public MetricApiTestWithReclaimAttribute(ITestOutputHelper output)
1899-
: base(output, shouldReclaimUnusedMetricPoints: true)
1885+
: base(output)
19001886
{
19011887
}
19021888
}

0 commit comments

Comments
 (0)