// // 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; } } }