Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/OpenTelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
metrics exporters which support exemplars.
([#5386](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5386))

* **Experimental (pre-release builds only):** Added support for exemplars when
using Base2 Exponential Bucket Histogram Aggregation configured via the View
API.
([#5396](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5396))

## 1.7.0

Released 2023-Dec-08
Expand Down
78 changes: 50 additions & 28 deletions src/OpenTelemetry/Metrics/MetricPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ internal MetricPoint(
{
this.mpComponents = new MetricPointOptionalComponents();
this.mpComponents.Base2ExponentialBucketHistogram = new Base2ExponentialBucketHistogram(exponentialHistogramMaxSize, exponentialHistogramMaxScale);
if (isExemplarEnabled && reservoir == null)
{
reservoir = new SimpleFixedSizeExemplarReservoir(Math.Min(20, exponentialHistogramMaxSize));
}
}
else
{
Expand Down Expand Up @@ -558,13 +562,13 @@ internal void UpdateWithExemplar(long number, ReadOnlySpan<KeyValuePair<string,

case AggregationType.Base2ExponentialHistogram:
{
this.UpdateBase2ExponentialHistogram((double)number, tags, true);
this.UpdateBase2ExponentialHistogram((double)number, tags, reportExemplar: true, isSampled);
break;
}

case AggregationType.Base2ExponentialHistogramWithMinMax:
{
this.UpdateBase2ExponentialHistogramWithMinMax((double)number, tags, true);
this.UpdateBase2ExponentialHistogramWithMinMax((double)number, tags, reportExemplar: true, isSampled);
break;
}
}
Expand Down Expand Up @@ -770,13 +774,13 @@ internal void UpdateWithExemplar(double number, ReadOnlySpan<KeyValuePair<string

case AggregationType.Base2ExponentialHistogram:
{
this.UpdateBase2ExponentialHistogram(number, tags, true);
this.UpdateBase2ExponentialHistogram(number, tags, reportExemplar: true, isSampled);
break;
}

case AggregationType.Base2ExponentialHistogramWithMinMax:
{
this.UpdateBase2ExponentialHistogramWithMinMax(number, tags, true);
this.UpdateBase2ExponentialHistogramWithMinMax(number, tags, reportExemplar: true, isSampled);
break;
}
}
Expand Down Expand Up @@ -1262,6 +1266,7 @@ internal void TakeSnapshotWithExemplar(bool outputDelta)
histogram.Reset();
}

this.mpComponents.Exemplars = this.mpComponents.ExemplarReservoir?.Collect();
this.MetricPointStatus = MetricPointStatus.NoCollectPending;

this.mpComponents.ReleaseLock();
Expand Down Expand Up @@ -1292,6 +1297,7 @@ internal void TakeSnapshotWithExemplar(bool outputDelta)
histogram.RunningMax = double.NegativeInfinity;
}

this.mpComponents.Exemplars = this.mpComponents.ExemplarReservoir?.Collect();
this.MetricPointStatus = MetricPointStatus.NoCollectPending;

this.mpComponents.ReleaseLock();
Expand Down Expand Up @@ -1372,16 +1378,16 @@ private void UpdateHistogramWithBuckets(double number, ReadOnlySpan<KeyValuePair
this.runningValue.AsLong++;
histogramBuckets.RunningSum += number;
histogramBuckets.BucketCounts[i].RunningValue++;
}

if (reportExemplar && isSampled)
{
Debug.Assert(this.mpComponents.ExemplarReservoir != null, "ExemplarReservoir was null");
if (reportExemplar && isSampled)
{
Debug.Assert(this.mpComponents.ExemplarReservoir != null, "ExemplarReservoir was null");

// TODO: Need to ensure that the lock is always released.
// A custom implementation of `ExemplarReservoir.Offer` might throw an exception.
this.mpComponents.ExemplarReservoir!.Offer(
new ExemplarMeasurement<double>(number, tags, i));
}
// TODO: Need to ensure that the lock is always released.
// A custom implementation of `ExemplarReservoir.Offer` might throw an exception.
this.mpComponents.ExemplarReservoir!.Offer(
new ExemplarMeasurement<double>(number, tags, i));
}

this.mpComponents.ReleaseLock();
Expand All @@ -1403,26 +1409,24 @@ private void UpdateHistogramWithBucketsAndMinMax(double number, ReadOnlySpan<Key
histogramBuckets.RunningSum += number;
histogramBuckets.BucketCounts[i].RunningValue++;

if (reportExemplar && isSampled)
{
Debug.Assert(this.mpComponents.ExemplarReservoir != null, "ExemplarReservoir was null");

// TODO: Need to ensure that the lock is always released.
// A custom implementation of `ExemplarReservoir.Offer` might throw an exception.
this.mpComponents.ExemplarReservoir!.Offer(
new ExemplarMeasurement<double>(number, tags, i));
}

histogramBuckets.RunningMin = Math.Min(histogramBuckets.RunningMin, number);
histogramBuckets.RunningMax = Math.Max(histogramBuckets.RunningMax, number);
}

if (reportExemplar && isSampled)
{
Debug.Assert(this.mpComponents.ExemplarReservoir != null, "ExemplarReservoir was null");

// TODO: Need to ensure that the lock is always released.
// A custom implementation of `ExemplarReservoir.Offer` might throw an exception.
this.mpComponents.ExemplarReservoir!.Offer(
new ExemplarMeasurement<double>(number, tags, i));
}

this.mpComponents.ReleaseLock();
}

#pragma warning disable IDE0060 // Remove unused parameter: Exemplars for exponential histograms will be a follow up PR
private void UpdateBase2ExponentialHistogram(double number, ReadOnlySpan<KeyValuePair<string, object?>> tags = default, bool reportExemplar = false)
#pragma warning restore IDE0060 // Remove unused parameter
private void UpdateBase2ExponentialHistogram(double number, ReadOnlySpan<KeyValuePair<string, object?>> tags = default, bool reportExemplar = false, bool isSampled = false)
{
if (number < 0)
{
Expand All @@ -1442,12 +1446,20 @@ private void UpdateBase2ExponentialHistogram(double number, ReadOnlySpan<KeyValu
histogram.Record(number);
}

if (reportExemplar && isSampled)
{
Debug.Assert(this.mpComponents.ExemplarReservoir != null, "ExemplarReservoir was null");

// TODO: Need to ensure that the lock is always released.
// A custom implementation of `ExemplarReservoir.Offer` might throw an exception.
this.mpComponents.ExemplarReservoir!.Offer(
new ExemplarMeasurement<double>(number, tags));
}

this.mpComponents.ReleaseLock();
}

#pragma warning disable IDE0060 // Remove unused parameter: Exemplars for exponential histograms will be a follow up PR
private void UpdateBase2ExponentialHistogramWithMinMax(double number, ReadOnlySpan<KeyValuePair<string, object?>> tags = default, bool reportExemplar = false)
#pragma warning restore IDE0060 // Remove unused parameter
private void UpdateBase2ExponentialHistogramWithMinMax(double number, ReadOnlySpan<KeyValuePair<string, object?>> tags = default, bool reportExemplar = false, bool isSampled = false)
{
if (number < 0)
{
Expand All @@ -1470,6 +1482,16 @@ private void UpdateBase2ExponentialHistogramWithMinMax(double number, ReadOnlySp
histogram.RunningMax = Math.Max(histogram.RunningMax, number);
}

if (reportExemplar && isSampled)
{
Debug.Assert(this.mpComponents.ExemplarReservoir != null, "ExemplarReservoir was null");

// TODO: Need to ensure that the lock is always released.
// A custom implementation of `ExemplarReservoir.Offer` might throw an exception.
this.mpComponents.ExemplarReservoir!.Offer(
new ExemplarMeasurement<double>(number, tags));
}

this.mpComponents.ReleaseLock();
}

Expand Down
Loading