Skip to content

Commit 25a9366

Browse files
CodeBlanchKielek
andauthored
[sdk-metrics] Fix a race condition when a metric is deactivated and re-activated in the same collection cycle (open-telemetry#5908)
Co-authored-by: Piotr Kiełkowicz <[email protected]>
1 parent 0eebf97 commit 25a9366

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

src/OpenTelemetry/Metrics/Reader/MetricReaderExt.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace OpenTelemetry.Metrics;
1515
public abstract partial class MetricReader
1616
{
1717
private readonly HashSet<string> metricStreamNames = new(StringComparer.OrdinalIgnoreCase);
18-
private readonly ConcurrentDictionary<MetricStreamIdentity, Metric> instrumentIdentityToMetric = new();
18+
private readonly ConcurrentDictionary<MetricStreamIdentity, Metric?> instrumentIdentityToMetric = new();
1919
private readonly Lock instrumentCreationLock = new();
2020
private int metricLimit;
2121
private int cardinalityLimit;
@@ -201,7 +201,7 @@ internal void ApplyParentProviderSettings(
201201

202202
private bool TryGetExistingMetric(in MetricStreamIdentity metricStreamIdentity, [NotNullWhen(true)] out Metric? existingMetric)
203203
=> this.instrumentIdentityToMetric.TryGetValue(metricStreamIdentity, out existingMetric)
204-
&& existingMetric.Active;
204+
&& existingMetric != null && existingMetric.Active;
205205

206206
private void CreateOrUpdateMetricStreamRegistration(in MetricStreamIdentity metricStreamIdentity)
207207
{
@@ -268,8 +268,12 @@ private void RemoveMetric(ref Metric? metric)
268268

269269
OpenTelemetrySdkEventSource.Log.MetricInstrumentRemoved(metric!.Name, metric.MeterName);
270270

271-
var result = this.instrumentIdentityToMetric.TryRemove(metric.InstrumentIdentity, out var _);
272-
Debug.Assert(result, "result was false");
271+
// Note: This is using TryUpdate and NOT TryRemove because there is a
272+
// race condition. If a metric is deactivated and then reactivated in
273+
// the same collection cycle
274+
// instrumentIdentityToMetric[metric.InstrumentIdentity] may already
275+
// point to the new activated metric and not the old deactivated one.
276+
this.instrumentIdentityToMetric.TryUpdate(metric.InstrumentIdentity, null, metric);
273277

274278
// Note: metric is a reference to the array storage so
275279
// this clears the metric out of the array.

0 commit comments

Comments
 (0)