Support UpDownCounter and ObservableUpDownCounter (#3606)
This commit is contained in:
parent
a37198c6d0
commit
c2f5e80b0d
|
|
@ -143,10 +143,11 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation
|
|||
switch (metric.MetricType)
|
||||
{
|
||||
case MetricType.LongSum:
|
||||
case MetricType.LongSumNonMonotonic:
|
||||
{
|
||||
var sum = new OtlpMetrics.Sum
|
||||
{
|
||||
IsMonotonic = true,
|
||||
IsMonotonic = metric.MetricType == MetricType.LongSum,
|
||||
AggregationTemporality = temporality,
|
||||
};
|
||||
|
||||
|
|
@ -169,10 +170,11 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation
|
|||
}
|
||||
|
||||
case MetricType.DoubleSum:
|
||||
case MetricType.DoubleSumNonMonotonic:
|
||||
{
|
||||
var sum = new OtlpMetrics.Sum
|
||||
{
|
||||
IsMonotonic = true,
|
||||
IsMonotonic = metric.MetricType == MetricType.DoubleSum,
|
||||
AggregationTemporality = temporality,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace OpenTelemetry.Exporter.Prometheus
|
|||
{
|
||||
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",
|
||||
};
|
||||
|
||||
public static int WriteMetric(byte[] buffer, int cursor, Metric metric)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -67,6 +67,34 @@ namespace OpenTelemetry.Metrics
|
|||
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>))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,13 +44,8 @@ namespace OpenTelemetry.Metrics
|
|||
// 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,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace OpenTelemetry.Metrics
|
|||
0x50: HistogramWithMinMax (reserved)
|
||||
0x60: ExponentialHistogram (reserved)
|
||||
0x70: ExponentialHistogramWithMinMax (reserved)
|
||||
0x80: Reserved
|
||||
0x80: SumNonMonotonic
|
||||
|
||||
Point kind:
|
||||
0x04: I1 (signed 1-byte integer)
|
||||
|
|
@ -69,5 +69,15 @@ namespace OpenTelemetry.Metrics
|
|||
/// Histogram.
|
||||
/// </summary>
|
||||
Histogram = 0x40,
|
||||
|
||||
/// <summary>
|
||||
/// Non-monotonic Sum of Long type.
|
||||
/// </summary>
|
||||
LongSumNonMonotonic = 0x8a,
|
||||
|
||||
/// <summary>
|
||||
/// Non-monotonic Sum of Double type.
|
||||
/// </summary>
|
||||
DoubleSumNonMonotonic = 0x8d,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,11 @@ namespace OpenTelemetry.Metrics
|
|||
|
||||
internal const MetricType METRIC_TYPE_MASK = (MetricType)0xf0;
|
||||
|
||||
internal const MetricType METRIC_TYPE_SUM = (MetricType)0x10;
|
||||
internal const MetricType METRIC_TYPE_MONOTONIC_SUM = (MetricType)0x10;
|
||||
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_NON_MONOTONIC_SUM = (MetricType)0x80;
|
||||
|
||||
internal const MetricType POINT_KIND_MASK = (MetricType)0x0f;
|
||||
|
||||
|
|
@ -47,7 +48,8 @@ namespace OpenTelemetry.Metrics
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsSum(this MetricType self)
|
||||
{
|
||||
return (self & METRIC_TYPE_MASK) == METRIC_TYPE_SUM;
|
||||
var type = self & METRIC_TYPE_MASK;
|
||||
return type == METRIC_TYPE_MONOTONIC_SUM || type == METRIC_TYPE_NON_MONOTONIC_SUM;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
|
|||
|
|
@ -271,12 +271,12 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests
|
|||
}
|
||||
|
||||
[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>();
|
||||
|
||||
|
|
@ -324,7 +324,7 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests
|
|||
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
|
||||
|
|
@ -359,6 +359,95 @@ namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests
|
|||
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);
|
||||
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)]
|
||||
|
|
|
|||
|
|
@ -187,6 +187,33 @@ namespace OpenTelemetry.Exporter.Prometheus.Tests
|
|||
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(-11);
|
||||
|
||||
provider.ForceFlush();
|
||||
|
||||
var cursor = PrometheusSerializer.WriteMetric(buffer, 0, metrics[0]);
|
||||
Assert.Matches(
|
||||
("^"
|
||||
+ "# TYPE test_updown_counter gauge\n"
|
||||
+ "test_updown_counter -1 \\d+\n"
|
||||
+ "$").Replace('\'', '"'),
|
||||
Encoding.UTF8.GetString(buffer, 0, cursor));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HistogramZeroDimension()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -586,7 +586,7 @@ namespace OpenTelemetry.Metrics.Tests
|
|||
exportedItems.Clear();
|
||||
|
||||
#if NETFRAMEWORK
|
||||
Thread.Sleep(5000); // Compensates for low resolution timing in netfx.
|
||||
Thread.Sleep(10); // Compensates for low resolution timing in netfx.
|
||||
#endif
|
||||
|
||||
counterLong.Add(10);
|
||||
|
|
@ -864,6 +864,224 @@ namespace OpenTelemetry.Metrics.Tests
|
|||
Assert.Equal(30, metricPoint1.GetSumLong());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void UpDownCounterAggregationTest(bool exportDelta)
|
||||
{
|
||||
DateTime testStartTime = DateTime.UtcNow;
|
||||
|
||||
var exportedItems = new List<Metric>();
|
||||
|
||||
using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}");
|
||||
var counterLong = meter.CreateUpDownCounter<long>("mycounter");
|
||||
using var meterProvider = Sdk.CreateMeterProviderBuilder()
|
||||
.AddMeter(meter.Name)
|
||||
.AddInMemoryExporter(exportedItems, metricReaderOptions =>
|
||||
{
|
||||
metricReaderOptions.TemporalityPreference = exportDelta ? MetricReaderTemporalityPreference.Delta : MetricReaderTemporalityPreference.Cumulative;
|
||||
})
|
||||
.Build();
|
||||
|
||||
counterLong.Add(10);
|
||||
counterLong.Add(-5);
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
long sumReceived = GetLongSum(exportedItems);
|
||||
Assert.Equal(5, sumReceived);
|
||||
|
||||
var metricPoint = GetFirstMetricPoint(exportedItems);
|
||||
Assert.NotNull(metricPoint);
|
||||
Assert.True(metricPoint.Value.StartTime >= testStartTime);
|
||||
Assert.True(metricPoint.Value.EndTime != default);
|
||||
|
||||
DateTimeOffset firstRunStartTime = metricPoint.Value.StartTime;
|
||||
DateTimeOffset firstRunEndTime = metricPoint.Value.EndTime;
|
||||
|
||||
exportedItems.Clear();
|
||||
|
||||
#if NETFRAMEWORK
|
||||
Thread.Sleep(10); // Compensates for low resolution timing in netfx.
|
||||
#endif
|
||||
|
||||
counterLong.Add(10);
|
||||
counterLong.Add(-5);
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
sumReceived = GetLongSum(exportedItems);
|
||||
|
||||
// Same for both cumulative and delta. MetricReaderTemporalityPreference.Delta implies cumulative for UpDownCounters.
|
||||
Assert.Equal(10, sumReceived);
|
||||
|
||||
metricPoint = GetFirstMetricPoint(exportedItems);
|
||||
Assert.NotNull(metricPoint);
|
||||
Assert.True(metricPoint.Value.StartTime >= testStartTime);
|
||||
Assert.True(metricPoint.Value.EndTime != default);
|
||||
|
||||
// Same for both cumulative and delta. MetricReaderTemporalityPreference.Delta implies cumulative for UpDownCounters.
|
||||
Assert.Equal(firstRunStartTime, metricPoint.Value.StartTime);
|
||||
|
||||
Assert.True(metricPoint.Value.EndTime > firstRunEndTime);
|
||||
|
||||
exportedItems.Clear();
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
sumReceived = GetLongSum(exportedItems);
|
||||
|
||||
// Same for both cumulative and delta. MetricReaderTemporalityPreference.Delta implies cumulative for UpDownCounters.
|
||||
Assert.Equal(10, sumReceived);
|
||||
|
||||
exportedItems.Clear();
|
||||
counterLong.Add(40);
|
||||
counterLong.Add(-20);
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
sumReceived = GetLongSum(exportedItems);
|
||||
|
||||
// Same for both cumulative and delta. MetricReaderTemporalityPreference.Delta implies cumulative for UpDownCounters.
|
||||
Assert.Equal(30, sumReceived);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void ObservableUpDownCounterAggregationTest(bool exportDelta)
|
||||
{
|
||||
var exportedItems = new List<Metric>();
|
||||
|
||||
using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}");
|
||||
int i = 1;
|
||||
var counterLong = meter.CreateObservableUpDownCounter(
|
||||
"observable-counter",
|
||||
() =>
|
||||
{
|
||||
return new List<Measurement<long>>()
|
||||
{
|
||||
new Measurement<long>(i++ * 10),
|
||||
};
|
||||
});
|
||||
|
||||
using var meterProvider = Sdk.CreateMeterProviderBuilder()
|
||||
.AddMeter(meter.Name)
|
||||
.AddInMemoryExporter(exportedItems, metricReaderOptions =>
|
||||
{
|
||||
metricReaderOptions.TemporalityPreference = exportDelta ? MetricReaderTemporalityPreference.Delta : MetricReaderTemporalityPreference.Cumulative;
|
||||
})
|
||||
.Build();
|
||||
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
long sumReceived = GetLongSum(exportedItems);
|
||||
Assert.Equal(10, sumReceived);
|
||||
|
||||
exportedItems.Clear();
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
sumReceived = GetLongSum(exportedItems);
|
||||
|
||||
// Same for both cumulative and delta. MetricReaderTemporalityPreference.Delta implies cumulative for UpDownCounters.
|
||||
Assert.Equal(20, sumReceived);
|
||||
|
||||
exportedItems.Clear();
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
sumReceived = GetLongSum(exportedItems);
|
||||
|
||||
// Same for both cumulative and delta. MetricReaderTemporalityPreference.Delta implies cumulative for UpDownCounters.
|
||||
Assert.Equal(30, sumReceived);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public void ObservableUpDownCounterWithTagsAggregationTest(bool exportDelta)
|
||||
{
|
||||
var exportedItems = new List<Metric>();
|
||||
var tags1 = new List<KeyValuePair<string, object>>
|
||||
{
|
||||
new("statusCode", 200),
|
||||
new("verb", "get"),
|
||||
};
|
||||
|
||||
var tags2 = new List<KeyValuePair<string, object>>
|
||||
{
|
||||
new("statusCode", 200),
|
||||
new("verb", "post"),
|
||||
};
|
||||
|
||||
var tags3 = new List<KeyValuePair<string, object>>
|
||||
{
|
||||
new("statusCode", 500),
|
||||
new("verb", "get"),
|
||||
};
|
||||
|
||||
using var meter = new Meter($"{Utils.GetCurrentMethodName()}.{exportDelta}");
|
||||
var counterLong = meter.CreateObservableUpDownCounter(
|
||||
"observable-counter",
|
||||
() =>
|
||||
{
|
||||
return new List<Measurement<long>>()
|
||||
{
|
||||
new Measurement<long>(10, tags1),
|
||||
new Measurement<long>(10, tags2),
|
||||
new Measurement<long>(10, tags3),
|
||||
};
|
||||
});
|
||||
|
||||
using var meterProvider = Sdk.CreateMeterProviderBuilder()
|
||||
.AddMeter(meter.Name)
|
||||
.AddInMemoryExporter(exportedItems, metricReaderOptions =>
|
||||
{
|
||||
metricReaderOptions.TemporalityPreference = exportDelta ? MetricReaderTemporalityPreference.Delta : MetricReaderTemporalityPreference.Cumulative;
|
||||
})
|
||||
.Build();
|
||||
|
||||
// Export 1
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
Assert.Single(exportedItems);
|
||||
var metric = exportedItems[0];
|
||||
Assert.Equal("observable-counter", metric.Name);
|
||||
List<MetricPoint> metricPoints = new List<MetricPoint>();
|
||||
foreach (ref readonly var mp in metric.GetMetricPoints())
|
||||
{
|
||||
metricPoints.Add(mp);
|
||||
}
|
||||
|
||||
Assert.Equal(3, metricPoints.Count);
|
||||
|
||||
var metricPoint1 = metricPoints[0];
|
||||
Assert.Equal(10, metricPoint1.GetSumLong());
|
||||
ValidateMetricPointTags(tags1, metricPoint1.Tags);
|
||||
|
||||
var metricPoint2 = metricPoints[1];
|
||||
Assert.Equal(10, metricPoint2.GetSumLong());
|
||||
ValidateMetricPointTags(tags2, metricPoint2.Tags);
|
||||
|
||||
var metricPoint3 = metricPoints[2];
|
||||
Assert.Equal(10, metricPoint3.GetSumLong());
|
||||
ValidateMetricPointTags(tags3, metricPoint3.Tags);
|
||||
|
||||
// Export 2
|
||||
exportedItems.Clear();
|
||||
meterProvider.ForceFlush(MaxTimeToAllowForFlush);
|
||||
Assert.Single(exportedItems);
|
||||
metric = exportedItems[0];
|
||||
Assert.Equal("observable-counter", metric.Name);
|
||||
metricPoints.Clear();
|
||||
foreach (ref readonly var mp in metric.GetMetricPoints())
|
||||
{
|
||||
metricPoints.Add(mp);
|
||||
}
|
||||
|
||||
Assert.Equal(3, metricPoints.Count);
|
||||
|
||||
// Same for both cumulative and delta. MetricReaderTemporalityPreference.Delta implies cumulative for UpDownCounters.
|
||||
metricPoint1 = metricPoints[0];
|
||||
Assert.Equal(10, metricPoint1.GetSumLong());
|
||||
ValidateMetricPointTags(tags1, metricPoint1.Tags);
|
||||
|
||||
metricPoint2 = metricPoints[1];
|
||||
Assert.Equal(10, metricPoint2.GetSumLong());
|
||||
ValidateMetricPointTags(tags2, metricPoint2.Tags);
|
||||
|
||||
metricPoint3 = metricPoints[2];
|
||||
Assert.Equal(10, metricPoint3.GetSumLong());
|
||||
ValidateMetricPointTags(tags3, metricPoint3.Tags);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
|
|
|
|||
Loading…
Reference in New Issue