Allow ability to override max Metric streams and MetricPoints per stream (#2635)
This commit is contained in:
parent
ca291422ff
commit
5dcf29f770
|
|
@ -112,6 +112,8 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTel
|
|||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, string name) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Func<System.Diagnostics.Metrics.Instrument, OpenTelemetry.Metrics.MetricStreamConfiguration> viewConfig) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Build(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProvider
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricPointsPerMetricStream(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricStreams(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricStreams) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderExtensions.ForceFlush(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool
|
||||
static OpenTelemetry.Metrics.MeterProviderExtensions.Shutdown(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTel
|
|||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, string instrumentName, string name) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.AddView(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, System.Func<System.Diagnostics.Metrics.Instrument, OpenTelemetry.Metrics.MetricStreamConfiguration> viewConfig) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.Build(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder) -> OpenTelemetry.Metrics.MeterProvider
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricPointsPerMetricStream(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetMaxMetricStreams(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, int maxMetricStreams) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderBuilderExtensions.SetResourceBuilder(this OpenTelemetry.Metrics.MeterProviderBuilder meterProviderBuilder, OpenTelemetry.Resources.ResourceBuilder resourceBuilder) -> OpenTelemetry.Metrics.MeterProviderBuilder
|
||||
static OpenTelemetry.Metrics.MeterProviderExtensions.ForceFlush(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool
|
||||
static OpenTelemetry.Metrics.MeterProviderExtensions.Shutdown(this OpenTelemetry.Metrics.MeterProvider provider, int timeoutMilliseconds = -1) -> bool
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
* Add support for multiple Metric readers
|
||||
([#2596](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2596))
|
||||
|
||||
* Add ability to configure MaxMetricStreams, MaxMetricPointsPerMetricStream
|
||||
([#2635](https://github.com/open-telemetry/opentelemetry-dotnet/pull/2635))
|
||||
|
||||
## 1.2.0-beta1
|
||||
|
||||
Released 2021-Oct-08
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ namespace OpenTelemetry.Metrics
|
|||
{
|
||||
internal sealed class AggregatorStore
|
||||
{
|
||||
internal const int MaxMetricPoints = 2000;
|
||||
private static readonly ObjectArrayEqualityComparer ObjectArrayComparer = new ObjectArrayEqualityComparer();
|
||||
private readonly object lockZeroTags = new object();
|
||||
private readonly HashSet<string> tagKeysInteresting;
|
||||
|
|
@ -42,6 +41,7 @@ namespace OpenTelemetry.Metrics
|
|||
private readonly double[] histogramBounds;
|
||||
private readonly UpdateLongDelegate updateLongCallback;
|
||||
private readonly UpdateDoubleDelegate updateDoubleCallback;
|
||||
private readonly int maxMetricPoints;
|
||||
private int metricPointIndex = 0;
|
||||
private int batchSize = 0;
|
||||
private bool zeroTagMetricPointInitialized;
|
||||
|
|
@ -51,11 +51,13 @@ namespace OpenTelemetry.Metrics
|
|||
internal AggregatorStore(
|
||||
AggregationType aggType,
|
||||
AggregationTemporality temporality,
|
||||
int maxMetricPoints,
|
||||
double[] histogramBounds,
|
||||
string[] tagKeysInteresting = null)
|
||||
{
|
||||
this.metricPoints = new MetricPoint[MaxMetricPoints];
|
||||
this.currentMetricPointBatch = new int[MaxMetricPoints];
|
||||
this.maxMetricPoints = maxMetricPoints;
|
||||
this.metricPoints = new MetricPoint[maxMetricPoints];
|
||||
this.currentMetricPointBatch = new int[maxMetricPoints];
|
||||
this.aggType = aggType;
|
||||
this.temporality = temporality;
|
||||
this.outputDelta = temporality == AggregationTemporality.Delta ? true : false;
|
||||
|
|
@ -98,7 +100,7 @@ namespace OpenTelemetry.Metrics
|
|||
internal int Snapshot()
|
||||
{
|
||||
this.batchSize = 0;
|
||||
var indexSnapshot = Math.Min(this.metricPointIndex, MaxMetricPoints - 1);
|
||||
var indexSnapshot = Math.Min(this.metricPointIndex, this.maxMetricPoints - 1);
|
||||
if (this.temporality == AggregationTemporality.Delta)
|
||||
{
|
||||
this.SnapshotDelta(indexSnapshot);
|
||||
|
|
@ -197,7 +199,7 @@ namespace OpenTelemetry.Metrics
|
|||
if (!value2metrics.TryGetValue(tagValues, out aggregatorIndex))
|
||||
{
|
||||
aggregatorIndex = this.metricPointIndex;
|
||||
if (aggregatorIndex >= MaxMetricPoints)
|
||||
if (aggregatorIndex >= this.maxMetricPoints)
|
||||
{
|
||||
// sorry! out of data points.
|
||||
// TODO: Once we support cleanup of
|
||||
|
|
@ -212,7 +214,7 @@ namespace OpenTelemetry.Metrics
|
|||
if (!value2metrics.TryGetValue(tagValues, out aggregatorIndex))
|
||||
{
|
||||
aggregatorIndex = Interlocked.Increment(ref this.metricPointIndex);
|
||||
if (aggregatorIndex >= MaxMetricPoints)
|
||||
if (aggregatorIndex >= this.maxMetricPoints)
|
||||
{
|
||||
// sorry! out of data points.
|
||||
// TODO: Once we support cleanup of
|
||||
|
|
|
|||
|
|
@ -29,10 +29,14 @@ namespace OpenTelemetry.Metrics
|
|||
/// </summary>
|
||||
public abstract class MeterProviderBuilderBase : MeterProviderBuilder
|
||||
{
|
||||
internal const int MaxMetricsDefault = 1000;
|
||||
internal const int MaxMetricPointsPerMetricDefault = 2000;
|
||||
private readonly List<InstrumentationFactory> instrumentationFactories = new List<InstrumentationFactory>();
|
||||
private readonly List<string> meterSources = new List<string>();
|
||||
private readonly List<Func<Instrument, MetricStreamConfiguration>> viewConfigs = new List<Func<Instrument, MetricStreamConfiguration>>();
|
||||
private ResourceBuilder resourceBuilder = ResourceBuilder.CreateDefault();
|
||||
private int maxMetricStreams = MaxMetricsDefault;
|
||||
private int maxMetricPointsPerMetricStream = MaxMetricPointsPerMetricDefault;
|
||||
|
||||
protected MeterProviderBuilderBase()
|
||||
{
|
||||
|
|
@ -100,6 +104,22 @@ namespace OpenTelemetry.Metrics
|
|||
return this;
|
||||
}
|
||||
|
||||
internal MeterProviderBuilder SetMaxMetricStreams(int maxMetricStreams)
|
||||
{
|
||||
Guard.Range(maxMetricStreams, min: 1);
|
||||
|
||||
this.maxMetricStreams = maxMetricStreams;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal MeterProviderBuilder SetMaxMetricPointsPerMetricStream(int maxMetricPointsPerMetricStream)
|
||||
{
|
||||
Guard.Range(maxMetricPointsPerMetricStream, min: 1);
|
||||
|
||||
this.maxMetricPointsPerMetricStream = maxMetricPointsPerMetricStream;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal MeterProviderBuilder SetResourceBuilder(ResourceBuilder resourceBuilder)
|
||||
{
|
||||
Debug.Assert(resourceBuilder != null, $"{nameof(resourceBuilder)} must not be null");
|
||||
|
|
@ -119,6 +139,8 @@ namespace OpenTelemetry.Metrics
|
|||
this.meterSources,
|
||||
this.instrumentationFactories,
|
||||
this.viewConfigs,
|
||||
this.maxMetricStreams,
|
||||
this.maxMetricPointsPerMetricStream,
|
||||
this.MetricReaders.ToArray());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,53 @@ namespace OpenTelemetry.Metrics
|
|||
return meterProviderBuilder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the maximum number of Metric streams supported by the MeterProvider.
|
||||
/// When no Views are configured, every instrument will result in one metric stream,
|
||||
/// so this control the numbers of instruments supported.
|
||||
/// When Views are configued, a single instrument can result in multiple metric streams,
|
||||
/// so this control the number of streams.
|
||||
/// </summary>
|
||||
/// <param name="meterProviderBuilder">MeterProviderBuilder instance.</param>
|
||||
/// <param name="maxMetricStreams">Maximum number of metric streams allowed.</param>
|
||||
/// <returns>Returns <see cref="MeterProviderBuilder"/> for chaining.</returns>
|
||||
/// <remarks>
|
||||
/// If an instrument is created, but disposed later, this will still be contributing to the limit.
|
||||
/// This may change in the future.
|
||||
/// </remarks>
|
||||
public static MeterProviderBuilder SetMaxMetricStreams(this MeterProviderBuilder meterProviderBuilder, int maxMetricStreams)
|
||||
{
|
||||
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
|
||||
{
|
||||
meterProviderBuilderBase.SetMaxMetricStreams(maxMetricStreams);
|
||||
}
|
||||
|
||||
return meterProviderBuilder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the maximum number of MetricPoints allowed per metric stream.
|
||||
/// This limits the number of unique combinations of key/value pairs used
|
||||
/// for reporting measurements.
|
||||
/// </summary>
|
||||
/// <param name="meterProviderBuilder">MeterProviderBuilder instance.</param>
|
||||
/// <param name="maxMetricPointsPerMetricStream">Maximum maximum number of metric points allowed per metric stream.</param>
|
||||
/// <returns>Returns <see cref="MeterProviderBuilder"/> for chaining.</returns>
|
||||
/// <remarks>
|
||||
/// If a particular key/value pair combination is used at least once,
|
||||
/// it will contribute to the limit for the life of the process.
|
||||
/// This may change in the future. See: https://github.com/open-telemetry/opentelemetry-dotnet/issues/2360.
|
||||
/// </remarks>
|
||||
public static MeterProviderBuilder SetMaxMetricPointsPerMetricStream(this MeterProviderBuilder meterProviderBuilder, int maxMetricPointsPerMetricStream)
|
||||
{
|
||||
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
|
||||
{
|
||||
meterProviderBuilderBase.SetMaxMetricPointsPerMetricStream(maxMetricPointsPerMetricStream);
|
||||
}
|
||||
|
||||
return meterProviderBuilder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="ResourceBuilder"/> from which the Resource associated with
|
||||
/// this provider is built from. Overwrites currently set ResourceBuilder.
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ namespace OpenTelemetry.Metrics
|
|||
IEnumerable<string> meterSources,
|
||||
List<MeterProviderBuilderBase.InstrumentationFactory> instrumentationFactories,
|
||||
List<Func<Instrument, MetricStreamConfiguration>> viewConfigs,
|
||||
int maxMetricStreams,
|
||||
int maxMetricPointsPerMetricStream,
|
||||
IEnumerable<MetricReader> readers)
|
||||
{
|
||||
this.Resource = resource;
|
||||
|
|
@ -51,6 +53,8 @@ namespace OpenTelemetry.Metrics
|
|||
Guard.Null(reader, nameof(reader));
|
||||
|
||||
reader.SetParentProvider(this);
|
||||
reader.SetMaxMetricStreams(maxMetricStreams);
|
||||
reader.SetMaxMetricPointsPerMetricStream(maxMetricPointsPerMetricStream);
|
||||
|
||||
if (this.reader == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ namespace OpenTelemetry.Metrics
|
|||
AggregationTemporality temporality,
|
||||
string metricName,
|
||||
string metricDescription,
|
||||
int maxMetricPointsPerMetricStream,
|
||||
double[] histogramBounds = null,
|
||||
string[] tagKeysInteresting = null)
|
||||
{
|
||||
|
|
@ -104,7 +105,7 @@ namespace OpenTelemetry.Metrics
|
|||
// TODO: Log and assign some invalid Enum.
|
||||
}
|
||||
|
||||
this.aggStore = new AggregatorStore(aggType, temporality, histogramBounds ?? DefaultHistogramBounds, tagKeysInteresting);
|
||||
this.aggStore = new AggregatorStore(aggType, temporality, maxMetricPointsPerMetricStream, histogramBounds ?? DefaultHistogramBounds, tagKeysInteresting);
|
||||
this.Temporality = temporality;
|
||||
this.InstrumentDisposed = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,11 +26,12 @@ namespace OpenTelemetry.Metrics
|
|||
/// </summary>
|
||||
public abstract partial class MetricReader
|
||||
{
|
||||
internal const int MaxMetrics = 1000;
|
||||
private readonly Metric[] metrics = new Metric[MaxMetrics];
|
||||
private readonly Metric[] metricsCurrentBatch = new Metric[MaxMetrics];
|
||||
private readonly HashSet<string> metricStreamNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly object instrumentCreationLock = new object();
|
||||
private int maxMetricStreams;
|
||||
private int maxMetricPointsPerMetricStream;
|
||||
private Metric[] metrics;
|
||||
private Metric[] metricsCurrentBatch;
|
||||
private int metricIndex = -1;
|
||||
|
||||
internal Metric AddMetricWithNoViews(Instrument instrument)
|
||||
|
|
@ -47,14 +48,14 @@ namespace OpenTelemetry.Metrics
|
|||
}
|
||||
|
||||
var index = ++this.metricIndex;
|
||||
if (index >= MaxMetrics)
|
||||
if (index >= this.maxMetricStreams)
|
||||
{
|
||||
OpenTelemetrySdkEventSource.Log.MetricInstrumentIgnored(metricName, instrument.Meter.Name, "Maximum allowed Metrics for the provider exceeded.", "Use views to drop unused instruments. Or configure Provider to allow higher limit.");
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var metric = new Metric(instrument, this.preferredAggregationTemporality, metricName, instrument.Description);
|
||||
var metric = new Metric(instrument, this.preferredAggregationTemporality, metricName, instrument.Description, this.maxMetricPointsPerMetricStream);
|
||||
this.metrics[index] = metric;
|
||||
this.metricStreamNames.Add(metricStreamName);
|
||||
return metric;
|
||||
|
|
@ -118,7 +119,7 @@ namespace OpenTelemetry.Metrics
|
|||
}
|
||||
|
||||
var index = ++this.metricIndex;
|
||||
if (index >= MaxMetrics)
|
||||
if (index >= this.maxMetricStreams)
|
||||
{
|
||||
// TODO: Log that instrument is ignored
|
||||
// as max number of Metrics have reached.
|
||||
|
|
@ -130,7 +131,7 @@ namespace OpenTelemetry.Metrics
|
|||
string[] tagKeysInteresting = metricStreamConfig?.TagKeys;
|
||||
double[] histogramBucketBounds = (metricStreamConfig is ExplicitBucketHistogramConfiguration histogramConfig
|
||||
&& histogramConfig.Boundaries != null) ? histogramConfig.Boundaries : null;
|
||||
metric = new Metric(instrument, this.preferredAggregationTemporality, metricName, metricDescription, histogramBucketBounds, tagKeysInteresting);
|
||||
metric = new Metric(instrument, this.preferredAggregationTemporality, metricName, metricDescription, this.maxMetricPointsPerMetricStream, histogramBucketBounds, tagKeysInteresting);
|
||||
|
||||
this.metrics[index] = metric;
|
||||
metrics.Add(metric);
|
||||
|
|
@ -191,11 +192,23 @@ namespace OpenTelemetry.Metrics
|
|||
}
|
||||
}
|
||||
|
||||
internal void SetMaxMetricStreams(int maxMetricStreams)
|
||||
{
|
||||
this.maxMetricStreams = maxMetricStreams;
|
||||
this.metrics = new Metric[maxMetricStreams];
|
||||
this.metricsCurrentBatch = new Metric[maxMetricStreams];
|
||||
}
|
||||
|
||||
internal void SetMaxMetricPointsPerMetricStream(int maxMetricPointsPerMetricStream)
|
||||
{
|
||||
this.maxMetricPointsPerMetricStream = maxMetricPointsPerMetricStream;
|
||||
}
|
||||
|
||||
private Batch<Metric> GetMetricsBatch()
|
||||
{
|
||||
try
|
||||
{
|
||||
var indexSnapshot = Math.Min(this.metricIndex, MaxMetrics - 1);
|
||||
var indexSnapshot = Math.Min(this.metricIndex, this.maxMetricStreams - 1);
|
||||
var target = indexSnapshot + 1;
|
||||
int metricCountCurrentBatch = 0;
|
||||
for (int i = 0; i < target; i++)
|
||||
|
|
|
|||
|
|
@ -489,26 +489,26 @@ namespace OpenTelemetry.Metrics.Tests
|
|||
// for no tag point!
|
||||
// This may be changed later.
|
||||
counterLong.Add(10);
|
||||
for (int i = 0; i < AggregatorStore.MaxMetricPoints + 1; i++)
|
||||
for (int i = 0; i < MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault + 1; i++)
|
||||
{
|
||||
counterLong.Add(10, new KeyValuePair<string, object>("key", "value" + i));
|
||||
}
|
||||
|
||||
metricReader.Collect();
|
||||
Assert.Equal(AggregatorStore.MaxMetricPoints, MetricPointCount());
|
||||
Assert.Equal(MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault, MetricPointCount());
|
||||
|
||||
metricItems.Clear();
|
||||
counterLong.Add(10);
|
||||
for (int i = 0; i < AggregatorStore.MaxMetricPoints + 1; i++)
|
||||
for (int i = 0; i < MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault + 1; i++)
|
||||
{
|
||||
counterLong.Add(10, new KeyValuePair<string, object>("key", "value" + i));
|
||||
}
|
||||
|
||||
metricReader.Collect();
|
||||
Assert.Equal(AggregatorStore.MaxMetricPoints, MetricPointCount());
|
||||
Assert.Equal(MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault, MetricPointCount());
|
||||
|
||||
counterLong.Add(10);
|
||||
for (int i = 0; i < AggregatorStore.MaxMetricPoints + 1; i++)
|
||||
for (int i = 0; i < MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault + 1; i++)
|
||||
{
|
||||
counterLong.Add(10, new KeyValuePair<string, object>("key", "value" + i));
|
||||
}
|
||||
|
|
@ -519,7 +519,7 @@ namespace OpenTelemetry.Metrics.Tests
|
|||
counterLong.Add(10, new KeyValuePair<string, object>("key", "valueC"));
|
||||
metricItems.Clear();
|
||||
metricReader.Collect();
|
||||
Assert.Equal(AggregatorStore.MaxMetricPoints, MetricPointCount());
|
||||
Assert.Equal(MeterProviderBuilderBase.MaxMetricPointsPerMetricDefault, MetricPointCount());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Reference in New Issue