//
// 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.
//
using System;
using System.Diagnostics.Metrics;
using OpenTelemetry.Resources;
namespace OpenTelemetry.Metrics
{
///
/// Contains extension methods for the class.
///
public static class MeterProviderBuilderExtensions
{
///
/// Adds a reader to the provider.
///
/// .
/// .
/// .
public static MeterProviderBuilder AddReader(this MeterProviderBuilder meterProviderBuilder, MetricReader reader)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
{
return meterProviderBuilderBase.AddReader(reader);
}
return meterProviderBuilder;
}
///
/// Add metric view, which can be used to customize the Metrics outputted
/// from the SDK. The views are applied in the order they are added.
///
/// .
/// Name of the instrument, to be used as part of Instrument selection criteria.
/// Name of the view. This will be used as name of resulting metrics stream.
/// .
/// See View specification here : https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#view.
public static MeterProviderBuilder AddView(this MeterProviderBuilder meterProviderBuilder, string instrumentName, string name)
{
if (!MeterProviderBuilderSdk.IsValidInstrumentName(name))
{
throw new ArgumentException($"Custom view name {name} is invalid.", nameof(name));
}
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
{
return meterProviderBuilderBase.AddView(instrumentName, name);
}
return meterProviderBuilder;
}
///
/// Add metric view, which can be used to customize the Metrics outputted
/// from the SDK. The views are applied in the order they are added.
///
/// .
/// Name of the instrument, to be used as part of Instrument selection criteria.
/// Aggregation configuration used to produce metrics stream.
/// .
/// See View specification here : https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#view.
public static MeterProviderBuilder AddView(this MeterProviderBuilder meterProviderBuilder, string instrumentName, MetricStreamConfiguration metricStreamConfiguration)
{
if (metricStreamConfiguration == null)
{
throw new ArgumentNullException($"Metric stream configuration cannot be null.", nameof(metricStreamConfiguration));
}
if (!MeterProviderBuilderSdk.IsValidViewName(metricStreamConfiguration.Name))
{
throw new ArgumentException($"Custom view name {metricStreamConfiguration.Name} is invalid.", nameof(metricStreamConfiguration.Name));
}
if (metricStreamConfiguration is ExplicitBucketHistogramConfiguration histogramConfiguration)
{
// Validate histogram boundaries
if (histogramConfiguration.Boundaries != null && !IsSortedAndDistinct(histogramConfiguration.Boundaries))
{
throw new ArgumentException($"Histogram boundaries must be in ascending order with distinct values", nameof(histogramConfiguration.Boundaries));
}
}
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
{
return meterProviderBuilderBase.AddView(instrumentName, metricStreamConfiguration);
}
return meterProviderBuilder;
}
///
/// Add metric view, which can be used to customize the Metrics outputted
/// from the SDK. The views are applied in the order they are added.
///
/// .
/// Function to configure aggregation based on the instrument.
/// .
/// See View specification here : https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#view.
public static MeterProviderBuilder AddView(this MeterProviderBuilder meterProviderBuilder, Func viewConfig)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
{
return meterProviderBuilderBase.AddView(viewConfig);
}
return meterProviderBuilder;
}
///
/// Sets the from which the Resource associated with
/// this provider is built from. Overwrites currently set ResourceBuilder.
///
/// MeterProviderBuilder instance.
/// from which Resource will be built.
/// Returns for chaining.
public static MeterProviderBuilder SetResourceBuilder(this MeterProviderBuilder meterProviderBuilder, ResourceBuilder resourceBuilder)
{
if (meterProviderBuilder is MeterProviderBuilderBase meterProviderBuilderBase)
{
meterProviderBuilderBase.SetResourceBuilder(resourceBuilder);
}
return meterProviderBuilder;
}
///
/// Run the given actions to initialize the .
///
/// .
/// .
public static MeterProvider Build(this MeterProviderBuilder meterProviderBuilder)
{
if (meterProviderBuilder is IDeferredMeterProviderBuilder)
{
throw new NotSupportedException("DeferredMeterProviderBuilder requires a ServiceProvider to build.");
}
if (meterProviderBuilder is MeterProviderBuilderSdk meterProviderBuilderSdk)
{
return meterProviderBuilderSdk.BuildSdk();
}
return null;
}
private static bool IsSortedAndDistinct(double[] values)
{
for (int i = 1; i < values.Length; i++)
{
if (values[i] <= values[i - 1])
{
return false;
}
}
return true;
}
}
}