Add collectAll method to the Meter and MeterProvider (#942)

* Add collectAll method to the Meter and MeterProvider

Signed-off-by: Bogdan Cristian Drutu <bogdandrutu@gmail.com>

* Minor fixes from the review.

Signed-off-by: Bogdan Cristian Drutu <bogdandrutu@gmail.com>
This commit is contained in:
Bogdan Drutu 2020-02-27 15:02:13 -08:00 committed by GitHub
parent dc68060ddd
commit ecf7067a14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 193 additions and 29 deletions

View File

@ -17,6 +17,9 @@
package io.opentelemetry.sdk.internal;
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.annotation.Nullable;
@ -38,7 +41,7 @@ public abstract class ComponentRegistry<V> {
* @param instrumentationName the name of the instrumentation library.
* @return the registered value associated with this name and {@code null} version.
*/
public V get(String instrumentationName) {
public final V get(String instrumentationName) {
return get(instrumentationName, null);
}
@ -50,7 +53,7 @@ public abstract class ComponentRegistry<V> {
* @param instrumentationVersion the version of the instrumentation library.
* @return the registered value associated with this name and version.
*/
public V get(String instrumentationName, @Nullable String instrumentationVersion) {
public final V get(String instrumentationName, @Nullable String instrumentationVersion) {
InstrumentationLibraryInfo instrumentationLibraryInfo =
InstrumentationLibraryInfo.create(instrumentationName, instrumentationVersion);
@ -64,5 +67,14 @@ public abstract class ComponentRegistry<V> {
return oldComponent != null ? oldComponent : newComponent;
}
/**
* Returns a {@code Collection} view of the registered components.
*
* @return a {@code Collection} view of the registered components.
*/
public final Collection<V> getComponents() {
return Collections.unmodifiableCollection(new ArrayList<>(registry.values()));
}
public abstract V newComponent(InstrumentationLibraryInfo instrumentationLibraryInfo);
}

View File

@ -61,7 +61,7 @@ abstract class AbstractInstrument implements Instrument {
return activeBatcher;
}
abstract List<MetricData> collect();
abstract List<MetricData> collectAll();
@Override
public boolean equals(Object o) {

View File

@ -71,7 +71,7 @@ abstract class AbstractInstrumentWithBinding<B extends AbstractBoundInstrument>
* call.
*/
@Override
final List<MetricData> collect() {
final List<MetricData> collectAll() {
collectLock.lock();
try {
Batcher batcher = getActiveBatcher();

View File

@ -46,7 +46,7 @@ class AbstractObserver extends AbstractInstrument {
}
@Override
List<MetricData> collect() {
List<MetricData> collectAll() {
// TODO: Implement this.
return Collections.emptyList();
}

View File

@ -19,6 +19,10 @@ package io.opentelemetry.sdk.metrics;
import io.opentelemetry.metrics.LabelSet;
import io.opentelemetry.metrics.Meter;
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
import io.opentelemetry.sdk.metrics.data.MetricData;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/** {@link MeterSdk} is SDK implementation of {@link Meter}. */
@ -81,4 +85,14 @@ final class MeterSdk implements Meter {
public LabelSetSdk createLabelSet(Map<String, String> labels) {
return LabelSetSdk.create(labels);
}
Collection<MetricData> collectAll() {
InstrumentRegistry instrumentRegistry = meterSharedState.getInstrumentRegistry();
Collection<AbstractInstrument> instruments = instrumentRegistry.getInstruments();
List<MetricData> result = new ArrayList<>(instruments.size());
for (AbstractInstrument instrument : instruments) {
result.addAll(instrument.collectAll());
}
return result;
}
}

View File

@ -22,8 +22,13 @@ import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
import io.opentelemetry.sdk.internal.ComponentRegistry;
import io.opentelemetry.sdk.internal.MillisClock;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.resources.EnvVarResource;
import io.opentelemetry.sdk.resources.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
/**
@ -50,6 +55,20 @@ public final class MeterSdkProvider implements MeterProvider {
return registry.get(instrumentationName, instrumentationVersion);
}
/**
* Collects all the metrics and returns a collection of collected {@link MetricData}.
*
* @return a collection of collected {@link MetricData}.
*/
public Collection<MetricData> collectAll() {
Collection<MeterSdk> meters = registry.getComponents();
List<MetricData> result = new ArrayList<>(meters.size());
for (MeterSdk meter : meters) {
result.addAll(meter.collectAll());
}
return Collections.unmodifiableCollection(result);
}
/**
* Returns a new {@link Builder} for {@link MeterSdkProvider}.
*

View File

@ -196,7 +196,7 @@ public class AbstractInstrumentBuilderTest {
}
@Override
List<MetricData> collect() {
List<MetricData> collectAll() {
return Collections.emptyList();
}
}

View File

@ -68,7 +68,7 @@ public class AbstractInstrumentTest {
}
@Override
List<MetricData> collect() {
List<MetricData> collectAll() {
return Collections.emptyList();
}
}

View File

@ -74,7 +74,7 @@ public class BatchRecorderSdkTest {
.put(doubleMeasure, 13.1d)
.record();
assertThat(doubleCounter.collect())
assertThat(doubleCounter.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
@ -88,7 +88,7 @@ public class BatchRecorderSdkTest {
Collections.<Point>singletonList(
DoublePoint.create(
testClock.now(), testClock.now(), labelSet.getLabels(), 12.1d))));
assertThat(longCounter.collect())
assertThat(longCounter.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(

View File

@ -67,7 +67,7 @@ public class DoubleCounterSdkTest {
.setMonotonic(true)
.build();
assertThat(doubleCounter).isInstanceOf(DoubleCounterSdk.class);
List<MetricData> metricDataList = ((DoubleCounterSdk) doubleCounter).collect();
List<MetricData> metricDataList = ((DoubleCounterSdk) doubleCounter).collectAll();
assertThat(metricDataList).hasSize(1);
MetricData metricData = metricDataList.get(0);
assertThat(metricData.getDescriptor())
@ -88,7 +88,7 @@ public class DoubleCounterSdkTest {
DoubleCounterSdk doubleCounter = testSdk.doubleCounterBuilder("testCounter").build();
testClock.advanceNanos(SECOND_NANOS);
doubleCounter.add(12.1d, testSdk.createLabelSet());
List<MetricData> metricDataList = doubleCounter.collect();
List<MetricData> metricDataList = doubleCounter.collectAll();
assertThat(metricDataList).hasSize(1);
MetricData metricData = metricDataList.get(0);
assertThat(metricData.getResource()).isEqualTo(RESOURCE);
@ -123,7 +123,7 @@ public class DoubleCounterSdkTest {
doubleCounter.add(111.1d, labelSet);
long firstCollect = testClock.now();
List<MetricData> metricDataList = doubleCounter.collect();
List<MetricData> metricDataList = doubleCounter.collectAll();
assertThat(metricDataList).hasSize(1);
MetricData metricData = metricDataList.get(0);
assertThat(metricData.getPoints()).hasSize(2);
@ -138,7 +138,7 @@ public class DoubleCounterSdkTest {
doubleCounter.add(11d, emptyLabelSet);
long secondCollect = testClock.now();
metricDataList = doubleCounter.collect();
metricDataList = doubleCounter.collectAll();
assertThat(metricDataList).hasSize(1);
metricData = metricDataList.get(0);
assertThat(metricData.getPoints()).hasSize(2);
@ -169,7 +169,7 @@ public class DoubleCounterSdkTest {
DoubleCounterSdk doubleCounter = testSdk.doubleCounterBuilder("testCounter").build();
BoundDoubleCounter boundCounter = doubleCounter.bind(testSdk.createLabelSet("K", "v"));
try {
doubleCounter.collect();
doubleCounter.collectAll();
BoundDoubleCounter duplicateBoundCounter =
doubleCounter.bind(testSdk.createLabelSet("K", "v"));
try {
@ -202,7 +202,7 @@ public class DoubleCounterSdkTest {
}
stressTestBuilder.build().run();
List<MetricData> metricDataList = doubleCounter.collect();
List<MetricData> metricDataList = doubleCounter.collectAll();
assertThat(metricDataList).hasSize(1);
assertThat(metricDataList.get(0).getPoints())
.containsExactly(
@ -235,7 +235,7 @@ public class DoubleCounterSdkTest {
}
stressTestBuilder.build().run();
List<MetricData> metricDataList = doubleCounter.collect();
List<MetricData> metricDataList = doubleCounter.collectAll();
assertThat(metricDataList).hasSize(1);
assertThat(metricDataList.get(0).getPoints())
.containsExactly(

View File

@ -66,7 +66,7 @@ public class DoubleMeasureSdkTest {
DoubleMeasureSdk doubleMeasure = testSdk.doubleMeasureBuilder("testMeasure").build();
BoundDoubleMeasure boundMeasure = doubleMeasure.bind(testSdk.createLabelSet("K", "v"));
try {
doubleMeasure.collect();
doubleMeasure.collectAll();
BoundDoubleMeasure duplicateBoundMeasure =
doubleMeasure.bind(testSdk.createLabelSet("K", "v"));
try {

View File

@ -130,7 +130,7 @@ public class InstrumentRegistryTest {
}
@Override
List<MetricData> collect() {
List<MetricData> collectAll() {
return Collections.emptyList();
}
}
@ -145,7 +145,7 @@ public class InstrumentRegistryTest {
}
@Override
List<MetricData> collect() {
List<MetricData> collectAll() {
return Collections.emptyList();
}
}

View File

@ -68,7 +68,7 @@ public class LongCounterSdkTest {
.setMonotonic(true)
.build();
assertThat(longCounter).isInstanceOf(LongCounterSdk.class);
List<MetricData> metricDataList = ((LongCounterSdk) longCounter).collect();
List<MetricData> metricDataList = ((LongCounterSdk) longCounter).collectAll();
assertThat(metricDataList).hasSize(1);
MetricData metricData = metricDataList.get(0);
assertThat(metricData.getDescriptor())
@ -89,7 +89,7 @@ public class LongCounterSdkTest {
LongCounterSdk longCounter = testSdk.longCounterBuilder("testCounter").build();
testClock.advanceNanos(SECOND_NANOS);
longCounter.add(12, testSdk.createLabelSet());
List<MetricData> metricDataList = longCounter.collect();
List<MetricData> metricDataList = longCounter.collectAll();
assertThat(metricDataList).hasSize(1);
MetricData metricData = metricDataList.get(0);
assertThat(metricData.getResource()).isEqualTo(RESOURCE);
@ -124,7 +124,7 @@ public class LongCounterSdkTest {
longCounter.add(111, labelSet);
long firstCollect = testClock.now();
List<MetricData> metricDataList = longCounter.collect();
List<MetricData> metricDataList = longCounter.collectAll();
assertThat(metricDataList).hasSize(1);
MetricData metricData = metricDataList.get(0);
assertThat(metricData.getPoints()).hasSize(2);
@ -139,7 +139,7 @@ public class LongCounterSdkTest {
longCounter.add(11, emptyLabelSet);
long secondCollect = testClock.now();
metricDataList = longCounter.collect();
metricDataList = longCounter.collectAll();
assertThat(metricDataList).hasSize(1);
metricData = metricDataList.get(0);
assertThat(metricData.getPoints()).hasSize(2);
@ -171,7 +171,7 @@ public class LongCounterSdkTest {
}
stressTestBuilder.build().run();
List<MetricData> metricDataList = longCounter.collect();
List<MetricData> metricDataList = longCounter.collectAll();
assertThat(metricDataList).hasSize(1);
assertThat(metricDataList.get(0).getPoints())
.containsExactly(
@ -202,7 +202,7 @@ public class LongCounterSdkTest {
}
stressTestBuilder.build().run();
List<MetricData> metricDataList = longCounter.collect();
List<MetricData> metricDataList = longCounter.collectAll();
assertThat(metricDataList).hasSize(1);
assertThat(metricDataList.get(0).getPoints())
.containsExactly(
@ -246,7 +246,7 @@ public class LongCounterSdkTest {
LongCounterSdk longCounter = testSdk.longCounterBuilder("testCounter").build();
BoundLongCounter boundCounter = longCounter.bind(testSdk.createLabelSet("K", "v"));
try {
longCounter.collect();
longCounter.collectAll();
BoundLongCounter duplicateBoundCounter = longCounter.bind(testSdk.createLabelSet("K", "v"));
try {
assertThat(duplicateBoundCounter).isEqualTo(boundCounter);

View File

@ -66,7 +66,7 @@ public class LongMeasureSdkTest {
LongMeasureSdk longMeasure = testSdk.longMeasureBuilder("testMeasure").build();
BoundLongMeasure boundMeasure = longMeasure.bind(testSdk.createLabelSet("K", "v"));
try {
longMeasure.collect();
longMeasure.collectAll();
BoundLongMeasure duplicateBoundMeasure = longMeasure.bind(testSdk.createLabelSet("K", "v"));
try {
assertThat(duplicateBoundMeasure).isEqualTo(boundMeasure);

View File

@ -19,9 +19,17 @@ package io.opentelemetry.sdk.metrics;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import io.opentelemetry.metrics.LongCounter;
import io.opentelemetry.sdk.common.Clock;
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
import io.opentelemetry.sdk.internal.TestClock;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.data.MetricData.Descriptor;
import io.opentelemetry.sdk.metrics.data.MetricData.Descriptor.Type;
import io.opentelemetry.sdk.metrics.data.MetricData.LongPoint;
import io.opentelemetry.sdk.metrics.data.MetricData.Point;
import io.opentelemetry.sdk.resources.Resource;
import java.util.Collections;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@ -33,7 +41,9 @@ import org.junit.runners.JUnit4;
public class MeterSdkRegistryTest {
@Rule public final ExpectedException thrown = ExpectedException.none();
private final MeterSdkProvider meterRegistry = MeterSdkProvider.builder().build();
private final TestClock testClock = TestClock.create();
private final MeterSdkProvider meterRegistry =
MeterSdkProvider.builder().setClock(testClock).setResource(Resource.getEmpty()).build();
@Test
public void builder_HappyPath() {
@ -83,4 +93,47 @@ public class MeterSdkRegistryTest {
MeterSdk meter = meterRegistry.get(expected.getName(), expected.getVersion());
assertThat(meter.getInstrumentationLibraryInfo()).isEqualTo(expected);
}
@Test
public void collectAll() {
MeterSdk meterSdk1 = meterRegistry.get("io.opentelemetry.sdk.metrics.MeterSdkRegistryTest_1");
LongCounter longCounter1 = meterSdk1.longCounterBuilder("testLongCounter").build();
longCounter1.add(10, meterSdk1.createLabelSet());
MeterSdk meterSdk2 = meterRegistry.get("io.opentelemetry.sdk.metrics.MeterSdkRegistryTest_2");
LongCounter longCounter2 = meterSdk2.longCounterBuilder("testLongCounter").build();
longCounter2.add(10, meterSdk2.createLabelSet());
assertThat(meterRegistry.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
"testLongCounter",
"",
"1",
Type.MONOTONIC_LONG,
Collections.<String, String>emptyMap()),
Resource.getEmpty(),
meterSdk1.getInstrumentationLibraryInfo(),
Collections.<Point>singletonList(
LongPoint.create(
testClock.now(),
testClock.now(),
Collections.<String, String>emptyMap(),
10))),
MetricData.create(
Descriptor.create(
"testLongCounter",
"",
"1",
Type.MONOTONIC_LONG,
Collections.<String, String>emptyMap()),
Resource.getEmpty(),
meterSdk2.getInstrumentationLibraryInfo(),
Collections.<Point>singletonList(
LongPoint.create(
testClock.now(),
testClock.now(),
Collections.<String, String>emptyMap(),
10))));
}
}

View File

@ -26,6 +26,16 @@ import io.opentelemetry.metrics.DoubleObserver;
import io.opentelemetry.metrics.LongCounter;
import io.opentelemetry.metrics.LongMeasure;
import io.opentelemetry.metrics.LongObserver;
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
import io.opentelemetry.sdk.internal.TestClock;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.metrics.data.MetricData.Descriptor;
import io.opentelemetry.sdk.metrics.data.MetricData.Descriptor.Type;
import io.opentelemetry.sdk.metrics.data.MetricData.DoublePoint;
import io.opentelemetry.sdk.metrics.data.MetricData.LongPoint;
import io.opentelemetry.sdk.metrics.data.MetricData.Point;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.trace.AttributeValue;
import java.util.Collections;
import org.junit.Rule;
import org.junit.Test;
@ -36,8 +46,17 @@ import org.junit.runners.JUnit4;
/** Unit tests for {@link MeterSdk}. */
@RunWith(JUnit4.class)
public class MeterSdkTest {
private static final Resource RESOURCE =
Resource.create(
Collections.singletonMap(
"resource_key", AttributeValue.stringAttributeValue("resource_value")));
private static final InstrumentationLibraryInfo INSTRUMENTATION_LIBRARY_INFO =
InstrumentationLibraryInfo.create("io.opentelemetry.sdk.metrics.MeterSdkTest", null);
private final TestClock testClock = TestClock.create();
private final MeterProviderSharedState meterProviderSharedState =
MeterProviderSharedState.create(testClock, RESOURCE);
private final MeterSdk testSdk =
MeterSdkProvider.builder().build().get("io.opentelemetry.sdk.metrics.MeterSdkTest");
new MeterSdk(meterProviderSharedState, INSTRUMENTATION_LIBRARY_INFO);
@Rule public final ExpectedException thrown = ExpectedException.none();
@ -228,6 +247,53 @@ public class MeterSdkTest {
assertThat(batchRecorder).isInstanceOf(BatchRecorderSdk.class);
}
@Test
public void collectAll() {
LongCounter longCounter = testSdk.longCounterBuilder("testLongCounter").build();
longCounter.add(10, testSdk.createLabelSet());
LongMeasure longMeasure = testSdk.longMeasureBuilder("testLongMeasure").build();
longMeasure.record(10, testSdk.createLabelSet());
// LongObserver longObserver = testSdk.longObserverBuilder("testLongObserver").build();
DoubleCounter doubleCounter = testSdk.doubleCounterBuilder("testDoubleCounter").build();
doubleCounter.add(10.1, testSdk.createLabelSet());
DoubleMeasure doubleMeasure = testSdk.doubleMeasureBuilder("testDoubleMeasure").build();
doubleMeasure.record(10.1, testSdk.createLabelSet());
// DoubleObserver doubleObserver = testSdk.doubleObserverBuilder("testDoubleObserver").build();
assertThat(testSdk.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
"testLongCounter",
"",
"1",
Type.MONOTONIC_LONG,
Collections.<String, String>emptyMap()),
RESOURCE,
INSTRUMENTATION_LIBRARY_INFO,
Collections.<Point>singletonList(
LongPoint.create(
testClock.now(),
testClock.now(),
Collections.<String, String>emptyMap(),
10))),
MetricData.create(
Descriptor.create(
"testDoubleCounter",
"",
"1",
Type.MONOTONIC_DOUBLE,
Collections.<String, String>emptyMap()),
RESOURCE,
INSTRUMENTATION_LIBRARY_INFO,
Collections.<Point>singletonList(
DoublePoint.create(
testClock.now(),
testClock.now(),
Collections.<String, String>emptyMap(),
10.1))));
}
@Test
public void testLabelSets() {
assertThat(testSdk.createLabelSet()).isSameInstanceAs(testSdk.createLabelSet());