Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support UpDownCounter and ObservableUpDownCounter #3606

Merged
merged 19 commits into from
Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from 13 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
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,11 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
switch (metric.MetricType)
{
case MetricType.LongSum:
case MetricType.LongSumNonMonotonic:
{
var sum = new OtlpMetrics.Sum
{
IsMonotonic = true,
IsMonotonic = metric.MetricType == MetricType.LongSum,
AggregationTemporality = temporality,
};

Expand All @@ -169,10 +170,11 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
}

case MetricType.DoubleSum:
case MetricType.DoubleSumNonMonotonic:
{
var sum = new OtlpMetrics.Sum
{
IsMonotonic = true,
IsMonotonic = metric.MetricType == MetricType.DoubleSum,
AggregationTemporality = temporality,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal static partial class PrometheusSerializer
{
private static readonly string[] MetricTypes = new string[]
{
"untyped", "counter", "gauge", "summary", "histogram", "histogram", "histogram", "histogram", "untyped",
"untyped", "counter", "gauge", "summary", "histogram", "histogram", "histogram", "histogram", "gauge",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: it might be good add a comment here to explain why. (like UpDownCounters are exported as Prometheus Gauge etc.)

};

public static int WriteMetric(byte[] buffer, int cursor, Metric metric)
Expand Down
2 changes: 2 additions & 0 deletions src/OpenTelemetry/.publicApi/net462/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceColl
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder> configure) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Metrics.MetricType.LongSumNonMonotonic = 138 -> OpenTelemetry.Metrics.MetricType
OpenTelemetry.Metrics.MetricType.DoubleSumNonMonotonic = 141 -> OpenTelemetry.Metrics.MetricType
2 changes: 2 additions & 0 deletions src/OpenTelemetry/.publicApi/net6.0/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceColl
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder> configure) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Metrics.MetricType.LongSumNonMonotonic = 138 -> OpenTelemetry.Metrics.MetricType
OpenTelemetry.Metrics.MetricType.DoubleSumNonMonotonic = 141 -> OpenTelemetry.Metrics.MetricType
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceColl
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder> configure) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Metrics.MetricType.LongSumNonMonotonic = 138 -> OpenTelemetry.Metrics.MetricType
OpenTelemetry.Metrics.MetricType.DoubleSumNonMonotonic = 141 -> OpenTelemetry.Metrics.MetricType
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceColl
static Microsoft.Extensions.DependencyInjection.TracerProviderBuilderServiceCollectionExtensions.ConfigureOpenTelemetryTracing(this Microsoft.Extensions.DependencyInjection.IServiceCollection! services, System.Action<OpenTelemetry.Trace.TracerProviderBuilder!>! configure) -> Microsoft.Extensions.DependencyInjection.IServiceCollection!
~static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder> configure) -> OpenTelemetry.Metrics.MeterProviderBuilder
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.ConfigureResource(this OpenTelemetry.Trace.TracerProviderBuilder! tracerProviderBuilder, System.Action<OpenTelemetry.Resources.ResourceBuilder!>! configure) -> OpenTelemetry.Trace.TracerProviderBuilder!
OpenTelemetry.Metrics.MetricType.LongSumNonMonotonic = 138 -> OpenTelemetry.Metrics.MetricType
OpenTelemetry.Metrics.MetricType.DoubleSumNonMonotonic = 141 -> OpenTelemetry.Metrics.MetricType
3 changes: 3 additions & 0 deletions src/OpenTelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* Allows samplers the ability to modify tracestate if desired.
([#3610](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3610))

* Added support for `UpDownCounter` and `ObservableUpDownCounter` instruments.
([#3606](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3606))

## 1.4.0-alpha.2

Released 2022-Aug-18
Expand Down
28 changes: 28 additions & 0 deletions src/OpenTelemetry/Metrics/Metric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,34 @@ internal Metric(
aggType = AggregationType.DoubleSumIncomingCumulative;
this.MetricType = MetricType.DoubleSum;
}
else if (instrumentIdentity.InstrumentType == typeof(ObservableUpDownCounter<long>)
|| instrumentIdentity.InstrumentType == typeof(ObservableUpDownCounter<int>)
|| instrumentIdentity.InstrumentType == typeof(ObservableUpDownCounter<short>)
|| instrumentIdentity.InstrumentType == typeof(ObservableUpDownCounter<byte>))
{
aggType = AggregationType.LongSumIncomingCumulative;
this.MetricType = MetricType.LongSumNonMonotonic;
}
else if (instrumentIdentity.InstrumentType == typeof(UpDownCounter<long>)
|| instrumentIdentity.InstrumentType == typeof(UpDownCounter<int>)
|| instrumentIdentity.InstrumentType == typeof(UpDownCounter<short>)
|| instrumentIdentity.InstrumentType == typeof(UpDownCounter<byte>))
{
aggType = AggregationType.LongSumIncomingDelta;
this.MetricType = MetricType.LongSumNonMonotonic;
}
else if (instrumentIdentity.InstrumentType == typeof(UpDownCounter<double>)
|| instrumentIdentity.InstrumentType == typeof(UpDownCounter<float>))
{
aggType = AggregationType.DoubleSumIncomingDelta;
this.MetricType = MetricType.DoubleSumNonMonotonic;
}
else if (instrumentIdentity.InstrumentType == typeof(ObservableUpDownCounter<double>)
|| instrumentIdentity.InstrumentType == typeof(ObservableUpDownCounter<float>))
{
aggType = AggregationType.DoubleSumIncomingCumulative;
this.MetricType = MetricType.DoubleSumNonMonotonic;
}
else if (instrumentIdentity.InstrumentType == typeof(ObservableGauge<double>)
|| instrumentIdentity.InstrumentType == typeof(ObservableGauge<float>))
{
Expand Down
9 changes: 2 additions & 7 deletions src/OpenTelemetry/Metrics/MetricReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,8 @@ public abstract partial class MetricReader : IDisposable
// Temporatlity is not defined for gauges, so this does not really affect anything.
var type when type == typeof(ObservableGauge<>) => AggregationTemporality.Delta,

// With .NET 7 the OpenTelemetry .NET SDK will support UpDownCounters.
// These will be aggregated using Cumulative temporatlity.
// See:
// https://docs.microsoft.com/dotnet/api/system.diagnostics.metrics.updowncounter-1
// https://docs.microsoft.com/dotnet/api/system.diagnostics.metrics.observableupdowncounter-1
// var type when type == typeof(UpDownCounter<>) => AggregationTemporality.Cumulative,
// var type when type == typeof(ObservableUpDownCounter<>) => AggregationTemporality.Cumulative,
var type when type == typeof(UpDownCounter<>) => AggregationTemporality.Cumulative,
var type when type == typeof(ObservableUpDownCounter<>) => AggregationTemporality.Cumulative,

// TODO: Consider logging here because we should not fall through to this case.
_ => AggregationTemporality.Delta,
Expand Down
12 changes: 11 additions & 1 deletion src/OpenTelemetry/Metrics/MetricType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public enum MetricType : byte
0x50: HistogramWithMinMax (reserved)
0x60: ExponentialHistogram (reserved)
0x70: ExponentialHistogramWithMinMax (reserved)
0x80: Reserved
0x80: SumNonMonotonic
cijothomas marked this conversation as resolved.
Show resolved Hide resolved

Point kind:
0x04: I1 (signed 1-byte integer)
Expand Down Expand Up @@ -69,5 +69,15 @@ public enum MetricType : byte
/// Histogram.
/// </summary>
Histogram = 0x40,

/// <summary>
/// Non-monotonic Sum of Long type.
/// </summary>
LongSumNonMonotonic = 0x8a,

/// <summary>
/// Non-monotonic Sum of Double type.
/// </summary>
DoubleSumNonMonotonic = 0x8d,
}
}
3 changes: 2 additions & 1 deletion src/OpenTelemetry/Metrics/MetricTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static class MetricTypeExtensions
internal const MetricType METRIC_TYPE_GAUGE = (MetricType)0x20;
/* internal const byte METRIC_TYPE_SUMMARY = 0x30; // not used */
internal const MetricType METRIC_TYPE_HISTOGRAM = (MetricType)0x40;
internal const MetricType METRIC_TYPE_SUM_NON_MONOTONIC = (MetricType)0x80;
reyang marked this conversation as resolved.
Show resolved Hide resolved

internal const MetricType POINT_KIND_MASK = (MetricType)0x0f;

Expand All @@ -47,7 +48,7 @@ public static class MetricTypeExtensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsSum(this MetricType self)
{
return (self & METRIC_TYPE_MASK) == METRIC_TYPE_SUM;
return (self & METRIC_TYPE_MASK) == METRIC_TYPE_SUM || (self & METRIC_TYPE_MASK) == METRIC_TYPE_SUM_NON_MONOTONIC;
reyang marked this conversation as resolved.
Show resolved Hide resolved
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,12 @@ public void TestGaugeToOtlpMetric(string name, string description, string unit,
}

[Theory]
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Cumulative, true)]
[InlineData("test_counter", null, null, null, 123.45, MetricReaderTemporalityPreference.Cumulative, true)]
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, true)]
[InlineData("test_counter", "description", "unit", 123L, null, MetricReaderTemporalityPreference.Cumulative, true)]
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, true, "key1", "value1", "key2", 123)]
public void TestCounterToOtlpMetric(string name, string description, string unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool isMonotonic, params object[] keysValues)
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData("test_counter", null, null, null, 123.45, MetricReaderTemporalityPreference.Cumulative)]
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta)]
[InlineData("test_counter", "description", "unit", 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, "key1", "value1", "key2", 123)]
public void TestCounterToOtlpMetric(string name, string description, string unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, params object[] keysValues)
{
var metrics = new List<Metric>();

Expand Down Expand Up @@ -324,7 +324,7 @@ public void TestCounterToOtlpMetric(string name, string description, string unit
Assert.Null(actual.ExponentialHistogram);
Assert.Null(actual.Summary);

Assert.Equal(isMonotonic, actual.Sum.IsMonotonic);
Assert.True(actual.Sum.IsMonotonic);

var otlpAggregationTemporality = aggregationTemporality == MetricReaderTemporalityPreference.Cumulative
? OtlpMetrics.AggregationTemporality.Cumulative
Expand Down Expand Up @@ -359,6 +359,95 @@ public void TestCounterToOtlpMetric(string name, string description, string unit
Assert.Empty(dataPoint.Exemplars);
}

[Theory]
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData("test_counter", null, null, null, 123.45, MetricReaderTemporalityPreference.Cumulative)]
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta)]
[InlineData("test_counter", "description", "unit", 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData("test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, "key1", "value1", "key2", 123)]
public void TestUpDownCounterToOtlpMetric(string name, string description, string unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, params object[] keysValues)
{
var metrics = new List<Metric>();

using var meter = new Meter(Utils.GetCurrentMethodName());
using var provider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.AddInMemoryExporter(metrics, metricReaderOptions =>
{
metricReaderOptions.TemporalityPreference = aggregationTemporality;
})
.Build();

var attributes = ToAttributes(keysValues).ToArray();
if (longValue.HasValue)
{
var counter = meter.CreateUpDownCounter<long>(name, unit, description);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: var counterUpDownCounter

counter.Add(longValue.Value, attributes);
}
else
{
var counter = meter.CreateUpDownCounter<double>(name, unit, description);
counter.Add(doubleValue.Value, attributes);
}

provider.ForceFlush();

var batch = new Batch<Metric>(metrics.ToArray(), metrics.Count);

var request = new OtlpCollector.ExportMetricsServiceRequest();
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch);

var resourceMetric = request.ResourceMetrics.Single();
var scopeMetrics = resourceMetric.ScopeMetrics.Single();
var actual = scopeMetrics.Metrics.Single();

Assert.Equal(name, actual.Name);
Assert.Equal(description ?? string.Empty, actual.Description);
Assert.Equal(unit ?? string.Empty, actual.Unit);

Assert.Equal(OtlpMetrics.Metric.DataOneofCase.Sum, actual.DataCase);

Assert.Null(actual.Gauge);
Assert.NotNull(actual.Sum);
Assert.Null(actual.Histogram);
Assert.Null(actual.ExponentialHistogram);
Assert.Null(actual.Summary);

Assert.False(actual.Sum.IsMonotonic);

var otlpAggregationTemporality = aggregationTemporality == MetricReaderTemporalityPreference.Cumulative
? OtlpMetrics.AggregationTemporality.Cumulative
: OtlpMetrics.AggregationTemporality.Cumulative;
Assert.Equal(otlpAggregationTemporality, actual.Sum.AggregationTemporality);

Assert.Single(actual.Sum.DataPoints);
var dataPoint = actual.Sum.DataPoints.First();
Assert.True(dataPoint.StartTimeUnixNano > 0);
Assert.True(dataPoint.TimeUnixNano > 0);

if (longValue.HasValue)
{
Assert.Equal(OtlpMetrics.NumberDataPoint.ValueOneofCase.AsInt, dataPoint.ValueCase);
Assert.Equal(longValue, dataPoint.AsInt);
}
else
{
Assert.Equal(OtlpMetrics.NumberDataPoint.ValueOneofCase.AsDouble, dataPoint.ValueCase);
Assert.Equal(doubleValue, dataPoint.AsDouble);
}

if (attributes.Length > 0)
{
OtlpTestHelpers.AssertOtlpAttributes(attributes, dataPoint.Attributes);
}
else
{
Assert.Empty(dataPoint.Attributes);
}

Assert.Empty(dataPoint.Exemplars);
}

[Theory]
[InlineData("test_histogram", null, null, 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData("test_histogram", null, null, null, 123.45, MetricReaderTemporalityPreference.Cumulative)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,33 @@ public void SumDoubleInfinites()
Encoding.UTF8.GetString(buffer, 0, cursor));
}

[Fact]
public void SumNonMonotonicDouble()
{
var buffer = new byte[85000];
var metrics = new List<Metric>();

using var meter = new Meter(Utils.GetCurrentMethodName());
using var provider = Sdk.CreateMeterProviderBuilder()
.AddMeter(meter.Name)
.AddInMemoryExporter(metrics)
.Build();

var counter = meter.CreateUpDownCounter<double>("test_updown_counter");
counter.Add(10);
counter.Add(-5);
alanwest marked this conversation as resolved.
Show resolved Hide resolved

provider.ForceFlush();

var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]);
Assert.Matches(
("^"
+ "# TYPE test_updown_counter gauge\n"
+ "test_updown_counter 5 \\d+\n"
+ "$").Replace('\'', '"'),
Encoding.UTF8.GetString(buffer, 0, cursor));
}

[Fact]
public void HistogramZeroDimension()
{
Expand Down
Loading