io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder Maven / Gradle / Ivy
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.metrics;
import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.internal.ScopeConfigurator;
import io.opentelemetry.sdk.internal.ScopeConfiguratorBuilder;
import io.opentelemetry.sdk.metrics.export.CardinalityLimitSelector;
import io.opentelemetry.sdk.metrics.export.MetricProducer;
import io.opentelemetry.sdk.metrics.export.MetricReader;
import io.opentelemetry.sdk.metrics.internal.MeterConfig;
import io.opentelemetry.sdk.metrics.internal.SdkMeterProviderUtil;
import io.opentelemetry.sdk.metrics.internal.debug.SourceInfo;
import io.opentelemetry.sdk.metrics.internal.exemplar.ExemplarFilter;
import io.opentelemetry.sdk.metrics.internal.view.RegisteredView;
import io.opentelemetry.sdk.resources.Resource;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
/**
* Builder class for the {@link SdkMeterProvider}.
*
* @since 1.14.0
*/
public final class SdkMeterProviderBuilder {
/**
* By default, the exemplar filter is set to sample with traces.
*
* @see #setExemplarFilter(ExemplarFilter)
*/
private static final ExemplarFilter DEFAULT_EXEMPLAR_FILTER = ExemplarFilter.traceBased();
private Clock clock = Clock.getDefault();
private Resource resource = Resource.getDefault();
private final IdentityHashMap metricReaders =
new IdentityHashMap<>();
private final List metricProducers = new ArrayList<>();
private final List registeredViews = new ArrayList<>();
private ExemplarFilter exemplarFilter = DEFAULT_EXEMPLAR_FILTER;
private ScopeConfiguratorBuilder meterConfiguratorBuilder =
MeterConfig.configuratorBuilder();
SdkMeterProviderBuilder() {}
/**
* Assign a {@link Clock}.
*
* @param clock The clock to use for all temporal needs.
*/
public SdkMeterProviderBuilder setClock(Clock clock) {
Objects.requireNonNull(clock, "clock");
this.clock = clock;
return this;
}
/** Assign a {@link Resource} to be attached to all metrics. */
public SdkMeterProviderBuilder setResource(Resource resource) {
Objects.requireNonNull(resource, "resource");
this.resource = resource;
return this;
}
/**
* Merge a {@link Resource} with the current.
*
* @param resource {@link Resource} to merge with current.
* @since 1.29.0
*/
public SdkMeterProviderBuilder addResource(Resource resource) {
Objects.requireNonNull(resource, "resource");
this.resource = this.resource.merge(resource);
return this;
}
/**
* Assign an {@link ExemplarFilter} for all metrics created by Meters.
*
* This method is experimental so not public. You may reflectively call it using {@link
* SdkMeterProviderUtil#setExemplarFilter(SdkMeterProviderBuilder, ExemplarFilter)}.
*/
SdkMeterProviderBuilder setExemplarFilter(ExemplarFilter filter) {
this.exemplarFilter = filter;
return this;
}
/**
* Register a {@link View}.
*
*
The {@code view} influences how instruments which match the {@code selector} are aggregated
* and exported.
*
*
For example, the following code registers a view which changes all histogram instruments to
* aggregate with bucket boundaries different from the default:
*
*
{@code
* // create a SdkMeterProviderBuilder
* SdkMeterProviderBuilder meterProviderBuilder = SdkMeterProvider.builder();
*
* // register the view with the SdkMeterProviderBuilder
* meterProviderBuilder.registerView(
* InstrumentSelector.builder()
* .setType(InstrumentType.HISTOGRAM)
* .build(),
* View.builder()
* .setAggregation(
* Aggregation.explicitBucketHistogram(Arrays.asList(10d, 20d, 30d, 40d, 50d)))
* .build());
* }
*/
public SdkMeterProviderBuilder registerView(InstrumentSelector selector, View view) {
Objects.requireNonNull(selector, "selector");
Objects.requireNonNull(view, "view");
registeredViews.add(
RegisteredView.create(
selector,
view,
view.getAttributesProcessor(),
view.getCardinalityLimit(),
SourceInfo.fromCurrentStack()));
return this;
}
/** Registers a {@link MetricReader}. */
public SdkMeterProviderBuilder registerMetricReader(MetricReader reader) {
metricReaders.put(reader, CardinalityLimitSelector.defaultCardinalityLimitSelector());
return this;
}
/**
* Registers a {@link MetricReader} with a {@link CardinalityLimitSelector}.
*
* If {@link #registerMetricReader(MetricReader)} is used, the {@link
* CardinalityLimitSelector#defaultCardinalityLimitSelector()} is used.
*
* @since 1.44.0
*/
public SdkMeterProviderBuilder registerMetricReader(
MetricReader reader, CardinalityLimitSelector cardinalityLimitSelector) {
metricReaders.put(reader, cardinalityLimitSelector);
return this;
}
/**
* Registers a {@link MetricProducer}.
*
* @since 1.31.0
*/
public SdkMeterProviderBuilder registerMetricProducer(MetricProducer metricProducer) {
metricProducers.add(metricProducer);
return this;
}
/**
* Set the meter configurator, which computes {@link MeterConfig} for each {@link
* InstrumentationScopeInfo}.
*
*
This method is experimental so not public. You may reflectively call it using {@link
* SdkMeterProviderUtil#setMeterConfigurator(SdkMeterProviderBuilder, ScopeConfigurator)}.
*
*
Overrides any matchers added via {@link #addMeterConfiguratorCondition(Predicate,
* MeterConfig)}.
*
* @see MeterConfig#configuratorBuilder()
*/
SdkMeterProviderBuilder setMeterConfigurator(ScopeConfigurator meterConfigurator) {
this.meterConfiguratorBuilder = meterConfigurator.toBuilder();
return this;
}
/**
* Adds a condition to the meter configurator, which computes {@link MeterConfig} for each {@link
* InstrumentationScopeInfo}.
*
* This method is experimental so not public. You may reflectively call it using {@link
* SdkMeterProviderUtil#addMeterConfiguratorCondition(SdkMeterProviderBuilder, Predicate,
* MeterConfig)}.
*
*
Applies after any previously added conditions.
*
*
If {@link #setMeterConfigurator(ScopeConfigurator)} was previously called, this condition
* will only be applied if the {@link ScopeConfigurator#apply(Object)} returns null for the
* matched {@link InstrumentationScopeInfo}(s).
*
* @see ScopeConfiguratorBuilder#nameEquals(String)
* @see ScopeConfiguratorBuilder#nameMatchesGlob(String)
*/
SdkMeterProviderBuilder addMeterConfiguratorCondition(
Predicate scopeMatcher, MeterConfig meterConfig) {
this.meterConfiguratorBuilder.addCondition(scopeMatcher, meterConfig);
return this;
}
/** Returns an {@link SdkMeterProvider} built with the configuration of this builder. */
public SdkMeterProvider build() {
return new SdkMeterProvider(
registeredViews,
metricReaders,
metricProducers,
clock,
resource,
exemplarFilter,
meterConfiguratorBuilder.build());
}
}