Plugin aggregator for observer, add tests, fix lock. (#1018)

Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
This commit is contained in:
Bogdan Drutu 2020-03-16 13:53:13 -07:00 committed by GitHub
parent 29297249ab
commit a8401f933e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 238 additions and 8 deletions

View File

@ -17,7 +17,9 @@
package io.opentelemetry.sdk.metrics;
import io.opentelemetry.metrics.Observer;
import io.opentelemetry.sdk.metrics.common.InstrumentType;
import io.opentelemetry.sdk.metrics.common.InstrumentValueType;
import io.opentelemetry.sdk.metrics.view.Aggregations;
abstract class AbstractObserver extends AbstractInstrument {
private final boolean monotonic;
@ -33,7 +35,15 @@ abstract class AbstractObserver extends AbstractInstrument {
descriptor,
meterProviderSharedState,
meterSharedState,
new ActiveBatcher(Batchers.getNoop()));
new ActiveBatcher(
new ActiveBatcher(
getDefaultBatcher(
descriptor,
getInstrumentType(monotonic),
instrumentValueType,
meterProviderSharedState,
meterSharedState,
Aggregations.lastValue()))));
this.monotonic = monotonic;
this.instrumentValueType = instrumentValueType;
}
@ -88,4 +98,8 @@ abstract class AbstractObserver extends AbstractInstrument {
return this.monotonic;
}
}
private static InstrumentType getInstrumentType(boolean monotonic) {
return monotonic ? InstrumentType.OBSERVER_MONOTONIC : InstrumentType.OBSERVER_NON_MONOTONIC;
}
}

View File

@ -23,10 +23,12 @@ import io.opentelemetry.sdk.metrics.common.InstrumentValueType;
import io.opentelemetry.sdk.metrics.data.MetricData;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Nullable;
final class DoubleObserverSdk extends AbstractObserver implements DoubleObserver {
@Nullable private volatile Callback<ResultDoubleObserver> metricUpdater = null;
private final ReentrantLock collectLock = new ReentrantLock();
DoubleObserverSdk(
InstrumentDescriptor descriptor,
@ -35,7 +37,7 @@ final class DoubleObserverSdk extends AbstractObserver implements DoubleObserver
boolean monotonic) {
super(
descriptor,
InstrumentValueType.LONG,
InstrumentValueType.DOUBLE,
meterProviderSharedState,
meterSharedState,
monotonic);
@ -47,9 +49,14 @@ final class DoubleObserverSdk extends AbstractObserver implements DoubleObserver
if (currentMetricUpdater == null) {
return Collections.emptyList();
}
final ActiveBatcher activeBatcher = getActiveBatcher();
currentMetricUpdater.update(new ResultDoubleObserverSdk(activeBatcher, isMonotonic()));
return activeBatcher.completeCollectionCycle();
collectLock.lock();
try {
final ActiveBatcher activeBatcher = getActiveBatcher();
currentMetricUpdater.update(new ResultDoubleObserverSdk(activeBatcher, isMonotonic()));
return activeBatcher.completeCollectionCycle();
} finally {
collectLock.unlock();
}
}
@Override

View File

@ -23,10 +23,12 @@ import io.opentelemetry.sdk.metrics.common.InstrumentValueType;
import io.opentelemetry.sdk.metrics.data.MetricData;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Nullable;
final class LongObserverSdk extends AbstractObserver implements LongObserver {
@Nullable private volatile Callback<ResultLongObserver> metricUpdater = null;
private final ReentrantLock collectLock = new ReentrantLock();
LongObserverSdk(
InstrumentDescriptor descriptor,
@ -47,9 +49,14 @@ final class LongObserverSdk extends AbstractObserver implements LongObserver {
if (currentMetricUpdater == null) {
return Collections.emptyList();
}
final ActiveBatcher activeBatcher = getActiveBatcher();
currentMetricUpdater.update(new ResultLongObserverSdk(activeBatcher, isMonotonic()));
return activeBatcher.completeCollectionCycle();
collectLock.lock();
try {
final ActiveBatcher activeBatcher = getActiveBatcher();
currentMetricUpdater.update(new ResultLongObserverSdk(activeBatcher, isMonotonic()));
return activeBatcher.completeCollectionCycle();
} finally {
collectLock.unlock();
}
}
@Override

View File

@ -16,11 +16,18 @@
package io.opentelemetry.sdk.metrics;
import static com.google.common.truth.Truth.assertThat;
import io.opentelemetry.common.AttributeValue;
import io.opentelemetry.metrics.DoubleObserver.ResultDoubleObserver;
import io.opentelemetry.metrics.Observer.Callback;
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.Point;
import io.opentelemetry.sdk.resources.Resource;
import java.util.Collections;
import org.junit.Rule;
@ -34,6 +41,7 @@ import org.junit.runners.JUnit4;
public class DoubleObserverSdkTest {
@Rule public ExpectedException thrown = ExpectedException.none();
private static final long SECOND_NANOS = 1_000_000_000;
private static final Resource RESOURCE =
Resource.create(
Collections.singletonMap(
@ -46,6 +54,99 @@ public class DoubleObserverSdkTest {
private final MeterSdk testSdk =
new MeterSdk(meterProviderSharedState, INSTRUMENTATION_LIBRARY_INFO);
@Test
public void collectMetrics_NoCallback() {
DoubleObserverSdk doubleObserver =
testSdk
.doubleObserverBuilder("testObserver")
.setConstantLabels(Collections.singletonMap("sk1", "sv1"))
.setLabelKeys(Collections.singletonList("sk1"))
.setDescription("My very own measure")
.setUnit("ms")
.build();
assertThat(doubleObserver.collectAll()).isEmpty();
}
@Test
public void collectMetrics_NoRecords() {
DoubleObserverSdk doubleObserver =
testSdk
.doubleObserverBuilder("testObserver")
.setConstantLabels(Collections.singletonMap("sk1", "sv1"))
.setLabelKeys(Collections.singletonList("sk1"))
.setDescription("My very own measure")
.setUnit("ms")
.build();
doubleObserver.setCallback(
new Callback<ResultDoubleObserver>() {
@Override
public void update(ResultDoubleObserver result) {
// Do nothing.
}
});
assertThat(doubleObserver.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
"testObserver",
"My very own measure",
"ms",
Type.NON_MONOTONIC_DOUBLE,
Collections.singletonMap("sk1", "sv1")),
RESOURCE,
INSTRUMENTATION_LIBRARY_INFO,
Collections.<Point>emptyList()));
}
@Test
public void collectMetrics_WithOneRecord() {
DoubleObserverSdk doubleObserver =
testSdk.doubleObserverBuilder("testObserver").setMonotonic(true).build();
doubleObserver.setCallback(
new Callback<ResultDoubleObserver>() {
@Override
public void update(ResultDoubleObserver result) {
result.observe(12.1d, "k", "v");
}
});
testClock.advanceNanos(SECOND_NANOS);
assertThat(doubleObserver.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
"testObserver",
"",
"1",
Type.MONOTONIC_DOUBLE,
Collections.<String, String>emptyMap()),
RESOURCE,
INSTRUMENTATION_LIBRARY_INFO,
Collections.<Point>singletonList(
DoublePoint.create(
testClock.now() - SECOND_NANOS,
testClock.now(),
Collections.singletonMap("k", "v"),
12.1d))));
testClock.advanceNanos(SECOND_NANOS);
assertThat(doubleObserver.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
"testObserver",
"",
"1",
Type.MONOTONIC_DOUBLE,
Collections.<String, String>emptyMap()),
RESOURCE,
INSTRUMENTATION_LIBRARY_INFO,
Collections.<Point>singletonList(
DoublePoint.create(
testClock.now() - 2 * SECOND_NANOS,
testClock.now(),
Collections.singletonMap("k", "v"),
12.1d))));
}
@Test
public void observeMonotonic_NegativeValue() {
DoubleObserverSdk doubleObserver =

View File

@ -16,11 +16,18 @@
package io.opentelemetry.sdk.metrics;
import static com.google.common.truth.Truth.assertThat;
import io.opentelemetry.common.AttributeValue;
import io.opentelemetry.metrics.LongObserver.ResultLongObserver;
import io.opentelemetry.metrics.Observer.Callback;
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;
@ -34,6 +41,7 @@ import org.junit.runners.JUnit4;
public class LongObserverSdkTest {
@Rule public ExpectedException thrown = ExpectedException.none();
private static final long SECOND_NANOS = 1_000_000_000;
private static final Resource RESOURCE =
Resource.create(
Collections.singletonMap(
@ -46,6 +54,99 @@ public class LongObserverSdkTest {
private final MeterSdk testSdk =
new MeterSdk(meterProviderSharedState, INSTRUMENTATION_LIBRARY_INFO);
@Test
public void collectMetrics_NoCallback() {
LongObserverSdk longObserver =
testSdk
.longObserverBuilder("testObserver")
.setConstantLabels(Collections.singletonMap("sk1", "sv1"))
.setLabelKeys(Collections.singletonList("sk1"))
.setDescription("My very own measure")
.setUnit("ms")
.build();
assertThat(longObserver.collectAll()).isEmpty();
}
@Test
public void collectMetrics_NoRecords() {
LongObserverSdk longObserver =
testSdk
.longObserverBuilder("testObserver")
.setConstantLabels(Collections.singletonMap("sk1", "sv1"))
.setLabelKeys(Collections.singletonList("sk1"))
.setDescription("My very own measure")
.setUnit("ms")
.build();
longObserver.setCallback(
new Callback<ResultLongObserver>() {
@Override
public void update(ResultLongObserver result) {
// Do nothing.
}
});
assertThat(longObserver.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
"testObserver",
"My very own measure",
"ms",
Type.NON_MONOTONIC_LONG,
Collections.singletonMap("sk1", "sv1")),
RESOURCE,
INSTRUMENTATION_LIBRARY_INFO,
Collections.<Point>emptyList()));
}
@Test
public void collectMetrics_WithOneRecord() {
LongObserverSdk longObserver =
testSdk.longObserverBuilder("testObserver").setMonotonic(true).build();
longObserver.setCallback(
new Callback<ResultLongObserver>() {
@Override
public void update(ResultLongObserver result) {
result.observe(12, "k", "v");
}
});
testClock.advanceNanos(SECOND_NANOS);
assertThat(longObserver.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
"testObserver",
"",
"1",
Type.MONOTONIC_LONG,
Collections.<String, String>emptyMap()),
RESOURCE,
INSTRUMENTATION_LIBRARY_INFO,
Collections.<Point>singletonList(
LongPoint.create(
testClock.now() - SECOND_NANOS,
testClock.now(),
Collections.singletonMap("k", "v"),
12))));
testClock.advanceNanos(SECOND_NANOS);
assertThat(longObserver.collectAll())
.containsExactly(
MetricData.create(
Descriptor.create(
"testObserver",
"",
"1",
Type.MONOTONIC_LONG,
Collections.<String, String>emptyMap()),
RESOURCE,
INSTRUMENTATION_LIBRARY_INFO,
Collections.<Point>singletonList(
LongPoint.create(
testClock.now() - 2 * SECOND_NANOS,
testClock.now(),
Collections.singletonMap("k", "v"),
12))));
}
@Test
public void observeMonotonic_NegativeValue() {
LongObserverSdk longObserver =