Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introducing view #2956

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ static <T> Aggregator<T> getAggregator(
return meterProviderSharedState
.getViewRegistry()
.findView(descriptor)
.getAggregatorFactory()
.create(
meterProviderSharedState.getResource(),
meterSharedState.getInstrumentationLibraryInfo(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.sdk.internal.ComponentRegistry;
import io.opentelemetry.sdk.metrics.aggregator.AggregatorFactory;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.export.MetricProducer;
import io.opentelemetry.sdk.metrics.view.InstrumentSelector;
import io.opentelemetry.sdk.metrics.view.View;
import io.opentelemetry.sdk.resources.Resource;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -95,13 +95,14 @@ public static SdkMeterProviderBuilder builder() {
* .buildInstrument();
*
* // create a specification of how you want the metrics aggregated:
* AggregationFactory aggregationFactory = AggregationFactory.minMaxSumCount();
* AggregatorFactory aggregatorFactory = AggregatorFactory.minMaxSumCount();
*
* //register the view with the MeterSdkProvider
* meterProvider.registerView(instrumentSelector, aggregationFactory);
* meterProvider.registerView(instrumentSelector, View.builder()
* .setAggregatorFactory(aggregatorFactory).build());
* }</pre>
*/
public void registerView(InstrumentSelector selector, AggregatorFactory aggregatorFactory) {
sharedState.getViewRegistry().registerView(selector, aggregatorFactory);
public void registerView(InstrumentSelector selector, View view) {
sharedState.getViewRegistry().registerView(selector, view);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import io.opentelemetry.sdk.metrics.common.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.common.InstrumentType;
import io.opentelemetry.sdk.metrics.view.InstrumentSelector;
import io.opentelemetry.sdk.metrics.view.View;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.Map;
Expand All @@ -23,15 +24,17 @@
* never blocked.
*/
final class ViewRegistry {
private static final LinkedHashMap<Pattern, AggregatorFactory> EMPTY_CONFIG =
new LinkedHashMap<>();
static final AggregatorFactory CUMULATIVE_SUM = AggregatorFactory.sum(true);
static final AggregatorFactory SUMMARY = AggregatorFactory.minMaxSumCount();
static final AggregatorFactory LAST_VALUE = AggregatorFactory.lastValue();
private static final LinkedHashMap<Pattern, View> EMPTY_CONFIG = new LinkedHashMap<>();
static final View CUMULATIVE_SUM =
View.builder().setAggregatorFactory(AggregatorFactory.sum(true)).build();
static final View SUMMARY =
View.builder().setAggregatorFactory(AggregatorFactory.minMaxSumCount()).build();
static final View LAST_VALUE =
View.builder().setAggregatorFactory(AggregatorFactory.lastValue()).build();

// The lock is used to ensure only one updated to the configuration happens at any moment.
private final ReentrantLock lock = new ReentrantLock();
private volatile EnumMap<InstrumentType, LinkedHashMap<Pattern, AggregatorFactory>> configuration;
private volatile EnumMap<InstrumentType, LinkedHashMap<Pattern, View>> configuration;

ViewRegistry() {
this.configuration = new EnumMap<>(InstrumentType.class);
Expand All @@ -43,27 +46,26 @@ final class ViewRegistry {
configuration.put(InstrumentType.VALUE_OBSERVER, EMPTY_CONFIG);
}

void registerView(InstrumentSelector selector, AggregatorFactory aggregatorFactory) {
void registerView(InstrumentSelector selector, View view) {
lock.lock();
try {
EnumMap<InstrumentType, LinkedHashMap<Pattern, AggregatorFactory>> newConfiguration =
EnumMap<InstrumentType, LinkedHashMap<Pattern, View>> newConfiguration =
new EnumMap<>(configuration);
newConfiguration.put(
selector.getInstrumentType(),
newLinkedHashMap(
selector.getInstrumentNamePattern(),
aggregatorFactory,
view,
newConfiguration.get(selector.getInstrumentType())));
configuration = newConfiguration;
} finally {
lock.unlock();
}
}

AggregatorFactory findView(InstrumentDescriptor descriptor) {
LinkedHashMap<Pattern, AggregatorFactory> configPerType =
configuration.get(descriptor.getType());
for (Map.Entry<Pattern, AggregatorFactory> entry : configPerType.entrySet()) {
View findView(InstrumentDescriptor descriptor) {
LinkedHashMap<Pattern, View> configPerType = configuration.get(descriptor.getType());
for (Map.Entry<Pattern, View> entry : configPerType.entrySet()) {
if (entry.getKey().matcher(descriptor.getName()).matches()) {
return entry.getValue();
}
Expand All @@ -72,7 +74,7 @@ AggregatorFactory findView(InstrumentDescriptor descriptor) {
return getDefaultSpecification(descriptor);
}

private static AggregatorFactory getDefaultSpecification(InstrumentDescriptor descriptor) {
private static View getDefaultSpecification(InstrumentDescriptor descriptor) {
switch (descriptor.getType()) {
case COUNTER:
case UP_DOWN_COUNTER:
Expand All @@ -87,12 +89,10 @@ private static AggregatorFactory getDefaultSpecification(InstrumentDescriptor de
throw new IllegalArgumentException("Unknown descriptor type: " + descriptor.getType());
}

private static LinkedHashMap<Pattern, AggregatorFactory> newLinkedHashMap(
Pattern pattern,
AggregatorFactory aggregatorFactory,
LinkedHashMap<Pattern, AggregatorFactory> parentConfiguration) {
LinkedHashMap<Pattern, AggregatorFactory> result = new LinkedHashMap<>();
result.put(pattern, aggregatorFactory);
private static LinkedHashMap<Pattern, View> newLinkedHashMap(
Pattern pattern, View view, LinkedHashMap<Pattern, View> parentConfiguration) {
LinkedHashMap<Pattern, View> result = new LinkedHashMap<>();
result.put(pattern, view);
result.putAll(parentConfiguration);
return result;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.metrics.view;

import com.google.auto.value.AutoValue;
import io.opentelemetry.sdk.metrics.aggregator.AggregatorFactory;
import javax.annotation.concurrent.Immutable;

/** TODO: javadoc. */
@AutoValue
@Immutable
public abstract class View {
as-polyakov marked this conversation as resolved.
Show resolved Hide resolved
public abstract AggregatorFactory getAggregatorFactory();

public static ViewBuilder builder() {
return new ViewBuilder();
}

static View create(AggregatorFactory aggregatorFactory) {
return new AutoValue_View(aggregatorFactory);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.metrics.view;

import io.opentelemetry.sdk.metrics.aggregator.AggregatorFactory;
import java.util.Objects;

public final class ViewBuilder {
private AggregatorFactory aggregatorFactory;

ViewBuilder() {}

public ViewBuilder setAggregatorFactory(AggregatorFactory aggregatorFactory) {
this.aggregatorFactory = Objects.requireNonNull(aggregatorFactory, "aggregatorFactory");
return this;
}

public View build() {
return View.create(this.aggregatorFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.data.ValueAtPercentile;
import io.opentelemetry.sdk.metrics.view.InstrumentSelector;
import io.opentelemetry.sdk.metrics.view.View;
import io.opentelemetry.sdk.resources.Resource;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -161,7 +162,7 @@ void collectAllSyncInstruments() {
void collectAllSyncInstruments_OverwriteTemporality() {
sdkMeterProvider.registerView(
InstrumentSelector.builder().setInstrumentType(InstrumentType.COUNTER).build(),
AggregatorFactory.sum(false));
View.builder().setAggregatorFactory(AggregatorFactory.sum(false)).build());

LongCounter longCounter = sdkMeter.longCounterBuilder("testLongCounter").build();
longCounter.add(10, Labels.empty());
Expand Down Expand Up @@ -671,7 +672,8 @@ private static void registerViewForAllTypes(
SdkMeterProvider meterProvider, AggregatorFactory factory) {
for (InstrumentType instrumentType : InstrumentType.values()) {
meterProvider.registerView(
InstrumentSelector.builder().setInstrumentType(instrumentType).build(), factory);
InstrumentSelector.builder().setInstrumentType(instrumentType).build(),
View.builder().setAggregatorFactory(factory).build());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,27 @@
import io.opentelemetry.sdk.metrics.common.InstrumentType;
import io.opentelemetry.sdk.metrics.common.InstrumentValueType;
import io.opentelemetry.sdk.metrics.view.InstrumentSelector;
import io.opentelemetry.sdk.metrics.view.View;
import org.junit.jupiter.api.Test;

class ViewRegistryTest {
@Test
void selection_onType() {
AggregatorFactory factory = AggregatorFactory.lastValue();
View view = View.builder().setAggregatorFactory(factory).build();

ViewRegistry viewRegistry = new ViewRegistry();
viewRegistry.registerView(
InstrumentSelector.builder()
.setInstrumentType(InstrumentType.COUNTER)
.setInstrumentNameRegex(".*")
.build(),
factory);
view);
assertThat(
viewRegistry.findView(
InstrumentDescriptor.create(
"", "", "", InstrumentType.COUNTER, InstrumentValueType.LONG)))
.isEqualTo(factory);
.isEqualTo(view);
// this one hasn't been configured, so it gets the default still.
assertThat(
viewRegistry.findView(
Expand All @@ -42,19 +44,20 @@ void selection_onType() {
@Test
void selection_onName() {
AggregatorFactory factory = AggregatorFactory.lastValue();
View view = View.builder().setAggregatorFactory(factory).build();

ViewRegistry viewRegistry = new ViewRegistry();
viewRegistry.registerView(
InstrumentSelector.builder()
.setInstrumentType(InstrumentType.COUNTER)
.setInstrumentNameRegex("overridden")
.build(),
factory);
view);
assertThat(
viewRegistry.findView(
InstrumentDescriptor.create(
"overridden", "", "", InstrumentType.COUNTER, InstrumentValueType.LONG)))
.isSameAs(factory);
.isSameAs(view);
// this one hasn't been configured, so it gets the default still.
assertThat(
viewRegistry.findView(
Expand All @@ -66,56 +69,59 @@ void selection_onName() {
@Test
void selection_LastAddedViewWins() {
AggregatorFactory factory1 = AggregatorFactory.lastValue();
View view1 = View.builder().setAggregatorFactory(factory1).build();
AggregatorFactory factory2 = AggregatorFactory.minMaxSumCount();
View view2 = View.builder().setAggregatorFactory(factory2).build();

ViewRegistry viewRegistry = new ViewRegistry();
viewRegistry.registerView(
InstrumentSelector.builder()
.setInstrumentType(InstrumentType.COUNTER)
.setInstrumentNameRegex(".*")
.build(),
factory1);
view1);
viewRegistry.registerView(
InstrumentSelector.builder()
.setInstrumentType(InstrumentType.COUNTER)
.setInstrumentNameRegex("overridden")
.build(),
factory2);
view2);

assertThat(
viewRegistry.findView(
InstrumentDescriptor.create(
"overridden", "", "", InstrumentType.COUNTER, InstrumentValueType.LONG)))
.isEqualTo(factory2);
.isEqualTo(view2);
assertThat(
viewRegistry.findView(
InstrumentDescriptor.create(
"default", "", "", InstrumentType.COUNTER, InstrumentValueType.LONG)))
.isEqualTo(factory1);
.isEqualTo(view1);
}

@Test
void selection_regex() {
AggregatorFactory factory = AggregatorFactory.lastValue();
View view = View.builder().setAggregatorFactory(factory).build();

ViewRegistry viewRegistry = new ViewRegistry();
viewRegistry.registerView(
InstrumentSelector.builder()
.setInstrumentNameRegex("overrid(es|den)")
.setInstrumentType(InstrumentType.COUNTER)
.build(),
factory);
view);

assertThat(
viewRegistry.findView(
InstrumentDescriptor.create(
"overridden", "", "", InstrumentType.COUNTER, InstrumentValueType.LONG)))
.isEqualTo(factory);
.isEqualTo(view);
assertThat(
viewRegistry.findView(
InstrumentDescriptor.create(
"overrides", "", "", InstrumentType.COUNTER, InstrumentValueType.LONG)))
.isEqualTo(factory);
.isEqualTo(view);
// this one hasn't been configured, so it gets the default still..
assertThat(
viewRegistry.findView(
Expand Down