Skip to content

Commit

Permalink
MetricReader TemporalityPreference (#3153)
Browse files Browse the repository at this point in the history
  • Loading branch information
alanwest authored Apr 12, 2022
1 parent 3bf869a commit 89a740e
Show file tree
Hide file tree
Showing 20 changed files with 181 additions and 129 deletions.
4 changes: 2 additions & 2 deletions examples/Console/TestMetrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ internal static object Run(MetricsOptions options)
exporterOptions.Protocol = options.UseGrpc ? OtlpExportProtocol.Grpc : OtlpExportProtocol.HttpProtobuf;

metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = options.DefaultCollectionPeriodMilliseconds;
metricReaderOptions.Temporality = options.IsDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative;
metricReaderOptions.TemporalityPreference = options.IsDelta ? MetricReaderTemporalityPreference.Delta : MetricReaderTemporalityPreference.Cumulative;
});
}
else
Expand All @@ -82,7 +82,7 @@ internal static object Run(MetricsOptions options)
exporterOptions.Targets = ConsoleExporterOutputTargets.Console;

metricReaderOptions.PeriodicExportingMetricReaderOptions.ExportIntervalMilliseconds = options.DefaultCollectionPeriodMilliseconds;
metricReaderOptions.Temporality = options.IsDelta ? AggregationTemporality.Delta : AggregationTemporality.Cumulative;
metricReaderOptions.TemporalityPreference = options.IsDelta ? MetricReaderTemporalityPreference.Delta : MetricReaderTemporalityPreference.Cumulative;
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ namespace OpenTelemetry.Exporter
/// <summary>
/// Exporter of OpenTelemetry metrics to Prometheus.
/// </summary>
[AggregationTemporality(AggregationTemporality.Cumulative)]
[ExportModes(ExportModes.Pull)]
public class PrometheusExporter : BaseExporter<Metric>, IPullMetricExporter
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ private static MeterProviderBuilder AddPrometheusExporter(MeterProviderBuilder b

var exporter = new PrometheusExporter(options);
var reader = new BaseExportingMetricReader(exporter);
reader.TemporalityPreference = MetricReaderTemporalityPreference.Cumulative;

return builder.AddReader(reader);
}
Expand Down
14 changes: 7 additions & 7 deletions src/OpenTelemetry/.publicApi/net461/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration
OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.get -> double[]
OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.set -> void
OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.ExplicitBucketHistogramConfiguration() -> void
OpenTelemetry.Metrics.MetricReader.TemporalityPreference.get -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricReader.TemporalityPreference.set -> void
OpenTelemetry.Metrics.MetricReaderOptions
OpenTelemetry.Metrics.MetricReaderOptions.MetricReaderOptions() -> void
OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.get -> OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions
OpenTelemetry.Metrics.MetricReaderOptions.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.MetricReaderOptions.Temporality.set -> void
OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.AggregationTemporality.Cumulative = 1 -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.AggregationTemporality.Delta = 2 -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.AggregationTemporalityAttribute
OpenTelemetry.Metrics.AggregationTemporalityAttribute.AggregationTemporalityAttribute(OpenTelemetry.Metrics.AggregationTemporality temporality) -> void
OpenTelemetry.Metrics.AggregationTemporalityAttribute.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.BaseExportingMetricReader
OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter<OpenTelemetry.Metrics.Metric> exporter) -> void
OpenTelemetry.Metrics.BaseExportingMetricReader.SupportedExportModes.get -> OpenTelemetry.Metrics.ExportModes
Expand Down Expand Up @@ -76,8 +73,11 @@ OpenTelemetry.Metrics.MetricReader.Collect(int timeoutMilliseconds = -1) -> bool
OpenTelemetry.Metrics.MetricReader.Dispose() -> void
OpenTelemetry.Metrics.MetricReader.MetricReader() -> void
OpenTelemetry.Metrics.MetricReader.Shutdown(int timeoutMilliseconds = -1) -> bool
OpenTelemetry.Metrics.MetricReader.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.MetricReader.Temporality.set -> void
OpenTelemetry.Metrics.MetricReaderOptions.TemporalityPreference.get -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricReaderOptions.TemporalityPreference.set -> void
OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricReaderTemporalityPreference.Cumulative = 1 -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricReaderTemporalityPreference.Delta = 2 -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricStreamConfiguration
OpenTelemetry.Metrics.MetricStreamConfiguration.Description.get -> string
OpenTelemetry.Metrics.MetricStreamConfiguration.Description.set -> void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@ OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration
OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.get -> double[]
OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.Boundaries.set -> void
OpenTelemetry.Metrics.ExplicitBucketHistogramConfiguration.ExplicitBucketHistogramConfiguration() -> void
OpenTelemetry.Metrics.MetricReader.TemporalityPreference.get -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricReader.TemporalityPreference.set -> void
OpenTelemetry.Metrics.MetricReaderOptions
OpenTelemetry.Metrics.MetricReaderOptions.MetricReaderOptions() -> void
OpenTelemetry.Metrics.MetricReaderOptions.PeriodicExportingMetricReaderOptions.get -> OpenTelemetry.Metrics.PeriodicExportingMetricReaderOptions
OpenTelemetry.Metrics.MetricReaderOptions.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.MetricReaderOptions.Temporality.set -> void
OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.AggregationTemporality.Cumulative = 1 -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.AggregationTemporality.Delta = 2 -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.AggregationTemporalityAttribute
OpenTelemetry.Metrics.AggregationTemporalityAttribute.AggregationTemporalityAttribute(OpenTelemetry.Metrics.AggregationTemporality temporality) -> void
OpenTelemetry.Metrics.AggregationTemporalityAttribute.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.BaseExportingMetricReader
OpenTelemetry.Metrics.BaseExportingMetricReader.BaseExportingMetricReader(OpenTelemetry.BaseExporter<OpenTelemetry.Metrics.Metric> exporter) -> void
OpenTelemetry.Metrics.BaseExportingMetricReader.SupportedExportModes.get -> OpenTelemetry.Metrics.ExportModes
Expand Down Expand Up @@ -76,8 +73,11 @@ OpenTelemetry.Metrics.MetricReader.Collect(int timeoutMilliseconds = -1) -> bool
OpenTelemetry.Metrics.MetricReader.Dispose() -> void
OpenTelemetry.Metrics.MetricReader.MetricReader() -> void
OpenTelemetry.Metrics.MetricReader.Shutdown(int timeoutMilliseconds = -1) -> bool
OpenTelemetry.Metrics.MetricReader.Temporality.get -> OpenTelemetry.Metrics.AggregationTemporality
OpenTelemetry.Metrics.MetricReader.Temporality.set -> void
OpenTelemetry.Metrics.MetricReaderOptions.TemporalityPreference.get -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricReaderOptions.TemporalityPreference.set -> void
OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricReaderTemporalityPreference.Cumulative = 1 -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricReaderTemporalityPreference.Delta = 2 -> OpenTelemetry.Metrics.MetricReaderTemporalityPreference
OpenTelemetry.Metrics.MetricStreamConfiguration
OpenTelemetry.Metrics.MetricStreamConfiguration.Description.get -> string
OpenTelemetry.Metrics.MetricStreamConfiguration.Description.set -> void
Expand Down
13 changes: 13 additions & 0 deletions src/OpenTelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

## Unreleased

* Removed the `Temporality` setting on `MetricReader` and replaced it with
`TemporalityPreference`. This is a breaking change.
`TemporalityPreference` is used to determine the `AggregationTemporality`
used on a per-instrument kind basis. Currently, there are two preferences:
* `Cumulative`: Measurements from all instrument kinds are aggregated using
`AggregationTemporality.Cumulative`.
* `Delta`: Measurements from `Counter`, `ObservableCounter`, and `Histogram`
instruments are aggregated using `AggregationTemporality.Delta`. When
UpDownCounters are supported with
[DiagnosticSource version 7.0 onwards](https://www.nuget.org/packages/System.Diagnostics.DiagnosticSource/7.0.0-preview.2.22152.2),
they will be aggregated using `AggregationTemporality.Cumulative`.
([#3153](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3153))

* Fix issue where `ExplicitBucketHistogramConfiguration` could be used to
configure metric streams for instruments that are not histograms. Currently,
it is not possible to change the aggregation of an instrument with views. This
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ internal static PeriodicExportingMetricReader CreatePeriodicExportingMetricReade

var metricReader = new PeriodicExportingMetricReader(exporter, exportInterval, exportTimeout)
{
Temporality = options.Temporality,
TemporalityPreference = options.TemporalityPreference,
};

return metricReader;
Expand Down
33 changes: 0 additions & 33 deletions src/OpenTelemetry/Metrics/AggregationTemporalityAttribute.cs

This file was deleted.

9 changes: 1 addition & 8 deletions src/OpenTelemetry/Metrics/BaseExportingMetricReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,7 @@ public BaseExportingMetricReader(BaseExporter<Metric> exporter)
this.exporter = exporter;

var exportorType = exporter.GetType();
var attributes = exportorType.GetCustomAttributes(typeof(AggregationTemporalityAttribute), true);
if (attributes.Length > 0)
{
var attr = (AggregationTemporalityAttribute)attributes[attributes.Length - 1];
this.Temporality = attr.Temporality;
}

attributes = exportorType.GetCustomAttributes(typeof(ExportModesAttribute), true);
var attributes = exportorType.GetCustomAttributes(typeof(ExportModesAttribute), true);
if (attributes.Length > 0)
{
var attr = (ExportModesAttribute)attributes[attributes.Length - 1];
Expand Down
58 changes: 49 additions & 9 deletions src/OpenTelemetry/Metrics/MetricReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

using System;
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Threading;
using System.Threading.Tasks;
using OpenTelemetry.Internal;
Expand All @@ -27,35 +28,74 @@ namespace OpenTelemetry.Metrics
/// </summary>
public abstract partial class MetricReader : IDisposable
{
private const AggregationTemporality AggregationTemporalityUnspecified = (AggregationTemporality)0;
private const MetricReaderTemporalityPreference MetricReaderTemporalityPreferenceUnspecified = (MetricReaderTemporalityPreference)0;

private static Func<Type, AggregationTemporality> cumulativeTemporatlityPreferenceFunc =
(instrumentType) => AggregationTemporality.Cumulative;

private static Func<Type, AggregationTemporality> monotonicDeltaTemporatlityPreferenceFunc = (instrumentType) =>
{
return instrumentType.GetGenericTypeDefinition() switch
{
var type when type == typeof(Counter<>) => AggregationTemporality.Delta,
var type when type == typeof(ObservableCounter<>) => AggregationTemporality.Delta,
var type when type == typeof(Histogram<>) => AggregationTemporality.Delta,

// 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,

// TODO: Consider logging here because we should not fall through to this case.
_ => AggregationTemporality.Delta,
};
};

private readonly object newTaskLock = new();
private readonly object onCollectLock = new();
private readonly TaskCompletionSource<bool> shutdownTcs = new();
private AggregationTemporality temporality = AggregationTemporalityUnspecified;
private MetricReaderTemporalityPreference temporalityPreference = MetricReaderTemporalityPreferenceUnspecified;
private Func<Type, AggregationTemporality> temporatlityFunc = cumulativeTemporatlityPreferenceFunc;
private int shutdownCount;
private TaskCompletionSource<bool> collectionTcs;
private BaseProvider parentProvider;

public AggregationTemporality Temporality
public MetricReaderTemporalityPreference TemporalityPreference
{
get
{
if (this.temporality == AggregationTemporalityUnspecified)
if (this.temporalityPreference == MetricReaderTemporalityPreferenceUnspecified)
{
this.temporality = AggregationTemporality.Cumulative;
this.temporalityPreference = MetricReaderTemporalityPreference.Cumulative;
}

return this.temporality;
return this.temporalityPreference;
}

set
{
if (this.temporality != AggregationTemporalityUnspecified)
if (this.temporalityPreference != MetricReaderTemporalityPreferenceUnspecified)
{
throw new NotSupportedException($"The temporality cannot be modified (the current value is {this.temporality}).");
throw new NotSupportedException($"The temporality preference cannot be modified (the current value is {this.temporalityPreference}).");
}

this.temporality = value;
this.temporalityPreference = value;
switch (value)
{
case MetricReaderTemporalityPreference.Delta:
this.temporatlityFunc = monotonicDeltaTemporatlityPreferenceFunc;
break;
case MetricReaderTemporalityPreference.Cumulative:
default:
this.temporatlityFunc = cumulativeTemporatlityPreferenceFunc;
break;
}
}
}

Expand Down
9 changes: 7 additions & 2 deletions src/OpenTelemetry/Metrics/MetricReaderExt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ public abstract partial class MetricReader
private Metric[] metricsCurrentBatch;
private int metricIndex = -1;

internal AggregationTemporality GetAggregationTemporality(Type instrumentType)
{
return this.temporatlityFunc(instrumentType);
}

internal Metric AddMetricWithNoViews(Instrument instrument)
{
var metricStreamIdentity = new MetricStreamIdentity(instrument, metricStreamConfiguration: null);
Expand Down Expand Up @@ -66,7 +71,7 @@ internal Metric AddMetricWithNoViews(Instrument instrument)
Metric metric = null;
try
{
metric = new Metric(metricStreamIdentity, this.Temporality, this.maxMetricPointsPerMetricStream);
metric = new Metric(metricStreamIdentity, this.GetAggregationTemporality(metricStreamIdentity.InstrumentType), this.maxMetricPointsPerMetricStream);
}
catch (NotSupportedException nse)
{
Expand Down Expand Up @@ -152,7 +157,7 @@ internal List<Metric> AddMetricsListWithViews(Instrument instrument, List<Metric
else
{
Metric metric;
metric = new Metric(metricStreamIdentity, this.Temporality, this.maxMetricPointsPerMetricStream, metricStreamIdentity.HistogramBucketBounds, metricStreamIdentity.TagKeys);
metric = new Metric(metricStreamIdentity, this.GetAggregationTemporality(metricStreamIdentity.InstrumentType), this.maxMetricPointsPerMetricStream, metricStreamIdentity.HistogramBucketBounds, metricStreamIdentity.TagKeys);

this.instrumentIdentityToMetric[metricStreamIdentity] = metric;
this.metrics[index] = metric;
Expand Down
5 changes: 2 additions & 3 deletions src/OpenTelemetry/Metrics/MetricReaderOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ namespace OpenTelemetry.Metrics;
public class MetricReaderOptions
{
/// <summary>
/// Gets or sets the AggregationTemporality used for Histogram
/// and Sum metrics.
/// Gets or sets the <see cref="MetricReaderTemporalityPreference" />.
/// </summary>
public AggregationTemporality Temporality { get; set; } = AggregationTemporality.Cumulative;
public MetricReaderTemporalityPreference TemporalityPreference { get; set; } = MetricReaderTemporalityPreference.Cumulative;

/// <summary>
/// Gets the <see cref="PeriodicExportingMetricReaderOptions" /> options.
Expand Down
35 changes: 35 additions & 0 deletions src/OpenTelemetry/Metrics/MetricReaderTemporalityPreference.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// <copyright file="MetricReaderTemporalityPreference.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;

/// <summary>
/// Defines the behavior of a <see cref="MetricReader" />
/// with respect to <see cref="AggregationTemporality" />.
/// </summary>
public enum MetricReaderTemporalityPreference
{
/// <summary>
/// All aggregations are performed using cumulative temporatlity.
/// </summary>
Cumulative = 1,

/// <summary>
/// All measurements that are monotnic in nature are aggregated using delta temporality.
/// Aggregations of non-monotonic measurements use cumulative temporality.
/// </summary>
Delta = 2,
}
Loading

0 comments on commit 89a740e

Please sign in to comment.