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

Remove meters from storage list when removed and handle NoRecordedValue flag when removing meters #5997

Closed
Closed
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Added feature flag OTEL_DOTNET_EXPERIMENTAL_OTLP_METRICS_EMIT_NO_RECO…
…RDED_VALUE to only emil no recorded value data points as a opt-in feature
stonkie committed Nov 29, 2024
commit 8ab84afe71e299fda0827e7f847a6b4d34a01c53
Original file line number Diff line number Diff line change
@@ -19,6 +19,8 @@ internal sealed class ExperimentalOptions

public const string OtlpUseCustomSerializer = "OTEL_DOTNET_EXPERIMENTAL_USE_CUSTOM_PROTOBUF_SERIALIZER";

public const string EmitNoRecordedValueNeededDataPointsEnvVar = "OTEL_DOTNET_EXPERIMENTAL_OTLP_METRICS_EMIT_NO_RECORDED_VALUE";

public ExperimentalOptions()
: this(new ConfigurationBuilder().AddEnvironmentVariables().Build())
{
@@ -36,6 +38,11 @@ public ExperimentalOptions(IConfiguration configuration)
this.UseCustomProtobufSerializer = useCustomSerializer;
}

if (configuration.TryGetBoolValue(OpenTelemetryProtocolExporterEventSource.Log, EmitNoRecordedValueNeededDataPointsEnvVar, out var emitNoRecordedValueNeededDataPoints))
{
this.EmitNoRecordedValueNeededDataPoints = emitNoRecordedValueNeededDataPoints;
}

if (configuration.TryGetStringValue(OtlpRetryEnvVar, out var retryPolicy) && retryPolicy != null)
{
if (retryPolicy.Equals("in_memory", StringComparison.OrdinalIgnoreCase))
@@ -90,4 +97,10 @@ public ExperimentalOptions(IConfiguration configuration)
/// Gets a value indicating whether custom serializer should be used for OTLP export.
/// </summary>
public bool UseCustomProtobufSerializer { get; }

/// <summary>
/// Gets a value indicating whether the NoRecordedValue measurement should be sent when metrics are removed,
/// e.g when disposing a Meter.
/// </summary>
public bool EmitNoRecordedValueNeededDataPoints { get; }
}
Original file line number Diff line number Diff line change
@@ -24,7 +24,8 @@ internal static class MetricItemExtensions
internal static void AddMetrics(
this OtlpCollector.ExportMetricsServiceRequest request,
OtlpResource.Resource processResource,
in Batch<Metric> metrics)
in Batch<Metric> metrics,
bool experimentalEmitNoRecordedValueNeededDataPoints = false)
{
var metricsByLibrary = new Dictionary<string, ScopeMetrics>();
var resourceMetrics = new ResourceMetrics
@@ -35,7 +36,7 @@ internal static void AddMetrics(

foreach (var metric in metrics)
{
var otlpMetric = metric.ToOtlpMetric();
var otlpMetric = metric.ToOtlpMetric(experimentalEmitNoRecordedValueNeededDataPoints);

// TODO: Replace null check with exception handling.
if (otlpMetric == null)
@@ -109,7 +110,7 @@ internal static ScopeMetrics GetMetricListFromPool(string name, string version,
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)
internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric, bool experimentalEmitNoRecordedValueNeededDataPoints)
{
var otlpMetric = new OtlpMetrics.Metric
{
@@ -170,7 +171,7 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)

sum.DataPoints.Add(dataPoint);

if (metric.NoRecordedValueNeeded)
if (experimentalEmitNoRecordedValueNeededDataPoints && metric.NoRecordedValueNeeded)
{
sum.DataPoints.Add(CreateNoRecordedValueNumberDataPoint(dataPoint.TimeUnixNano, metricPoint.Tags));
}
@@ -212,7 +213,7 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)

sum.DataPoints.Add(dataPoint);

if (metric.NoRecordedValueNeeded)
if (experimentalEmitNoRecordedValueNeededDataPoints && metric.NoRecordedValueNeeded)
{
sum.DataPoints.Add(CreateNoRecordedValueNumberDataPoint(dataPoint.TimeUnixNano, metricPoint.Tags));
}
@@ -248,7 +249,7 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)

gauge.DataPoints.Add(dataPoint);

if (metric.NoRecordedValueNeeded)
if (experimentalEmitNoRecordedValueNeededDataPoints && metric.NoRecordedValueNeeded)
{
gauge.DataPoints.Add(CreateNoRecordedValueNumberDataPoint(dataPoint.TimeUnixNano, metricPoint.Tags));
}
@@ -284,7 +285,7 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)

gauge.DataPoints.Add(dataPoint);

if (metric.NoRecordedValueNeeded)
if (experimentalEmitNoRecordedValueNeededDataPoints && metric.NoRecordedValueNeeded)
{
gauge.DataPoints.Add(CreateNoRecordedValueNumberDataPoint(dataPoint.TimeUnixNano, metricPoint.Tags));
}
@@ -339,7 +340,7 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)

histogram.DataPoints.Add(dataPoint);

if (metric.NoRecordedValueNeeded)
if (experimentalEmitNoRecordedValueNeededDataPoints && metric.NoRecordedValueNeeded)
{
histogram.DataPoints.Add(CreateNoRecordedValueHistogramDataPoint(dataPoint.TimeUnixNano, metricPoint.Tags));
}
@@ -396,7 +397,7 @@ internal static OtlpMetrics.Metric ToOtlpMetric(this Metric metric)

histogram.DataPoints.Add(dataPoint);

if (metric.NoRecordedValueNeeded)
if (experimentalEmitNoRecordedValueNeededDataPoints && metric.NoRecordedValueNeeded)
{
histogram.DataPoints.Add(CreateNoRecordedValueExponentialHistogramDataPoint(dataPoint.TimeUnixNano, metricPoint.Tags));
}
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ public class OtlpMetricExporter : BaseExporter<Metric>
{
private readonly OtlpExporterTransmissionHandler<OtlpCollector.ExportMetricsServiceRequest> transmissionHandler;

private readonly bool emitNoRecordedValueNeededDataPoints;
private OtlpResource.Resource? processResource;

/// <summary>
@@ -44,6 +45,7 @@ internal OtlpMetricExporter(
Debug.Assert(experimentalOptions != null, "experimentalOptions was null");

this.transmissionHandler = transmissionHandler ?? exporterOptions!.GetMetricsExportTransmissionHandler(experimentalOptions!);
this.emitNoRecordedValueNeededDataPoints = experimentalOptions!.EmitNoRecordedValueNeededDataPoints;
}

internal OtlpResource.Resource ProcessResource => this.processResource ??= this.ParentProvider.GetResource().ToOtlpResource();
@@ -58,7 +60,7 @@ public override ExportResult Export(in Batch<Metric> metrics)

try
{
request.AddMetrics(this.ProcessResource, metrics);
request.AddMetrics(this.ProcessResource, metrics, this.emitNoRecordedValueNeededDataPoints);

if (!this.transmissionHandler.TrySubmitRequest(request))
{
Original file line number Diff line number Diff line change
@@ -248,7 +248,8 @@ public void ToOtlpResourceMetricsTest(bool useCustomSerializer, bool includeServ
[InlineData(false, "test_gauge", null, null, null, 123.45, true)]
[InlineData(false, "test_gauge", "description", "unit", 123L, null)]
[InlineData(false, "test_gauge", "description", "unit", 123L, null, false, true)]
public void TestGaugeToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, bool enableExemplars = false, bool disposeMeterEarly = false)
[InlineData(false, "test_gauge", "description", "unit", 123L, null, false, true, true)]
public void TestGaugeToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, bool enableExemplars = false, bool disposeMeterEarly = false, bool experimentalEmitNoRecordedValue = false)
{
var metrics = new List<Metric>();

@@ -288,7 +289,7 @@ public void TestGaugeToOtlpMetric(bool useCustomSerializer, string name, string?
}
else
{
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch);
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch, experimentalEmitNoRecordedValue);
}

var resourceMetric = request.ResourceMetrics.Single();
@@ -307,7 +308,7 @@ public void TestGaugeToOtlpMetric(bool useCustomSerializer, string name, string?
Assert.Null(actual.ExponentialHistogram);
Assert.Null(actual.Summary);

if (!disposeMeterEarly)
if (!disposeMeterEarly || !experimentalEmitNoRecordedValue)
{
Assert.Single(actual.Gauge.DataPoints);
}
@@ -380,7 +381,8 @@ public void TestGaugeToOtlpMetric(bool useCustomSerializer, string name, string?
[InlineData(false, "test_counter", "description", "unit", 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData(false, "test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, true)]
[InlineData(false, "test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, false, false, true)]
public void TestCounterToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool enableKeyValues = false, bool enableExemplars = false, bool disposeMeterEarly = false)
[InlineData(false, "test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, false, false, true, true)]
public void TestCounterToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool enableKeyValues = false, bool enableExemplars = false, bool disposeMeterEarly = false, bool experimentalEmitNoRecordedValue = false)
{
var metrics = new List<Metric>();

@@ -423,7 +425,7 @@ public void TestCounterToOtlpMetric(bool useCustomSerializer, string name, strin
}
else
{
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch);
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch, experimentalEmitNoRecordedValue);
}

var resourceMetric = request.ResourceMetrics.Single();
@@ -449,7 +451,7 @@ public void TestCounterToOtlpMetric(bool useCustomSerializer, string name, strin
: OtlpMetrics.AggregationTemporality.Delta;
Assert.Equal(otlpAggregationTemporality, actual.Sum.AggregationTemporality);

if (!disposeMeterEarly)
if (!disposeMeterEarly || !experimentalEmitNoRecordedValue)
{
Assert.Single(actual.Sum.DataPoints);
}
@@ -533,7 +535,8 @@ public void TestCounterToOtlpMetric(bool useCustomSerializer, string name, strin
[InlineData(false, "test_counter", "description", "unit", 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData(false, "test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, true)]
[InlineData(false, "test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, false, false, true)]
public void TestUpDownCounterToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool enableKeyValues = false, bool enableExemplars = false, bool disposeMeterEarly = false)
[InlineData(false, "test_counter", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, false, false, true, true)]
public void TestUpDownCounterToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool enableKeyValues = false, bool enableExemplars = false, bool disposeMeterEarly = false, bool experimentalEmitNoRecordedValue = false)
{
var metrics = new List<Metric>();

@@ -575,7 +578,7 @@ public void TestUpDownCounterToOtlpMetric(bool useCustomSerializer, string name,
}
else
{
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch);
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch, experimentalEmitNoRecordedValue);
}

var resourceMetric = request.ResourceMetrics.Single();
@@ -601,7 +604,7 @@ public void TestUpDownCounterToOtlpMetric(bool useCustomSerializer, string name,
: OtlpMetrics.AggregationTemporality.Cumulative;
Assert.Equal(otlpAggregationTemporality, actual.Sum.AggregationTemporality);

if (!disposeMeterEarly)
if (!disposeMeterEarly || !experimentalEmitNoRecordedValue)
{
Assert.Single(actual.Sum.DataPoints);
}
@@ -685,7 +688,8 @@ public void TestUpDownCounterToOtlpMetric(bool useCustomSerializer, string name,
[InlineData(false, "test_histogram", "description", "unit", 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData(false, "test_histogram", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, true)]
[InlineData(false, "test_histogram", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, false, false, true)]
public void TestExponentialHistogramToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool enableKeyValues = false, bool enableExemplars = false, bool disposeMeterEarly = false)
[InlineData(false, "test_histogram", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, false, false, true, true)]
public void TestExponentialHistogramToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool enableKeyValues = false, bool enableExemplars = false, bool disposeMeterEarly = false, bool experimentalEmitNoRecordedValue = false)
{
var metrics = new List<Metric>();

@@ -733,7 +737,7 @@ public void TestExponentialHistogramToOtlpMetric(bool useCustomSerializer, strin
}
else
{
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch);
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch, experimentalEmitNoRecordedValue);
}

var resourceMetric = request.ResourceMetrics.Single();
@@ -757,7 +761,7 @@ public void TestExponentialHistogramToOtlpMetric(bool useCustomSerializer, strin
: OtlpMetrics.AggregationTemporality.Delta;
Assert.Equal(otlpAggregationTemporality, actual.ExponentialHistogram.AggregationTemporality);

if (!disposeMeterEarly)
if (!disposeMeterEarly || !experimentalEmitNoRecordedValue)
{
Assert.Single(actual.ExponentialHistogram.DataPoints);
}
@@ -881,7 +885,8 @@ public void TestExponentialHistogramToOtlpMetric(bool useCustomSerializer, strin
[InlineData(false, "test_histogram", "description", "unit", 123L, null, MetricReaderTemporalityPreference.Cumulative)]
[InlineData(false, "test_histogram", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, true)]
[InlineData(false, "test_histogram", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, false, false, true)]
public void TestHistogramToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool enableKeyValues = false, bool enableExemplars = false, bool disposeMeterEarly = false)
[InlineData(false, "test_histogram", null, null, 123L, null, MetricReaderTemporalityPreference.Delta, false, false, true, true)]
public void TestHistogramToOtlpMetric(bool useCustomSerializer, string name, string? description, string? unit, long? longValue, double? doubleValue, MetricReaderTemporalityPreference aggregationTemporality, bool enableKeyValues = false, bool enableExemplars = false, bool disposeMeterEarly = false, bool experimentalEmitNoRecordedValue = false)
{
var metrics = new List<Metric>();

@@ -924,7 +929,7 @@ public void TestHistogramToOtlpMetric(bool useCustomSerializer, string name, str
}
else
{
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch);
request.AddMetrics(ResourceBuilder.CreateEmpty().Build().ToOtlpResource(), batch, experimentalEmitNoRecordedValue);
}

var resourceMetric = request.ResourceMetrics.Single();
@@ -948,7 +953,7 @@ public void TestHistogramToOtlpMetric(bool useCustomSerializer, string name, str
: OtlpMetrics.AggregationTemporality.Delta;
Assert.Equal(otlpAggregationTemporality, actual.Histogram.AggregationTemporality);

if (!disposeMeterEarly)
if (!disposeMeterEarly || !experimentalEmitNoRecordedValue)
{
Assert.Single(actual.Histogram.DataPoints);
}