Update MetricPoint for Histograms (#2657)

This commit is contained in:
Utkarsh Umesan Pillai 2021-11-22 16:31:45 -08:00 committed by GitHub
parent ca22838762
commit 69ef5f86bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 224 additions and 99 deletions

View File

@ -95,38 +95,42 @@ namespace OpenTelemetry.Exporter
if (metricType.IsHistogram())
{
var bucketsBuilder = new StringBuilder();
bucketsBuilder.Append($"Sum: {metricPoint.DoubleValue} Count: {metricPoint.LongValue} \n");
var sum = metricPoint.GetHistogramSum();
var count = metricPoint.GetHistogramCount();
bucketsBuilder.Append($"Sum: {sum} Count: {count} \n");
if (metricPoint.ExplicitBounds != null)
var explicitBounds = metricPoint.GetExplicitBounds();
if (explicitBounds != null)
{
for (int i = 0; i < metricPoint.ExplicitBounds.Length + 1; i++)
var bucketCounts = metricPoint.GetBucketCounts();
for (int i = 0; i < explicitBounds.Length + 1; i++)
{
if (i == 0)
{
bucketsBuilder.Append("(-Infinity,");
bucketsBuilder.Append(metricPoint.ExplicitBounds[i]);
bucketsBuilder.Append(explicitBounds[i]);
bucketsBuilder.Append(']');
bucketsBuilder.Append(':');
bucketsBuilder.Append(metricPoint.BucketCounts[i]);
bucketsBuilder.Append(bucketCounts[i]);
}
else if (i == metricPoint.ExplicitBounds.Length)
else if (i == explicitBounds.Length)
{
bucketsBuilder.Append('(');
bucketsBuilder.Append(metricPoint.ExplicitBounds[i - 1]);
bucketsBuilder.Append(explicitBounds[i - 1]);
bucketsBuilder.Append(',');
bucketsBuilder.Append("+Infinity]");
bucketsBuilder.Append(':');
bucketsBuilder.Append(metricPoint.BucketCounts[i]);
bucketsBuilder.Append(bucketCounts[i]);
}
else
{
bucketsBuilder.Append('(');
bucketsBuilder.Append(metricPoint.ExplicitBounds[i - 1]);
bucketsBuilder.Append(explicitBounds[i - 1]);
bucketsBuilder.Append(',');
bucketsBuilder.Append(metricPoint.ExplicitBounds[i]);
bucketsBuilder.Append(explicitBounds[i]);
bucketsBuilder.Append(']');
bucketsBuilder.Append(':');
bucketsBuilder.Append(metricPoint.BucketCounts[i]);
bucketsBuilder.Append(bucketCounts[i]);
}
bucketsBuilder.AppendLine();

View File

@ -249,14 +249,16 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation
dataPoint.Count = (ulong)metricPoint.LongValue;
dataPoint.Sum = metricPoint.DoubleValue;
if (metricPoint.BucketCounts != null)
var bucketCounts = metricPoint.GetBucketCounts();
if (bucketCounts != null)
{
for (int i = 0; i < metricPoint.BucketCounts.Length; i++)
var explicitBounds = metricPoint.GetExplicitBounds();
for (int i = 0; i < bucketCounts.Length; i++)
{
dataPoint.BucketCounts.Add((ulong)metricPoint.BucketCounts[i]);
if (i < metricPoint.BucketCounts.Length - 1)
dataPoint.BucketCounts.Add((ulong)bucketCounts[i]);
if (i < bucketCounts.Length - 1)
{
dataPoint.ExplicitBounds.Add(metricPoint.ExplicitBounds[i]);
dataPoint.ExplicitBounds.Add(explicitBounds[i]);
}
}
}

View File

@ -91,11 +91,11 @@ namespace OpenTelemetry.Exporter.Prometheus
var tags = metricPoint.Tags;
var timestamp = metricPoint.EndTime.ToUnixTimeMilliseconds();
if (metricPoint.BucketCounts != null)
var bucketCounts = metricPoint.GetBucketCounts();
if (bucketCounts != null)
{
// Histogram buckets
var bucketCounts = metricPoint.BucketCounts;
var explicitBounds = metricPoint.ExplicitBounds;
var explicitBounds = metricPoint.GetExplicitBounds();
long totalCount = 0;
for (int idxBound = 0; idxBound < explicitBounds.Length + 1; idxBound++)
{
@ -133,6 +133,9 @@ namespace OpenTelemetry.Exporter.Prometheus
}
// Histogram sum
var count = metricPoint.GetHistogramCount();
var sum = metricPoint.GetHistogramSum();
cursor = WriteMetricName(buffer, cursor, metric.Name, metric.Unit);
cursor = WriteAsciiStringNoEscape(buffer, cursor, "_sum");
@ -156,7 +159,7 @@ namespace OpenTelemetry.Exporter.Prometheus
buffer[cursor++] = unchecked((byte)' ');
cursor = WriteDouble(buffer, cursor, metricPoint.DoubleValue);
cursor = WriteDouble(buffer, cursor, sum);
buffer[cursor++] = unchecked((byte)' ');
cursor = WriteLong(buffer, cursor, timestamp);
@ -187,7 +190,7 @@ namespace OpenTelemetry.Exporter.Prometheus
buffer[cursor++] = unchecked((byte)' ');
cursor = WriteLong(buffer, cursor, metricPoint.LongValue);
cursor = WriteLong(buffer, cursor, count);
buffer[cursor++] = unchecked((byte)' ');
cursor = WriteLong(buffer, cursor, timestamp);

View File

@ -56,10 +56,12 @@ OpenTelemetry.Metrics.Metric.Name.get -> string
OpenTelemetry.Metrics.Metric.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.Metric.Unit.get -> string
OpenTelemetry.Metrics.MetricPoint
OpenTelemetry.Metrics.MetricPoint.BucketCounts.get -> long[]
OpenTelemetry.Metrics.MetricPoint.DoubleValue.get -> double
OpenTelemetry.Metrics.MetricPoint.EndTime.get -> System.DateTimeOffset
OpenTelemetry.Metrics.MetricPoint.ExplicitBounds.get -> double[]
OpenTelemetry.Metrics.MetricPoint.GetBucketCounts() -> long[]
OpenTelemetry.Metrics.MetricPoint.GetExplicitBounds() -> double[]
OpenTelemetry.Metrics.MetricPoint.GetHistogramCount() -> long
OpenTelemetry.Metrics.MetricPoint.GetHistogramSum() -> double
OpenTelemetry.Metrics.MetricPoint.LongValue.get -> long
OpenTelemetry.Metrics.MetricPoint.MetricPoint() -> void
OpenTelemetry.Metrics.MetricPoint.StartTime.get -> System.DateTimeOffset

View File

@ -56,10 +56,12 @@ OpenTelemetry.Metrics.Metric.Name.get -> string
OpenTelemetry.Metrics.Metric.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.Metric.Unit.get -> string
OpenTelemetry.Metrics.MetricPoint
OpenTelemetry.Metrics.MetricPoint.BucketCounts.get -> long[]
OpenTelemetry.Metrics.MetricPoint.DoubleValue.get -> double
OpenTelemetry.Metrics.MetricPoint.EndTime.get -> System.DateTimeOffset
OpenTelemetry.Metrics.MetricPoint.ExplicitBounds.get -> double[]
OpenTelemetry.Metrics.MetricPoint.GetBucketCounts() -> long[]
OpenTelemetry.Metrics.MetricPoint.GetExplicitBounds() -> double[]
OpenTelemetry.Metrics.MetricPoint.GetHistogramCount() -> long
OpenTelemetry.Metrics.MetricPoint.GetHistogramSum() -> double
OpenTelemetry.Metrics.MetricPoint.LongValue.get -> long
OpenTelemetry.Metrics.MetricPoint.MetricPoint() -> void
OpenTelemetry.Metrics.MetricPoint.StartTime.get -> System.DateTimeOffset

View File

@ -6,12 +6,16 @@
`Keys`+`Values`
([#2642](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2642))
* Refactored `MetricPoint` and added public methods: `GetBucketCounts`,
`GetExplicitBounds`, `GetHistogramCount`, and `GetHistogramSum`
([#2657](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2657))
## 1.2.0-beta2
Released 2021-Nov-19
* Renamed `HistogramConfiguration` to `ExplicitBucketHistogramConfiguration`
and changed its member `BucketBounds` to `Boundaries`.
* Renamed `HistogramConfiguration` to `ExplicitBucketHistogramConfiguration` and
changed its member `BucketBounds` to `Boundaries`.
([#2638](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2638))
* Metrics with the same name but from different meters are allowed.

View File

@ -0,0 +1,45 @@
// <copyright file="HistogramMeasurements.cs" company="OpenTelemetry Authors">
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
namespace OpenTelemetry.Metrics
{
internal class HistogramMeasurements
{
internal readonly long[] BucketCounts;
internal readonly long[] AggregatedBucketCounts;
internal readonly double[] ExplicitBounds;
internal readonly object LockObject;
internal long CountVal;
internal long Count;
internal double SumVal;
internal double Sum;
internal HistogramMeasurements(double[] histogramBounds)
{
this.ExplicitBounds = histogramBounds;
this.BucketCounts = histogramBounds != null ? new long[histogramBounds.Length + 1] : null;
this.AggregatedBucketCounts = histogramBounds != null ? new long[histogramBounds.Length + 1] : null;
this.LockObject = new object();
}
}
}

View File

@ -23,8 +23,7 @@ namespace OpenTelemetry.Metrics
public struct MetricPoint
{
private readonly AggregationType aggType;
private readonly object lockObject;
private readonly long[] bucketCounts;
private readonly HistogramMeasurements histogramMeasurements;
private long longVal;
private long lastLongSum;
private double doubleVal;
@ -53,24 +52,15 @@ namespace OpenTelemetry.Metrics
if (this.aggType == AggregationType.Histogram)
{
this.ExplicitBounds = histogramBounds;
this.BucketCounts = new long[this.ExplicitBounds.Length + 1];
this.bucketCounts = new long[this.ExplicitBounds.Length + 1];
this.lockObject = new object();
this.histogramMeasurements = new HistogramMeasurements(histogramBounds);
}
else if (this.aggType == AggregationType.HistogramSumCount)
{
this.ExplicitBounds = null;
this.BucketCounts = null;
this.bucketCounts = null;
this.lockObject = new object();
this.histogramMeasurements = new HistogramMeasurements(null);
}
else
{
this.ExplicitBounds = null;
this.BucketCounts = null;
this.bucketCounts = null;
this.lockObject = null;
this.histogramMeasurements = null;
}
}
@ -87,12 +77,56 @@ namespace OpenTelemetry.Metrics
public double DoubleValue { get; internal set; }
public long[] BucketCounts { get; internal set; }
public double[] ExplicitBounds { get; internal set; }
internal MetricPointStatus MetricPointStatus { get; private set; }
public long[] GetBucketCounts()
{
if (this.aggType == AggregationType.Histogram)
{
return this.histogramMeasurements.AggregatedBucketCounts;
}
else
{
throw new NotSupportedException($"{nameof(this.GetBucketCounts)} is not supported for this metric type.");
}
}
public double[] GetExplicitBounds()
{
if (this.aggType == AggregationType.Histogram)
{
return this.histogramMeasurements.ExplicitBounds;
}
else
{
throw new NotSupportedException($"{nameof(this.GetExplicitBounds)} is not supported for this metric type.");
}
}
public long GetHistogramCount()
{
if (this.aggType == AggregationType.Histogram || this.aggType == AggregationType.HistogramSumCount)
{
return this.histogramMeasurements.Count;
}
else
{
throw new NotSupportedException($"{nameof(this.GetHistogramCount)} is not supported for this metric type.");
}
}
public double GetHistogramSum()
{
if (this.aggType == AggregationType.Histogram || this.aggType == AggregationType.HistogramSumCount)
{
return this.histogramMeasurements.Sum;
}
else
{
throw new NotSupportedException($"{nameof(this.GetHistogramSum)} is not supported for this metric type.");
}
}
internal void Update(long number)
{
switch (this.aggType)
@ -168,20 +202,20 @@ namespace OpenTelemetry.Metrics
case AggregationType.Histogram:
{
int i;
for (i = 0; i < this.ExplicitBounds.Length; i++)
for (i = 0; i < this.histogramMeasurements.ExplicitBounds.Length; i++)
{
// Upper bound is inclusive
if (number <= this.ExplicitBounds[i])
if (number <= this.histogramMeasurements.ExplicitBounds[i])
{
break;
}
}
lock (this.lockObject)
lock (this.histogramMeasurements.LockObject)
{
this.longVal++;
this.doubleVal += number;
this.bucketCounts[i]++;
this.histogramMeasurements.CountVal++;
this.histogramMeasurements.SumVal += number;
this.histogramMeasurements.BucketCounts[i]++;
}
break;
@ -189,10 +223,10 @@ namespace OpenTelemetry.Metrics
case AggregationType.HistogramSumCount:
{
lock (this.lockObject)
lock (this.histogramMeasurements.LockObject)
{
this.longVal++;
this.doubleVal += number;
this.histogramMeasurements.CountVal++;
this.histogramMeasurements.SumVal += number;
}
break;
@ -314,22 +348,22 @@ namespace OpenTelemetry.Metrics
case AggregationType.Histogram:
{
lock (this.lockObject)
lock (this.histogramMeasurements.LockObject)
{
this.LongValue = this.longVal;
this.DoubleValue = this.doubleVal;
this.histogramMeasurements.Count = this.histogramMeasurements.CountVal;
this.histogramMeasurements.Sum = this.histogramMeasurements.SumVal;
if (outputDelta)
{
this.longVal = 0;
this.doubleVal = 0;
this.histogramMeasurements.CountVal = 0;
this.histogramMeasurements.SumVal = 0;
}
for (int i = 0; i < this.bucketCounts.Length; i++)
for (int i = 0; i < this.histogramMeasurements.BucketCounts.Length; i++)
{
this.BucketCounts[i] = this.bucketCounts[i];
this.histogramMeasurements.AggregatedBucketCounts[i] = this.histogramMeasurements.BucketCounts[i];
if (outputDelta)
{
this.bucketCounts[i] = 0;
this.histogramMeasurements.BucketCounts[i] = 0;
}
}
@ -341,14 +375,14 @@ namespace OpenTelemetry.Metrics
case AggregationType.HistogramSumCount:
{
lock (this.lockObject)
lock (this.histogramMeasurements.LockObject)
{
this.LongValue = this.longVal;
this.DoubleValue = this.doubleVal;
this.histogramMeasurements.Count = this.histogramMeasurements.CountVal;
this.histogramMeasurements.Sum = this.histogramMeasurements.SumVal;
if (outputDelta)
{
this.longVal = 0;
this.doubleVal = 0;
this.histogramMeasurements.CountVal = 0;
this.histogramMeasurements.SumVal = 0;
}
this.MetricPointStatus = MetricPointStatus.NoCollectPending;

View File

@ -100,8 +100,12 @@ namespace OpenTelemetry.Instrumentation.AspNetCore.Tests
Assert.Single(metricPoints);
var metricPoint = metricPoints[0];
Assert.Equal(1L, metricPoint.LongValue);
Assert.True(metricPoint.DoubleValue > 0);
var count = metricPoint.GetHistogramCount();
var sum = metricPoint.GetHistogramSum();
Assert.Equal(1L, count);
Assert.True(sum > 0);
/*
var bucket = metric.Buckets

View File

@ -159,8 +159,12 @@ namespace OpenTelemetry.Instrumentation.Http.Tests
Assert.Single(metricPoints);
var metricPoint = metricPoints[0];
Assert.Equal(1L, metricPoint.LongValue);
Assert.Equal(activity.Duration.TotalMilliseconds, metricPoint.DoubleValue);
var count = metricPoint.GetHistogramCount();
var sum = metricPoint.GetHistogramSum();
Assert.Equal(1L, count);
Assert.Equal(activity.Duration.TotalMilliseconds, sum);
var attributes = new KeyValuePair<string, object>[metricPoint.Tags.Count];
int i = 0;

View File

@ -49,10 +49,13 @@ namespace OpenTelemetry.Metrics.Tests
histogramPoint.Update(10000000);
histogramPoint.TakeSnapshot(true);
Assert.Equal(22, histogramPoint.LongValue);
for (int i = 0; i < histogramPoint.BucketCounts.Length; i++)
var count = histogramPoint.GetHistogramCount();
var bucketCounts = histogramPoint.GetBucketCounts();
Assert.Equal(22, count);
for (int i = 0; i < bucketCounts.Length; i++)
{
Assert.Equal(2, histogramPoint.BucketCounts[i]);
Assert.Equal(2, bucketCounts[i]);
}
}
@ -75,15 +78,19 @@ namespace OpenTelemetry.Metrics.Tests
histogramPoint.TakeSnapshot(true);
var count = histogramPoint.GetHistogramCount();
var sum = histogramPoint.GetHistogramSum();
var bucketCounts = histogramPoint.GetBucketCounts();
// Sum of all recordings
Assert.Equal(40, histogramPoint.DoubleValue);
Assert.Equal(40, sum);
// Count = # of recordings
Assert.Equal(7, histogramPoint.LongValue);
Assert.Equal(boundaries.Length + 1, histogramPoint.BucketCounts.Length);
Assert.Equal(5, histogramPoint.BucketCounts[0]);
Assert.Equal(2, histogramPoint.BucketCounts[1]);
Assert.Equal(0, histogramPoint.BucketCounts[2]);
Assert.Equal(7, count);
Assert.Equal(boundaries.Length + 1, bucketCounts.Length);
Assert.Equal(5, bucketCounts[0]);
Assert.Equal(2, bucketCounts[1]);
Assert.Equal(0, bucketCounts[2]);
}
[Fact]
@ -102,13 +109,17 @@ namespace OpenTelemetry.Metrics.Tests
histogramPoint.TakeSnapshot(true);
var count = histogramPoint.GetHistogramCount();
var sum = histogramPoint.GetHistogramSum();
// Sum of all recordings
Assert.Equal(40, histogramPoint.DoubleValue);
Assert.Equal(40, sum);
// Count = # of recordings
Assert.Equal(7, histogramPoint.LongValue);
Assert.Null(histogramPoint.BucketCounts);
Assert.Null(histogramPoint.ExplicitBounds);
Assert.Equal(7, count);
Assert.Throws<NotSupportedException>(() => histogramPoint.GetBucketCounts());
Assert.Throws<NotSupportedException>(() => histogramPoint.GetExplicitBounds());
}
}
}

View File

@ -388,15 +388,20 @@ namespace OpenTelemetry.Metrics.Tests
Assert.Single(metricPointsDefault);
var histogramPoint = metricPointsDefault[0];
Assert.Equal(40, histogramPoint.DoubleValue);
Assert.Equal(7, histogramPoint.LongValue);
Assert.Equal(Metric.DefaultHistogramBounds.Length + 1, histogramPoint.BucketCounts.Length);
Assert.Equal(2, histogramPoint.BucketCounts[0]);
Assert.Equal(1, histogramPoint.BucketCounts[1]);
Assert.Equal(2, histogramPoint.BucketCounts[2]);
Assert.Equal(2, histogramPoint.BucketCounts[3]);
Assert.Equal(0, histogramPoint.BucketCounts[4]);
Assert.Equal(0, histogramPoint.BucketCounts[5]);
var count = histogramPoint.GetHistogramCount();
var sum = histogramPoint.GetHistogramSum();
var bucketCounts = histogramPoint.GetBucketCounts();
var explicitBounds = histogramPoint.GetExplicitBounds();
Assert.Equal(40, sum);
Assert.Equal(7, count);
Assert.Equal(Metric.DefaultHistogramBounds.Length + 1, bucketCounts.Length);
Assert.Equal(2, bucketCounts[0]);
Assert.Equal(1, bucketCounts[1]);
Assert.Equal(2, bucketCounts[2]);
Assert.Equal(2, bucketCounts[3]);
Assert.Equal(0, bucketCounts[4]);
Assert.Equal(0, bucketCounts[5]);
List<MetricPoint> metricPointsCustom = new List<MetricPoint>();
foreach (ref var mp in metricCustom.GetMetricPoints())
@ -407,12 +412,17 @@ namespace OpenTelemetry.Metrics.Tests
Assert.Single(metricPointsCustom);
histogramPoint = metricPointsCustom[0];
Assert.Equal(40, histogramPoint.DoubleValue);
Assert.Equal(7, histogramPoint.LongValue);
Assert.Equal(boundaries.Length + 1, histogramPoint.BucketCounts.Length);
Assert.Equal(5, histogramPoint.BucketCounts[0]);
Assert.Equal(2, histogramPoint.BucketCounts[1]);
Assert.Equal(0, histogramPoint.BucketCounts[2]);
count = histogramPoint.GetHistogramCount();
sum = histogramPoint.GetHistogramSum();
bucketCounts = histogramPoint.GetBucketCounts();
explicitBounds = histogramPoint.GetExplicitBounds();
Assert.Equal(40, sum);
Assert.Equal(7, count);
Assert.Equal(boundaries.Length + 1, bucketCounts.Length);
Assert.Equal(5, bucketCounts[0]);
Assert.Equal(2, bucketCounts[1]);
Assert.Equal(0, bucketCounts[2]);
}
[Fact]