Skip to content

Commit

Permalink
introducing view (#2956)
Browse files Browse the repository at this point in the history
* introducing view

* code review
  • Loading branch information
as-polyakov authored Mar 2, 2021
1 parent 02ca7c2 commit c7861e8
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 38 deletions.
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 {
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

0 comments on commit c7861e8

Please sign in to comment.