Drop micrometer shim (#4735)
* Drop micrometer shim * Remove remnants of micrometer-shim
This commit is contained in:
parent
c3a9f68ec8
commit
1046253f3f
|
|
@ -47,7 +47,6 @@ This project contains the following top level components:
|
|||
* [sdk-extensions](sdk-extensions/) defines additional SDK extensions, which are not part of the core SDK.
|
||||
* [OpenTracing shim](opentracing-shim/) defines a bridge layer from OpenTracing to the OpenTelemetry API.
|
||||
* [OpenCensus shim](opencensus-shim/) defines a bridge layer from OpenCensus to the OpenTelemetry API.
|
||||
* [Micrometer shim](micrometer1-shim/) defines a bridge layer from Micrometer to the OpenTelemetry API.
|
||||
|
||||
This project publishes a lot of artifacts, listed in [releases](#releases).
|
||||
[`opentelemetry-bom`](https://mvnrepository.com/artifact/io.opentelemetry/opentelemetry-bom) (BOM =
|
||||
|
|
@ -280,7 +279,6 @@ dependency as follows, replacing `{{artifact-id}}` with the value from the "Arti
|
|||
|
||||
| Component | Description | Artifact ID | Version |
|
||||
|----------------------------------------|--------------------------------------------------------------|----------------------------------|-------------------------------------------------------------|
|
||||
| [Micrometer Shim](./micrometer1-shim) | Bridge micrometer metrics into the OpenTelemetry metrics API | `opentelemetry-micrometer1-shim` | <!--VERSION_UNSTABLE-->1.17.0-alpha<!--/VERSION_UNSTABLE--> |
|
||||
| [OpenCensus Shim](./opencensus-shim) | Bridge opencensus metrics into the OpenTelemetry metrics SDK | `opentelemetry-opencensus-shim` | <!--VERSION_UNSTABLE-->1.17.0-alpha<!--/VERSION_UNSTABLE--> |
|
||||
| [OpenTracing Shim](./opentracing-shim) | Bridge opentracing spans into the OpenTelemetry trace API | `opentelemetry-opentracing-shim` | <!--VERSION_UNSTABLE-->1.17.0-alpha<!--/VERSION_UNSTABLE--> |
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ val DEPENDENCY_BOMS = listOf(
|
|||
"com.linecorp.armeria:armeria-bom:1.18.0",
|
||||
"com.squareup.okhttp3:okhttp-bom:4.10.0",
|
||||
"io.grpc:grpc-bom:1.49.0",
|
||||
"io.micrometer:micrometer-bom:1.9.3",
|
||||
"io.zipkin.brave:brave-bom:5.13.11",
|
||||
"io.zipkin.reporter2:zipkin-reporter-bom:2.16.3",
|
||||
"org.junit:junit-bom:5.9.0",
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
plugins {
|
||||
id("otel.java-conventions")
|
||||
id("otel.publish-conventions")
|
||||
}
|
||||
|
||||
description = "OpenTelemetry Micrometer Bridge"
|
||||
otelJava.moduleName.set("io.opentelemetry.micrometer1shim")
|
||||
|
||||
dependencies {
|
||||
api(project(":api:all"))
|
||||
|
||||
api("io.micrometer:micrometer-core")
|
||||
|
||||
testImplementation(project(":sdk:testing"))
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
// Test older LTS versions
|
||||
val testMicrometer15 by registering(JvmTestSuite::class) {
|
||||
sources {
|
||||
java {
|
||||
setSrcDirs(listOf("src/test/java"))
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation(project(":sdk:testing"))
|
||||
|
||||
implementation(project.dependencies.enforcedPlatform("io.micrometer:micrometer-bom:1.5.17"))
|
||||
}
|
||||
}
|
||||
val testMicrometer16 by registering(JvmTestSuite::class) {
|
||||
sources {
|
||||
java {
|
||||
setSrcDirs(listOf("src/test/java"))
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation(project(":sdk:testing"))
|
||||
|
||||
implementation(project.dependencies.enforcedPlatform("io.micrometer:micrometer-bom:1.6.13"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
check {
|
||||
dependsOn(testing.suites)
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
otel.release=alpha
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.Statistic;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
final class Bridging {
|
||||
|
||||
private static final ConcurrentMap<String, String> descriptionsCache = new ConcurrentHashMap<>();
|
||||
|
||||
static Attributes tagsAsAttributes(Meter.Id id, NamingConvention namingConvention) {
|
||||
Iterable<Tag> tags = id.getTagsAsIterable();
|
||||
if (!tags.iterator().hasNext()) {
|
||||
return Attributes.empty();
|
||||
}
|
||||
AttributesBuilder builder = Attributes.builder();
|
||||
for (Tag tag : tags) {
|
||||
String tagKey = namingConvention.tagKey(tag.getKey());
|
||||
String tagValue = namingConvention.tagValue(tag.getValue());
|
||||
builder.put(tagKey, tagValue);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static String name(Meter.Id id, NamingConvention namingConvention) {
|
||||
return namingConvention.name(id.getName(), id.getType(), id.getBaseUnit());
|
||||
}
|
||||
|
||||
static String description(Meter.Id id) {
|
||||
return descriptionsCache.computeIfAbsent(
|
||||
id.getName(),
|
||||
n -> {
|
||||
String description = id.getDescription();
|
||||
return description != null ? description : "";
|
||||
});
|
||||
}
|
||||
|
||||
static String baseUnit(Meter.Id id) {
|
||||
String baseUnit = id.getBaseUnit();
|
||||
return baseUnit == null ? "1" : baseUnit;
|
||||
}
|
||||
|
||||
static String statisticInstrumentName(
|
||||
Meter.Id id, Statistic statistic, NamingConvention namingConvention) {
|
||||
String prefix = id.getName() + ".";
|
||||
// use "total_time" instead of "total" to avoid clashing with Statistic.TOTAL
|
||||
String statisticStr =
|
||||
statistic == Statistic.TOTAL_TIME ? "total_time" : statistic.getTagValueRepresentation();
|
||||
return namingConvention.name(prefix + statisticStr, id.getType(), id.getBaseUnit());
|
||||
}
|
||||
|
||||
private Bridging() {}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
final class DoubleMeasurementRecorder<T> implements Consumer<ObservableDoubleMeasurement> {
|
||||
|
||||
// using a weak reference here so that the existence of the micrometer Meter does not block the
|
||||
// measured object from being GC'd; e.g. a Gauge (or any other async instrument) must not block
|
||||
// garbage collection of the object that it measures
|
||||
private final WeakReference<T> objWeakRef;
|
||||
private final ToDoubleFunction<T> metricFunction;
|
||||
private final Attributes attributes;
|
||||
|
||||
DoubleMeasurementRecorder(
|
||||
@Nullable T obj, ToDoubleFunction<T> metricFunction, Attributes attributes) {
|
||||
this.objWeakRef = new WeakReference<>(obj);
|
||||
this.metricFunction = metricFunction;
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ObservableDoubleMeasurement measurement) {
|
||||
T obj = objWeakRef.get();
|
||||
if (obj != null) {
|
||||
measurement.record(metricFunction.applyAsDouble(obj), attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.ToLongFunction;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
final class LongMeasurementRecorder<T> implements Consumer<ObservableLongMeasurement> {
|
||||
|
||||
// using a weak reference here so that the existence of the micrometer Meter does not block the
|
||||
// measured object from being GC'd; e.g. a Gauge (or any other async instrument) must not block
|
||||
// garbage collection of the object that it measures
|
||||
private final WeakReference<T> objWeakRef;
|
||||
private final ToLongFunction<T> metricFunction;
|
||||
private final Attributes attributes;
|
||||
|
||||
LongMeasurementRecorder(
|
||||
@Nullable T obj, ToLongFunction<T> metricFunction, Attributes attributes) {
|
||||
this.objWeakRef = new WeakReference<>(obj);
|
||||
this.metricFunction = metricFunction;
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ObservableLongMeasurement measurement) {
|
||||
T obj = objWeakRef.get();
|
||||
if (obj != null) {
|
||||
measurement.record(metricFunction.applyAsLong(obj), attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.baseUnit;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.name;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.tagsAsAttributes;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractMeter;
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.DoubleCounter;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import java.util.Collections;
|
||||
|
||||
final class OpenTelemetryCounter extends AbstractMeter implements Counter, RemovableMeter {
|
||||
|
||||
// TODO: use bound instruments when they're available
|
||||
private final DoubleCounter otelCounter;
|
||||
private final Attributes attributes;
|
||||
|
||||
private volatile boolean removed = false;
|
||||
|
||||
OpenTelemetryCounter(Id id, NamingConvention namingConvention, Meter otelMeter) {
|
||||
super(id);
|
||||
|
||||
this.attributes = tagsAsAttributes(id, namingConvention);
|
||||
String conventionName = name(id, namingConvention);
|
||||
this.otelCounter =
|
||||
otelMeter
|
||||
.counterBuilder(conventionName)
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(baseUnit(id))
|
||||
.ofDoubles()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment(double v) {
|
||||
if (removed) {
|
||||
return;
|
||||
}
|
||||
otelCounter.add(v, attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double count() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Measurement> measure() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.baseUnit;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.name;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.tagsAsAttributes;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractDistributionSummary;
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.core.instrument.distribution.NoopHistogram;
|
||||
import io.micrometer.core.instrument.distribution.TimeWindowMax;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.DoubleHistogram;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableDoubleGauge;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.DoubleAdder;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
final class OpenTelemetryDistributionSummary extends AbstractDistributionSummary
|
||||
implements RemovableMeter {
|
||||
|
||||
private final Measurements measurements;
|
||||
private final TimeWindowMax max;
|
||||
// TODO: use bound instruments when they're available
|
||||
private final DoubleHistogram otelHistogram;
|
||||
private final Attributes attributes;
|
||||
private final ObservableDoubleGauge observableMax;
|
||||
|
||||
private volatile boolean removed = false;
|
||||
|
||||
OpenTelemetryDistributionSummary(
|
||||
Id id,
|
||||
NamingConvention namingConvention,
|
||||
Clock clock,
|
||||
DistributionStatisticConfig distributionStatisticConfig,
|
||||
double scale,
|
||||
Meter otelMeter) {
|
||||
super(id, clock, distributionStatisticConfig, scale, false);
|
||||
|
||||
if (isUsingMicrometerHistograms()) {
|
||||
measurements = new MicrometerHistogramMeasurements();
|
||||
} else {
|
||||
measurements = NoopMeasurements.INSTANCE;
|
||||
}
|
||||
max = new TimeWindowMax(clock, distributionStatisticConfig);
|
||||
|
||||
this.attributes = tagsAsAttributes(id, namingConvention);
|
||||
|
||||
String name = name(id, namingConvention);
|
||||
this.otelHistogram =
|
||||
otelMeter
|
||||
.histogramBuilder(name)
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(baseUnit(id))
|
||||
.build();
|
||||
this.observableMax =
|
||||
otelMeter
|
||||
.gaugeBuilder(name + ".max")
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(baseUnit(id))
|
||||
.buildWithCallback(
|
||||
new DoubleMeasurementRecorder<>(max, TimeWindowMax::poll, attributes));
|
||||
}
|
||||
|
||||
boolean isUsingMicrometerHistograms() {
|
||||
return histogram != NoopHistogram.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recordNonNegative(double amount) {
|
||||
if (!removed) {
|
||||
otelHistogram.record(amount, attributes);
|
||||
measurements.record(amount);
|
||||
max.record(amount);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return measurements.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalAmount() {
|
||||
return measurements.totalAmount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double max() {
|
||||
return max.poll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Measurement> measure() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
removed = true;
|
||||
observableMax.close();
|
||||
}
|
||||
|
||||
private interface Measurements {
|
||||
void record(double amount);
|
||||
|
||||
long count();
|
||||
|
||||
double totalAmount();
|
||||
}
|
||||
|
||||
// if micrometer histograms are not being used then there's no need to keep any local state
|
||||
// OpenTelemetry metrics bridge does not support reading measurements
|
||||
enum NoopMeasurements implements Measurements {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public void record(double amount) {}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalAmount() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate count and totalAmount value for the use of micrometer histograms
|
||||
// kinda similar to how DropwizardDistributionSummary does that
|
||||
private static final class MicrometerHistogramMeasurements implements Measurements {
|
||||
|
||||
private final LongAdder count = new LongAdder();
|
||||
private final DoubleAdder totalAmount = new DoubleAdder();
|
||||
|
||||
@Override
|
||||
public void record(double amount) {
|
||||
count.increment();
|
||||
totalAmount.add(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return count.sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalAmount() {
|
||||
return totalAmount.sum();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.baseUnit;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.name;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.tagsAsAttributes;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractMeter;
|
||||
import io.micrometer.core.instrument.FunctionCounter;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableDoubleCounter;
|
||||
import java.util.Collections;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
|
||||
final class OpenTelemetryFunctionCounter<T> extends AbstractMeter
|
||||
implements FunctionCounter, RemovableMeter {
|
||||
|
||||
private final ObservableDoubleCounter observableCount;
|
||||
|
||||
OpenTelemetryFunctionCounter(
|
||||
Id id,
|
||||
NamingConvention namingConvention,
|
||||
T obj,
|
||||
ToDoubleFunction<T> countFunction,
|
||||
Meter otelMeter) {
|
||||
super(id);
|
||||
|
||||
String name = name(id, namingConvention);
|
||||
observableCount =
|
||||
otelMeter
|
||||
.counterBuilder(name)
|
||||
.ofDoubles()
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(baseUnit(id))
|
||||
.buildWithCallback(
|
||||
new DoubleMeasurementRecorder<>(
|
||||
obj, countFunction, tagsAsAttributes(id, namingConvention)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double count() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Measurement> measure() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
observableCount.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractMeter;
|
||||
import io.micrometer.core.instrument.FunctionTimer;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.micrometer.core.instrument.util.TimeUtils;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableDoubleCounter;
|
||||
import io.opentelemetry.api.metrics.ObservableLongCounter;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
import java.util.function.ToLongFunction;
|
||||
|
||||
final class OpenTelemetryFunctionTimer<T> extends AbstractMeter
|
||||
implements FunctionTimer, RemovableMeter {
|
||||
private final TimeUnit baseTimeUnit;
|
||||
private final ObservableLongCounter observableCount;
|
||||
private final ObservableDoubleCounter observableTotalTime;
|
||||
|
||||
OpenTelemetryFunctionTimer(
|
||||
Id id,
|
||||
NamingConvention namingConvention,
|
||||
T obj,
|
||||
ToLongFunction<T> countFunction,
|
||||
ToDoubleFunction<T> totalTimeFunction,
|
||||
TimeUnit totalTimeFunctionUnit,
|
||||
TimeUnit baseTimeUnit,
|
||||
Meter otelMeter) {
|
||||
super(id);
|
||||
this.baseTimeUnit = baseTimeUnit;
|
||||
|
||||
String name = Bridging.name(id, namingConvention);
|
||||
Attributes attributes = Bridging.tagsAsAttributes(id, namingConvention);
|
||||
|
||||
this.observableCount =
|
||||
otelMeter
|
||||
.counterBuilder(name + ".count")
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit("1")
|
||||
.buildWithCallback(new LongMeasurementRecorder<>(obj, countFunction, attributes));
|
||||
|
||||
this.observableTotalTime =
|
||||
otelMeter
|
||||
.counterBuilder(name + ".sum")
|
||||
.ofDoubles()
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(TimeUnitHelper.getUnitString(baseTimeUnit))
|
||||
.buildWithCallback(
|
||||
new DoubleMeasurementRecorder<>(
|
||||
obj,
|
||||
val ->
|
||||
TimeUtils.convert(
|
||||
totalTimeFunction.applyAsDouble(val),
|
||||
totalTimeFunctionUnit,
|
||||
baseTimeUnit),
|
||||
attributes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double count() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalTime(TimeUnit unit) {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double mean(TimeUnit unit) {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeUnit baseTimeUnit() {
|
||||
return baseTimeUnit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Measurement> measure() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
observableCount.close();
|
||||
observableTotalTime.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.baseUnit;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.name;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.tagsAsAttributes;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractMeter;
|
||||
import io.micrometer.core.instrument.Gauge;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableDoubleGauge;
|
||||
import java.util.Collections;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
final class OpenTelemetryGauge<T> extends AbstractMeter implements Gauge, RemovableMeter {
|
||||
|
||||
private final ObservableDoubleGauge observableGauge;
|
||||
|
||||
OpenTelemetryGauge(
|
||||
Id id,
|
||||
NamingConvention namingConvention,
|
||||
@Nullable T obj,
|
||||
ToDoubleFunction<T> objMetric,
|
||||
Meter otelMeter) {
|
||||
super(id);
|
||||
|
||||
String name = name(id, namingConvention);
|
||||
observableGauge =
|
||||
otelMeter
|
||||
.gaugeBuilder(name)
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(baseUnit(id))
|
||||
.buildWithCallback(
|
||||
new DoubleMeasurementRecorder<>(
|
||||
obj, objMetric, tagsAsAttributes(id, namingConvention)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double value() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Measurement> measure() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
observableGauge.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.name;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.tagsAsAttributes;
|
||||
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.core.instrument.internal.DefaultLongTaskTimer;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableDoubleUpDownCounter;
|
||||
import io.opentelemetry.api.metrics.ObservableLongUpDownCounter;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
final class OpenTelemetryLongTaskTimer extends DefaultLongTaskTimer implements RemovableMeter {
|
||||
|
||||
private final DistributionStatisticConfig distributionStatisticConfig;
|
||||
private final ObservableLongUpDownCounter observableActiveTasks;
|
||||
private final ObservableDoubleUpDownCounter observableDuration;
|
||||
|
||||
OpenTelemetryLongTaskTimer(
|
||||
Id id,
|
||||
NamingConvention namingConvention,
|
||||
Clock clock,
|
||||
TimeUnit baseTimeUnit,
|
||||
DistributionStatisticConfig distributionStatisticConfig,
|
||||
Meter otelMeter) {
|
||||
super(id, clock, baseTimeUnit, distributionStatisticConfig, false);
|
||||
|
||||
this.distributionStatisticConfig = distributionStatisticConfig;
|
||||
|
||||
String name = name(id, namingConvention);
|
||||
Attributes attributes = tagsAsAttributes(id, namingConvention);
|
||||
|
||||
this.observableActiveTasks =
|
||||
otelMeter
|
||||
.upDownCounterBuilder(name + ".active")
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit("tasks")
|
||||
.buildWithCallback(
|
||||
new LongMeasurementRecorder<>(this, DefaultLongTaskTimer::activeTasks, attributes));
|
||||
this.observableDuration =
|
||||
otelMeter
|
||||
.upDownCounterBuilder(name + ".duration")
|
||||
.ofDoubles()
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(TimeUnitHelper.getUnitString(baseTimeUnit))
|
||||
.buildWithCallback(
|
||||
new DoubleMeasurementRecorder<>(
|
||||
this, t -> t.duration(t.baseTimeUnit()), attributes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Measurement> measure() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
observableActiveTasks.close();
|
||||
observableDuration.close();
|
||||
}
|
||||
|
||||
boolean isUsingMicrometerHistograms() {
|
||||
return distributionStatisticConfig.isPublishingPercentiles()
|
||||
|| distributionStatisticConfig.isPublishingHistogram();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.baseUnit;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.statisticInstrumentName;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.tagsAsAttributes;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractMeter;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
final class OpenTelemetryMeter extends AbstractMeter implements Meter, RemovableMeter {
|
||||
|
||||
private final List<AutoCloseable> observableInstruments;
|
||||
|
||||
OpenTelemetryMeter(
|
||||
Id id,
|
||||
NamingConvention namingConvention,
|
||||
Iterable<Measurement> measurements,
|
||||
io.opentelemetry.api.metrics.Meter otelMeter) {
|
||||
super(id);
|
||||
Attributes attributes = tagsAsAttributes(id, namingConvention);
|
||||
|
||||
List<AutoCloseable> observableInstruments = new ArrayList<>();
|
||||
for (Measurement measurement : measurements) {
|
||||
String name = statisticInstrumentName(id, measurement.getStatistic(), namingConvention);
|
||||
String description = Bridging.description(id);
|
||||
String baseUnit = baseUnit(id);
|
||||
DoubleMeasurementRecorder<Measurement> callback =
|
||||
new DoubleMeasurementRecorder<>(measurement, Measurement::getValue, attributes);
|
||||
|
||||
switch (measurement.getStatistic()) {
|
||||
case TOTAL:
|
||||
// fall through
|
||||
case TOTAL_TIME:
|
||||
case COUNT:
|
||||
observableInstruments.add(
|
||||
otelMeter
|
||||
.counterBuilder(name)
|
||||
.ofDoubles()
|
||||
.setDescription(description)
|
||||
.setUnit(baseUnit)
|
||||
.buildWithCallback(callback));
|
||||
break;
|
||||
|
||||
case ACTIVE_TASKS:
|
||||
observableInstruments.add(
|
||||
otelMeter
|
||||
.upDownCounterBuilder(name)
|
||||
.ofDoubles()
|
||||
.setDescription(description)
|
||||
.setUnit(baseUnit)
|
||||
.buildWithCallback(callback));
|
||||
break;
|
||||
|
||||
case DURATION:
|
||||
// fall through
|
||||
case MAX:
|
||||
case VALUE:
|
||||
case UNKNOWN:
|
||||
observableInstruments.add(
|
||||
otelMeter
|
||||
.gaugeBuilder(name)
|
||||
.setDescription(description)
|
||||
.setUnit(baseUnit)
|
||||
.buildWithCallback(callback));
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.observableInstruments = observableInstruments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Measurement> measure() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
try {
|
||||
for (AutoCloseable observableInstrument : observableInstruments) {
|
||||
observableInstrument.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("SDK instruments should never throw on close()", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.FunctionCounter;
|
||||
import io.micrometer.core.instrument.FunctionTimer;
|
||||
import io.micrometer.core.instrument.Gauge;
|
||||
import io.micrometer.core.instrument.LongTaskTimer;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.core.instrument.distribution.HistogramGauges;
|
||||
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.ToDoubleFunction;
|
||||
import java.util.function.ToLongFunction;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A {@link MeterRegistry} implementation that forwards all the captured metrics to the {@linkplain
|
||||
* io.opentelemetry.api.metrics.Meter OpenTelemetry Meter} obtained from the passed {@link
|
||||
* OpenTelemetry} instance.
|
||||
*/
|
||||
public final class OpenTelemetryMeterRegistry extends MeterRegistry {
|
||||
|
||||
/**
|
||||
* Returns a new {@link OpenTelemetryMeterRegistry} configured with the given {@link
|
||||
* OpenTelemetry}.
|
||||
*/
|
||||
public static MeterRegistry create(OpenTelemetry openTelemetry) {
|
||||
return builder(openTelemetry).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link OpenTelemetryMeterRegistryBuilder} configured with the given {@link
|
||||
* OpenTelemetry}.
|
||||
*/
|
||||
public static OpenTelemetryMeterRegistryBuilder builder(OpenTelemetry openTelemetry) {
|
||||
return new OpenTelemetryMeterRegistryBuilder(openTelemetry);
|
||||
}
|
||||
|
||||
private final TimeUnit baseTimeUnit;
|
||||
private final io.opentelemetry.api.metrics.Meter otelMeter;
|
||||
|
||||
OpenTelemetryMeterRegistry(
|
||||
Clock clock,
|
||||
TimeUnit baseTimeUnit,
|
||||
NamingConvention namingConvention,
|
||||
io.opentelemetry.api.metrics.Meter otelMeter) {
|
||||
super(clock);
|
||||
this.baseTimeUnit = baseTimeUnit;
|
||||
this.otelMeter = otelMeter;
|
||||
|
||||
this.config()
|
||||
.namingConvention(namingConvention)
|
||||
.onMeterRemoved(OpenTelemetryMeterRegistry::onMeterRemoved);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> Gauge newGauge(Meter.Id id, @Nullable T obj, ToDoubleFunction<T> valueFunction) {
|
||||
return new OpenTelemetryGauge<>(id, config().namingConvention(), obj, valueFunction, otelMeter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Counter newCounter(Meter.Id id) {
|
||||
return new OpenTelemetryCounter(id, config().namingConvention(), otelMeter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LongTaskTimer newLongTaskTimer(
|
||||
Meter.Id id, DistributionStatisticConfig distributionStatisticConfig) {
|
||||
OpenTelemetryLongTaskTimer timer =
|
||||
new OpenTelemetryLongTaskTimer(
|
||||
id,
|
||||
config().namingConvention(),
|
||||
clock,
|
||||
getBaseTimeUnit(),
|
||||
distributionStatisticConfig,
|
||||
otelMeter);
|
||||
if (timer.isUsingMicrometerHistograms()) {
|
||||
HistogramGauges.registerWithCommonFormat(timer, this);
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Timer newTimer(
|
||||
Meter.Id id,
|
||||
DistributionStatisticConfig distributionStatisticConfig,
|
||||
PauseDetector pauseDetector) {
|
||||
OpenTelemetryTimer timer =
|
||||
new OpenTelemetryTimer(
|
||||
id,
|
||||
config().namingConvention(),
|
||||
clock,
|
||||
distributionStatisticConfig,
|
||||
pauseDetector,
|
||||
getBaseTimeUnit(),
|
||||
otelMeter);
|
||||
if (timer.isUsingMicrometerHistograms()) {
|
||||
HistogramGauges.registerWithCommonFormat(timer, this);
|
||||
}
|
||||
return timer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DistributionSummary newDistributionSummary(
|
||||
Meter.Id id, DistributionStatisticConfig distributionStatisticConfig, double scale) {
|
||||
OpenTelemetryDistributionSummary distributionSummary =
|
||||
new OpenTelemetryDistributionSummary(
|
||||
id, config().namingConvention(), clock, distributionStatisticConfig, scale, otelMeter);
|
||||
if (distributionSummary.isUsingMicrometerHistograms()) {
|
||||
HistogramGauges.registerWithCommonFormat(distributionSummary, this);
|
||||
}
|
||||
return distributionSummary;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Meter newMeter(Meter.Id id, Meter.Type type, Iterable<Measurement> measurements) {
|
||||
return new OpenTelemetryMeter(id, config().namingConvention(), measurements, otelMeter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> FunctionTimer newFunctionTimer(
|
||||
Meter.Id id,
|
||||
T obj,
|
||||
ToLongFunction<T> countFunction,
|
||||
ToDoubleFunction<T> totalTimeFunction,
|
||||
TimeUnit totalTimeFunctionUnit) {
|
||||
return new OpenTelemetryFunctionTimer<>(
|
||||
id,
|
||||
config().namingConvention(),
|
||||
obj,
|
||||
countFunction,
|
||||
totalTimeFunction,
|
||||
totalTimeFunctionUnit,
|
||||
getBaseTimeUnit(),
|
||||
otelMeter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> FunctionCounter newFunctionCounter(
|
||||
Meter.Id id, T obj, ToDoubleFunction<T> countFunction) {
|
||||
return new OpenTelemetryFunctionCounter<>(
|
||||
id, config().namingConvention(), obj, countFunction, otelMeter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TimeUnit getBaseTimeUnit() {
|
||||
return baseTimeUnit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DistributionStatisticConfig defaultHistogramConfig() {
|
||||
return DistributionStatisticConfig.DEFAULT;
|
||||
}
|
||||
|
||||
private static void onMeterRemoved(Meter meter) {
|
||||
if (meter instanceof RemovableMeter) {
|
||||
((RemovableMeter) meter).onRemove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** A builder of {@link OpenTelemetryMeterRegistry}. */
|
||||
public final class OpenTelemetryMeterRegistryBuilder {
|
||||
|
||||
// Visible for testing
|
||||
static final String INSTRUMENTATION_NAME = "io.opentelemetry.micrometer1shim";
|
||||
|
||||
private final OpenTelemetry openTelemetry;
|
||||
private Clock clock = Clock.SYSTEM;
|
||||
private TimeUnit baseTimeUnit = TimeUnit.MILLISECONDS;
|
||||
private boolean prometheusMode = false;
|
||||
|
||||
OpenTelemetryMeterRegistryBuilder(OpenTelemetry openTelemetry) {
|
||||
this.openTelemetry = openTelemetry;
|
||||
}
|
||||
|
||||
/** Sets a custom {@link Clock}. Useful for testing. */
|
||||
public OpenTelemetryMeterRegistryBuilder setClock(Clock clock) {
|
||||
this.clock = clock;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the base time unit. */
|
||||
public OpenTelemetryMeterRegistryBuilder setBaseTimeUnit(TimeUnit baseTimeUnit) {
|
||||
this.baseTimeUnit = baseTimeUnit;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the "Prometheus mode" - this will simulate the behavior of Micrometer's {@code
|
||||
* PrometheusMeterRegistry}. The instruments will be renamed to match Micrometer instrument
|
||||
* naming, and the base time unit will be set to seconds.
|
||||
*
|
||||
* <p>Set this to {@code true} if you are using the Prometheus metrics exporter.
|
||||
*/
|
||||
public OpenTelemetryMeterRegistryBuilder setPrometheusMode(boolean prometheusMode) {
|
||||
this.prometheusMode = prometheusMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link OpenTelemetryMeterRegistry} with the settings of this {@link
|
||||
* OpenTelemetryMeterRegistryBuilder}.
|
||||
*/
|
||||
public MeterRegistry build() {
|
||||
// prometheus mode overrides any unit settings with SECONDS
|
||||
TimeUnit baseTimeUnit = prometheusMode ? TimeUnit.SECONDS : this.baseTimeUnit;
|
||||
NamingConvention namingConvention =
|
||||
prometheusMode ? PrometheusModeNamingConvention.INSTANCE : NamingConvention.identity;
|
||||
|
||||
return new OpenTelemetryMeterRegistry(
|
||||
clock,
|
||||
baseTimeUnit,
|
||||
namingConvention,
|
||||
openTelemetry.getMeterProvider().get(INSTRUMENTATION_NAME));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.name;
|
||||
import static io.opentelemetry.micrometer1shim.Bridging.tagsAsAttributes;
|
||||
|
||||
import io.micrometer.core.instrument.AbstractTimer;
|
||||
import io.micrometer.core.instrument.Clock;
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
|
||||
import io.micrometer.core.instrument.distribution.NoopHistogram;
|
||||
import io.micrometer.core.instrument.distribution.TimeWindowMax;
|
||||
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
|
||||
import io.micrometer.core.instrument.util.TimeUtils;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.DoubleHistogram;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableDoubleGauge;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.DoubleAdder;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
final class OpenTelemetryTimer extends AbstractTimer implements RemovableMeter {
|
||||
|
||||
private final Measurements measurements;
|
||||
private final TimeWindowMax max;
|
||||
private final TimeUnit baseTimeUnit;
|
||||
// TODO: use bound instruments when they're available
|
||||
private final DoubleHistogram otelHistogram;
|
||||
private final Attributes attributes;
|
||||
private final ObservableDoubleGauge observableMax;
|
||||
|
||||
private volatile boolean removed = false;
|
||||
|
||||
OpenTelemetryTimer(
|
||||
Id id,
|
||||
NamingConvention namingConvention,
|
||||
Clock clock,
|
||||
DistributionStatisticConfig distributionStatisticConfig,
|
||||
PauseDetector pauseDetector,
|
||||
TimeUnit baseTimeUnit,
|
||||
Meter otelMeter) {
|
||||
super(id, clock, distributionStatisticConfig, pauseDetector, TimeUnit.MILLISECONDS, false);
|
||||
|
||||
if (isUsingMicrometerHistograms()) {
|
||||
measurements = new MicrometerHistogramMeasurements();
|
||||
} else {
|
||||
measurements = NoopMeasurements.INSTANCE;
|
||||
}
|
||||
max = new TimeWindowMax(clock, distributionStatisticConfig);
|
||||
|
||||
this.baseTimeUnit = baseTimeUnit;
|
||||
this.attributes = tagsAsAttributes(id, namingConvention);
|
||||
|
||||
String name = name(id, namingConvention);
|
||||
this.otelHistogram =
|
||||
otelMeter
|
||||
.histogramBuilder(name)
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(TimeUnitHelper.getUnitString(baseTimeUnit))
|
||||
.build();
|
||||
this.observableMax =
|
||||
otelMeter
|
||||
.gaugeBuilder(name + ".max")
|
||||
.setDescription(Bridging.description(id))
|
||||
.setUnit(TimeUnitHelper.getUnitString(baseTimeUnit))
|
||||
.buildWithCallback(
|
||||
new DoubleMeasurementRecorder<>(max, m -> m.poll(baseTimeUnit), attributes));
|
||||
}
|
||||
|
||||
boolean isUsingMicrometerHistograms() {
|
||||
return histogram != NoopHistogram.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void recordNonNegative(long amount, TimeUnit unit) {
|
||||
if (!removed) {
|
||||
double nanos = (double) unit.toNanos(amount);
|
||||
double time = TimeUtils.nanosToUnit(nanos, baseTimeUnit);
|
||||
otelHistogram.record(time, attributes);
|
||||
measurements.record(nanos);
|
||||
max.record(nanos, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return measurements.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalTime(TimeUnit unit) {
|
||||
return measurements.totalTime(unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double max(TimeUnit unit) {
|
||||
return max.poll(unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Measurement> measure() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove() {
|
||||
removed = true;
|
||||
observableMax.close();
|
||||
}
|
||||
|
||||
private interface Measurements {
|
||||
void record(double nanos);
|
||||
|
||||
long count();
|
||||
|
||||
double totalTime(TimeUnit unit);
|
||||
}
|
||||
|
||||
// if micrometer histograms are not being used then there's no need to keep any local state
|
||||
// OpenTelemetry metrics bridge does not support reading measurements
|
||||
enum NoopMeasurements implements Measurements {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public void record(double nanos) {}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalTime(TimeUnit unit) {
|
||||
UnsupportedReadLogger.logWarning();
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate count and totalTime value for the use of micrometer histograms
|
||||
// kinda similar to how DropwizardTimer does that
|
||||
private static final class MicrometerHistogramMeasurements implements Measurements {
|
||||
|
||||
private final LongAdder count = new LongAdder();
|
||||
private final DoubleAdder totalTime = new DoubleAdder();
|
||||
|
||||
@Override
|
||||
public void record(double nanos) {
|
||||
count.increment();
|
||||
totalTime.add(nanos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return count.sum();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double totalTime(TimeUnit unit) {
|
||||
return TimeUtils.nanosToUnit(totalTime.sum(), unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
// This naming strategy does not replace '.' with '_', and it does not append '_total' to counter
|
||||
// names - the reason behind it is that this is already done by the Prometheus exporter; see the
|
||||
// io.opentelemetry.exporter.prometheus.MetricAdapter class
|
||||
enum PrometheusModeNamingConvention implements NamingConvention {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public String name(String name, Meter.Type type, @Nullable String baseUnit) {
|
||||
if (type == Meter.Type.COUNTER
|
||||
|| type == Meter.Type.DISTRIBUTION_SUMMARY
|
||||
|| type == Meter.Type.GAUGE) {
|
||||
if (baseUnit != null && !name.endsWith("." + baseUnit)) {
|
||||
name = name + "." + baseUnit;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == Meter.Type.LONG_TASK_TIMER || type == Meter.Type.TIMER) {
|
||||
if (!name.endsWith(".seconds")) {
|
||||
name = name + ".seconds";
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
interface RemovableMeter {
|
||||
|
||||
void onRemove();
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
final class TimeUnitHelper {
|
||||
|
||||
static String getUnitString(TimeUnit unit) {
|
||||
switch (unit) {
|
||||
case NANOSECONDS:
|
||||
return "ns";
|
||||
case MICROSECONDS:
|
||||
return "us";
|
||||
case MILLISECONDS:
|
||||
return "ms";
|
||||
case SECONDS:
|
||||
return "s";
|
||||
case MINUTES:
|
||||
return "min";
|
||||
case HOURS:
|
||||
return "h";
|
||||
case DAYS:
|
||||
return "d";
|
||||
}
|
||||
throw new IllegalStateException("Should not ever happen");
|
||||
}
|
||||
|
||||
private TimeUnitHelper() {}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
final class UnsupportedReadLogger {
|
||||
|
||||
static {
|
||||
Logger logger = Logger.getLogger(OpenTelemetryMeterRegistry.class.getName());
|
||||
logger.log(Level.WARNING, "OpenTelemetry metrics bridge does not support reading measurements");
|
||||
}
|
||||
|
||||
static void logWarning() {
|
||||
// do nothing; the warning will be logged exactly once when this class is loaded
|
||||
}
|
||||
|
||||
private UnsupportedReadLogger() {}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class CounterTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing = new MicrometerTestingExtension();
|
||||
|
||||
@Test
|
||||
void testCounter() {
|
||||
Counter counter =
|
||||
Counter.builder("testCounter")
|
||||
.description("This is a test counter")
|
||||
.tags("tag", "value")
|
||||
.baseUnit("items")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
counter.increment();
|
||||
counter.increment(2);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testCounter")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test counter")
|
||||
.hasUnit("items")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(3)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
Metrics.globalRegistry.remove(counter);
|
||||
counter.increment();
|
||||
|
||||
// Synchronous instruments will continue to report previous value after removal
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testCounter")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum -> sum.hasPointsSatisfying(point -> point.hasValue(3))));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,217 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class DistributionSummaryTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing = new MicrometerTestingExtension();
|
||||
|
||||
@Test
|
||||
void testMicrometerDistributionSummary() {
|
||||
DistributionSummary summary =
|
||||
DistributionSummary.builder("testSummary")
|
||||
.description("This is a test distribution summary")
|
||||
.baseUnit("things")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
summary.record(1);
|
||||
summary.record(2);
|
||||
summary.record(4);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test distribution summary")
|
||||
.hasUnit("things")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(7)
|
||||
.hasCount(3)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary.max")
|
||||
.hasDescription("This is a test distribution summary")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(4)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
Metrics.globalRegistry.remove(summary);
|
||||
|
||||
// Histogram is synchronous and returns previous value after removal, max is asynchronous and is
|
||||
// removed completely.
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(7)
|
||||
.hasCount(3)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMicrometerHistogram() {
|
||||
DistributionSummary summary =
|
||||
DistributionSummary.builder("testSummary")
|
||||
.description("This is a test distribution summary")
|
||||
.baseUnit("things")
|
||||
.tags("tag", "value")
|
||||
.serviceLevelObjectives(1, 10, 100, 1000)
|
||||
.distributionStatisticBufferLength(10)
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
summary.record(0.5);
|
||||
summary.record(5);
|
||||
summary.record(50);
|
||||
summary.record(500);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test distribution summary")
|
||||
.hasUnit("things")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
points ->
|
||||
points
|
||||
.hasSum(555.5)
|
||||
.hasCount(4)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary.max")
|
||||
.hasDescription("This is a test distribution summary")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(500)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary.histogram")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(1)
|
||||
.hasAttributes(
|
||||
attributeEntry("le", "1"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(2)
|
||||
.hasAttributes(
|
||||
attributeEntry("le", "10"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(3)
|
||||
.hasAttributes(
|
||||
attributeEntry("le", "100"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(4)
|
||||
.hasAttributes(
|
||||
attributeEntry("le", "1000"),
|
||||
attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMicrometerPercentiles() {
|
||||
DistributionSummary summary =
|
||||
DistributionSummary.builder("testSummary")
|
||||
.description("This is a test distribution summary")
|
||||
.baseUnit("things")
|
||||
.tags("tag", "value")
|
||||
.publishPercentiles(0.5, 0.95, 0.99)
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
summary.record(50);
|
||||
summary.record(100);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test distribution summary")
|
||||
.hasUnit("things")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(150)
|
||||
.hasCount(2)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary.max")
|
||||
.hasDescription("This is a test distribution summary")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(100)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testSummary.percentile")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("phi", "0.5"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("phi", "0.95"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("phi", "0.99"),
|
||||
attributeEntry("tag", "value")))));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.FunctionCounter;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.internal.testing.slf4j.SuppressLogger;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import io.opentelemetry.sdk.metrics.internal.state.MetricStorageRegistry;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class FunctionCounterTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing = new MicrometerTestingExtension();
|
||||
|
||||
final AtomicLong num = new AtomicLong(12);
|
||||
final AtomicLong anotherNum = new AtomicLong(13);
|
||||
|
||||
@Test
|
||||
void testFunctionCounter() {
|
||||
FunctionCounter counter =
|
||||
FunctionCounter.builder("testFunctionCounter", num, AtomicLong::get)
|
||||
.description("This is a test function counter")
|
||||
.tags("tag", "value")
|
||||
.baseUnit("items")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testFunctionCounter")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test function counter")
|
||||
.hasUnit("items")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
Metrics.globalRegistry.remove(counter);
|
||||
assertThat(testing.collectAllMetrics()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressLogger(MetricStorageRegistry.class)
|
||||
void functionCountersWithSameNameAndDifferentTags() {
|
||||
FunctionCounter.builder("testFunctionCounterWithTags", num, AtomicLong::get)
|
||||
.description("First description")
|
||||
.tags("tag", "1")
|
||||
.baseUnit("items")
|
||||
.register(Metrics.globalRegistry);
|
||||
FunctionCounter.builder("testFunctionCounterWithTags", anotherNum, AtomicLong::get)
|
||||
.description("ignored")
|
||||
.tags("tag", "2")
|
||||
.baseUnit("items")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testFunctionCounterWithTags")
|
||||
.hasDescription("First description")
|
||||
.hasUnit("items")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12)
|
||||
.hasAttributes(attributeEntry("tag", "1")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(13)
|
||||
.hasAttributes(attributeEntry("tag", "2")))));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.FunctionTimer;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class FunctionTimerSecondsTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing =
|
||||
new MicrometerTestingExtension() {
|
||||
|
||||
@Override
|
||||
OpenTelemetryMeterRegistryBuilder configureOtelRegistry(
|
||||
OpenTelemetryMeterRegistryBuilder registry) {
|
||||
return registry.setBaseTimeUnit(TimeUnit.SECONDS);
|
||||
}
|
||||
};
|
||||
|
||||
final TestTimer timerObj = new TestTimer();
|
||||
|
||||
@BeforeEach
|
||||
void cleanupTimer() {
|
||||
timerObj.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFunctionTimerWithBaseUnitSeconds() {
|
||||
FunctionTimer functionTimer =
|
||||
FunctionTimer.builder(
|
||||
"testFunctionTimerSeconds",
|
||||
timerObj,
|
||||
TestTimer::getCount,
|
||||
TestTimer::getTotalTimeNanos,
|
||||
TimeUnit.NANOSECONDS)
|
||||
.description("This is a test function timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
timerObj.add(42, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testFunctionTimerSeconds.count")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test function timer")
|
||||
.hasUnit("1")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(1)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testFunctionTimerSeconds.sum")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test function timer")
|
||||
.hasUnit("s")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(42)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
Metrics.globalRegistry.remove(functionTimer);
|
||||
assertThat(testing.collectAllMetrics()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.FunctionTimer;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class FunctionTimerTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing = new MicrometerTestingExtension();
|
||||
|
||||
final TestTimer timerObj = new TestTimer();
|
||||
final TestTimer anotherTimerObj = new TestTimer();
|
||||
|
||||
@BeforeEach
|
||||
void cleanupTimers() {
|
||||
timerObj.reset();
|
||||
anotherTimerObj.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFunctionTimer() throws InterruptedException {
|
||||
FunctionTimer functionTimer =
|
||||
FunctionTimer.builder(
|
||||
"testFunctionTimer",
|
||||
timerObj,
|
||||
TestTimer::getCount,
|
||||
TestTimer::getTotalTimeNanos,
|
||||
TimeUnit.NANOSECONDS)
|
||||
.description("This is a test function timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
timerObj.add(42, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testFunctionTimer.count")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test function timer")
|
||||
.hasUnit("1")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(1)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testFunctionTimer.sum")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test function timer")
|
||||
.hasUnit("ms")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(42_000)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
Metrics.globalRegistry.remove(functionTimer);
|
||||
assertThat(testing.collectAllMetrics()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNanoPrecision() {
|
||||
FunctionTimer.builder(
|
||||
"testNanoFunctionTimer",
|
||||
timerObj,
|
||||
TestTimer::getCount,
|
||||
TestTimer::getTotalTimeNanos,
|
||||
TimeUnit.NANOSECONDS)
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
timerObj.add(1_234_000, TimeUnit.NANOSECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.anySatisfy(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testNanoFunctionTimer.sum")
|
||||
.hasUnit("ms")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point -> point.hasValue(1.234).hasAttributes(Attributes.empty()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void functionTimersWithSameNameAndDifferentTags() {
|
||||
FunctionTimer.builder(
|
||||
"testFunctionTimerWithTags",
|
||||
timerObj,
|
||||
TestTimer::getCount,
|
||||
TestTimer::getTotalTimeNanos,
|
||||
TimeUnit.NANOSECONDS)
|
||||
.tags("tag", "1")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
FunctionTimer.builder(
|
||||
"testFunctionTimerWithTags",
|
||||
anotherTimerObj,
|
||||
TestTimer::getCount,
|
||||
TestTimer::getTotalTimeNanos,
|
||||
TimeUnit.NANOSECONDS)
|
||||
.tags("tag", "2")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
timerObj.add(12, TimeUnit.SECONDS);
|
||||
anotherTimerObj.add(42, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.anySatisfy(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testFunctionTimerWithTags.sum")
|
||||
.hasUnit("ms")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12_000)
|
||||
.hasAttributes(attributeEntry("tag", "1")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(42_000)
|
||||
.hasAttributes(attributeEntry("tag", "2")))));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.Gauge;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class GaugeTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing = new MicrometerTestingExtension();
|
||||
|
||||
@Test
|
||||
void testGauge() {
|
||||
// when
|
||||
Gauge gauge =
|
||||
Gauge.builder("testGauge", () -> 42)
|
||||
.description("This is a test gauge")
|
||||
.tags("tag", "value")
|
||||
.baseUnit("items")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testGauge")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test gauge")
|
||||
.hasUnit("items")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
doubleGauge ->
|
||||
doubleGauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(42)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
// when
|
||||
Metrics.globalRegistry.remove(gauge);
|
||||
assertThat(testing.collectAllMetrics()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void gaugesWithSameNameAndDifferentTags() {
|
||||
Gauge.builder("testGaugeWithTags", () -> 12)
|
||||
.description("First description wins")
|
||||
.baseUnit("items")
|
||||
.tags("tag", "1")
|
||||
.register(Metrics.globalRegistry);
|
||||
Gauge.builder("testGaugeWithTags", () -> 42)
|
||||
.description("ignored")
|
||||
.baseUnit("items")
|
||||
.tags("tag", "2")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactly(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testGaugeWithTags")
|
||||
.hasDescription("First description wins")
|
||||
.hasUnit("items")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasValue(12).hasAttributes(attributeEntry("tag", "1")),
|
||||
point ->
|
||||
point.hasValue(42).hasAttributes(attributeEntry("tag", "2")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWeakRefGauge() throws InterruptedException {
|
||||
AtomicLong num = new AtomicLong(42);
|
||||
Gauge.builder("testWeakRefGauge", num, AtomicLong::get)
|
||||
.strongReference(false)
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactly(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testWeakRefGauge")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge -> gauge.hasPointsSatisfying(point -> point.hasValue(42))));
|
||||
|
||||
WeakReference<AtomicLong> numWeakRef = new WeakReference<>(num);
|
||||
num = null;
|
||||
awaitGc(numWeakRef);
|
||||
|
||||
assertThat(testing.collectAllMetrics()).isEmpty();
|
||||
}
|
||||
|
||||
private static void awaitGc(WeakReference<?> ref) throws InterruptedException {
|
||||
while (ref.get() != null) {
|
||||
if (Thread.interrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.LongTaskTimer;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.MockClock;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.time.Duration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class LongTaskTimerHistogramTest {
|
||||
|
||||
static MockClock clock = new MockClock();
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing =
|
||||
new MicrometerTestingExtension() {
|
||||
@Override
|
||||
OpenTelemetryMeterRegistryBuilder configureOtelRegistry(
|
||||
OpenTelemetryMeterRegistryBuilder registry) {
|
||||
return registry.setClock(clock);
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void testMicrometerHistogram() {
|
||||
LongTaskTimer timer =
|
||||
LongTaskTimer.builder("testLongTaskTimerHistogram")
|
||||
.description("This is a test timer")
|
||||
.serviceLevelObjectives(Duration.ofMillis(100), Duration.ofMillis(1000))
|
||||
.distributionStatisticBufferLength(10)
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
LongTaskTimer.Sample sample1 = timer.start();
|
||||
// only active tasks count
|
||||
timer.start().stop();
|
||||
clock.add(Duration.ofMillis(100));
|
||||
LongTaskTimer.Sample sample2 = timer.start();
|
||||
LongTaskTimer.Sample sample3 = timer.start();
|
||||
clock.add(Duration.ofMillis(10));
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerHistogram.active")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("tasks")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point -> point.hasValue(3).hasAttributes(Attributes.empty()))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerHistogram.duration")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("ms")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasAttributes(Attributes.empty())
|
||||
.satisfies(
|
||||
pointData ->
|
||||
assertThat(pointData.getValue())
|
||||
.isPositive()))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerHistogram.histogram")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(attributeEntry("le", "100")).hasValue(2),
|
||||
point ->
|
||||
point
|
||||
.hasAttributes(attributeEntry("le", "1000"))
|
||||
.hasValue(3))));
|
||||
|
||||
sample1.stop();
|
||||
sample2.stop();
|
||||
sample3.stop();
|
||||
|
||||
// Continues to report 0 after stopped.
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerHistogram.active")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("tasks")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point -> point.hasValue(0).hasAttributes(Attributes.empty()))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerHistogram.duration")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("ms")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point -> point.hasValue(0).hasAttributes(Attributes.empty()))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerHistogram.histogram")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasValue(0).hasAttributes(attributeEntry("le", "100")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(0)
|
||||
.hasAttributes(attributeEntry("le", "1000")))));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.LongTaskTimer;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class LongTaskTimerSecondsTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing =
|
||||
new MicrometerTestingExtension() {
|
||||
|
||||
@Override
|
||||
OpenTelemetryMeterRegistryBuilder configureOtelRegistry(
|
||||
OpenTelemetryMeterRegistryBuilder registry) {
|
||||
return registry.setBaseTimeUnit(TimeUnit.SECONDS);
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void testLongTaskTimerWithBaseUnitSeconds() throws InterruptedException {
|
||||
// given
|
||||
LongTaskTimer timer =
|
||||
LongTaskTimer.builder("testLongTaskTimerSeconds")
|
||||
.description("This is a test long task timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
// when
|
||||
LongTaskTimer.Sample sample = timer.start();
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerSeconds.active")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test long task timer")
|
||||
.hasUnit("tasks")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(1)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerSeconds.duration")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test long task timer")
|
||||
.hasUnit("s")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasAttributes(attributeEntry("tag", "value"))
|
||||
.satisfies(
|
||||
pointData ->
|
||||
assertThat(pointData.getValue())
|
||||
.isPositive()))));
|
||||
|
||||
// when
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
sample.stop();
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerSeconds.active")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(0)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimerSeconds.duration")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(0)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
// when timer is removed from the registry
|
||||
Metrics.globalRegistry.remove(timer);
|
||||
timer.start();
|
||||
|
||||
// then no tasks are active after starting a new sample
|
||||
assertThat(testing.collectAllMetrics()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.LongTaskTimer;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class LongTaskTimerTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing = new MicrometerTestingExtension();
|
||||
|
||||
@Test
|
||||
void testLongTaskTimer() throws InterruptedException {
|
||||
LongTaskTimer timer =
|
||||
LongTaskTimer.builder("testLongTaskTimer")
|
||||
.description("This is a test long task timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
LongTaskTimer.Sample sample = timer.start();
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimer.active")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test long task timer")
|
||||
.hasUnit("tasks")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(1)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimer.duration")
|
||||
.hasDescription("This is a test long task timer")
|
||||
.hasUnit("ms")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasAttributes(attributeEntry("tag", "value"))
|
||||
.satisfies(
|
||||
pointData ->
|
||||
assertThat(pointData.getValue())
|
||||
.isPositive()))));
|
||||
|
||||
// when
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
sample.stop();
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimer.active")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(0)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testLongTaskTimer.duration")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(0)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
// when timer is removed from the registry
|
||||
Metrics.globalRegistry.remove(timer);
|
||||
timer.start();
|
||||
|
||||
// then no tasks are active after starting a new sample
|
||||
assertThat(testing.collectAllMetrics()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.Measurement;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Statistic;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class MeterTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing = new MicrometerTestingExtension();
|
||||
|
||||
@Test
|
||||
void testMeter() {
|
||||
AtomicReference<Double> number = new AtomicReference<>(12345.0);
|
||||
|
||||
List<Measurement> measurements =
|
||||
Arrays.asList(
|
||||
new Measurement(number::get, Statistic.TOTAL),
|
||||
new Measurement(number::get, Statistic.TOTAL_TIME),
|
||||
new Measurement(number::get, Statistic.COUNT),
|
||||
new Measurement(number::get, Statistic.ACTIVE_TASKS),
|
||||
new Measurement(number::get, Statistic.DURATION),
|
||||
new Measurement(number::get, Statistic.MAX),
|
||||
new Measurement(number::get, Statistic.VALUE),
|
||||
new Measurement(number::get, Statistic.UNKNOWN));
|
||||
|
||||
Meter meter =
|
||||
Meter.builder("testMeter", Meter.Type.OTHER, measurements)
|
||||
.description("This is a test meter")
|
||||
.baseUnit("things")
|
||||
.tag("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testMeter.total")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test meter")
|
||||
.hasUnit("things")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testMeter.total_time")
|
||||
.hasDescription("This is a test meter")
|
||||
.hasUnit("things")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testMeter.count")
|
||||
.hasDescription("This is a test meter")
|
||||
.hasUnit("things")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testMeter.active")
|
||||
.hasDescription("This is a test meter")
|
||||
.hasUnit("things")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testMeter.duration")
|
||||
.hasDescription("This is a test meter")
|
||||
.hasUnit("things")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testMeter.max")
|
||||
.hasDescription("This is a test meter")
|
||||
.hasUnit("things")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testMeter.value")
|
||||
.hasDescription("This is a test meter")
|
||||
.hasUnit("things")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testMeter.unknown")
|
||||
.hasDescription("This is a test meter")
|
||||
.hasUnit("things")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
// when
|
||||
Metrics.globalRegistry.remove(meter);
|
||||
assertThat(testing.collectAllMetrics()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||
import io.opentelemetry.sdk.metrics.data.MetricData;
|
||||
import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader;
|
||||
import java.util.Collection;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
|
||||
class MicrometerTestingExtension implements AfterEachCallback, BeforeEachCallback {
|
||||
|
||||
private static final ExtensionContext.Namespace NAMESPACE =
|
||||
ExtensionContext.Namespace.create(MicrometerTestingExtension.class);
|
||||
|
||||
private InMemoryMetricReader metricReader;
|
||||
|
||||
Collection<MetricData> collectAllMetrics() {
|
||||
return metricReader.collectAllMetrics();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) {
|
||||
ExtensionContext.Store store = context.getStore(NAMESPACE);
|
||||
|
||||
metricReader = InMemoryMetricReader.create();
|
||||
SdkMeterProvider meterProvider =
|
||||
SdkMeterProvider.builder().registerMetricReader(metricReader).build();
|
||||
MeterRegistry otelMeterRegistry =
|
||||
configureOtelRegistry(
|
||||
OpenTelemetryMeterRegistry.builder(
|
||||
OpenTelemetrySdk.builder().setMeterProvider(meterProvider).build()))
|
||||
.build();
|
||||
configureMeterRegistry(otelMeterRegistry);
|
||||
|
||||
store.put(SdkMeterProvider.class, meterProvider);
|
||||
store.put(MeterRegistry.class, otelMeterRegistry);
|
||||
|
||||
Metrics.addRegistry(otelMeterRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) {
|
||||
ExtensionContext.Store store = context.getStore(NAMESPACE);
|
||||
MeterRegistry otelMeterRegistry = store.get(MeterRegistry.class, MeterRegistry.class);
|
||||
SdkMeterProvider meterProvider = store.get(SdkMeterProvider.class, SdkMeterProvider.class);
|
||||
|
||||
Metrics.removeRegistry(otelMeterRegistry);
|
||||
meterProvider.close();
|
||||
|
||||
Metrics.globalRegistry.forEachMeter(Metrics.globalRegistry::remove);
|
||||
}
|
||||
|
||||
OpenTelemetryMeterRegistryBuilder configureOtelRegistry(
|
||||
OpenTelemetryMeterRegistryBuilder registry) {
|
||||
return registry;
|
||||
}
|
||||
|
||||
MeterRegistry configureMeterRegistry(MeterRegistry registry) {
|
||||
return registry;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.LongTaskTimer;
|
||||
import io.micrometer.core.instrument.Meter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import io.micrometer.core.instrument.config.NamingConvention;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@SuppressWarnings("PreferJavaTimeOverload")
|
||||
class NamingConventionTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing =
|
||||
new MicrometerTestingExtension() {
|
||||
@Override
|
||||
MeterRegistry configureMeterRegistry(MeterRegistry registry) {
|
||||
registry
|
||||
.config()
|
||||
.namingConvention(
|
||||
new NamingConvention() {
|
||||
@Override
|
||||
public String name(String name, Meter.Type type, String baseUnit) {
|
||||
return "test." + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tagKey(String key) {
|
||||
return "test." + key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tagValue(String value) {
|
||||
return "test." + value;
|
||||
}
|
||||
});
|
||||
return registry;
|
||||
}
|
||||
};
|
||||
|
||||
final AtomicLong num = new AtomicLong(42);
|
||||
|
||||
@Test
|
||||
void renameCounter() {
|
||||
Counter counter = Metrics.counter("renamedCounter", "tag", "value");
|
||||
counter.increment();
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedCounter")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("test.tag", "test.value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void renameDistributionSummary() {
|
||||
DistributionSummary summary = Metrics.summary("renamedSummary", "tag", "value");
|
||||
summary.record(42);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedSummary")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(attributeEntry("test.tag", "test.value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedSummary.max")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("test.tag", "test.value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void renameFunctionCounter() {
|
||||
Metrics.more().counter("renamedFunctionCounter", Tags.of("tag", "value"), num);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedFunctionCounter")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("test.tag", "test.value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void renameFunctionTimer() {
|
||||
Metrics.more()
|
||||
.timer(
|
||||
"renamedFunctionTimer",
|
||||
Tags.of("tag", "value"),
|
||||
num,
|
||||
AtomicLong::longValue,
|
||||
AtomicLong::doubleValue,
|
||||
TimeUnit.SECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedFunctionTimer.count")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(attributeEntry("test.tag", "test.value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedFunctionTimer.sum")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("test.tag", "test.value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void renameGauge() {
|
||||
Metrics.gauge("renamedGauge", Tags.of("tag", "value"), num);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedGauge")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("test.tag", "test.value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void renameLongTaskTimer() {
|
||||
LongTaskTimer timer = Metrics.more().longTaskTimer("renamedLongTaskTimer", "tag", "value");
|
||||
timer.start().stop();
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedLongTaskTimer.active")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(attributeEntry("test.tag", "test.value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedLongTaskTimer.duration")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("test.tag", "test.value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void renameTimer() {
|
||||
Timer timer = Metrics.timer("renamedTimer", "tag", "value");
|
||||
timer.record(10, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedTimer")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(attributeEntry("test.tag", "test.value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("test.renamedTimer.max")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("test.tag", "test.value")))));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,320 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.FunctionTimer;
|
||||
import io.micrometer.core.instrument.Gauge;
|
||||
import io.micrometer.core.instrument.LongTaskTimer;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@SuppressWarnings("PreferJavaTimeOverload")
|
||||
class PrometheusModeTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing =
|
||||
new MicrometerTestingExtension() {
|
||||
|
||||
@Override
|
||||
OpenTelemetryMeterRegistryBuilder configureOtelRegistry(
|
||||
OpenTelemetryMeterRegistryBuilder registry) {
|
||||
return registry.setPrometheusMode(true);
|
||||
}
|
||||
};
|
||||
|
||||
final TestTimer timerObj = new TestTimer();
|
||||
|
||||
@BeforeEach
|
||||
void cleanupMeters() {
|
||||
Metrics.globalRegistry.forEachMeter(Metrics.globalRegistry::remove);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCounter() {
|
||||
// given
|
||||
Counter counter =
|
||||
Counter.builder("testPrometheusCounter")
|
||||
.description("This is a test counter")
|
||||
.tags("tag", "value")
|
||||
.baseUnit("items")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
// when
|
||||
counter.increment(12);
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusCounter.items")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test counter")
|
||||
.hasUnit("items")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDistributionSummary() {
|
||||
// given
|
||||
DistributionSummary summary =
|
||||
DistributionSummary.builder("testPrometheusSummary")
|
||||
.description("This is a test summary")
|
||||
.baseUnit("items")
|
||||
.tag("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
// when
|
||||
summary.record(12);
|
||||
summary.record(42);
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusSummary.items")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test summary")
|
||||
.hasUnit("items")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(54)
|
||||
.hasCount(2)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusSummary.items.max")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test summary")
|
||||
.hasUnit("items")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(42)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFunctionTimer() {
|
||||
// given
|
||||
FunctionTimer.builder(
|
||||
"testPrometheusFunctionTimer",
|
||||
timerObj,
|
||||
TestTimer::getCount,
|
||||
TestTimer::getTotalTimeNanos,
|
||||
TimeUnit.NANOSECONDS)
|
||||
.description("This is a test function timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
// when
|
||||
timerObj.add(42, TimeUnit.SECONDS);
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusFunctionTimer.seconds.count")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test function timer")
|
||||
.hasUnit("1")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(1)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusFunctionTimer.seconds.sum")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test function timer")
|
||||
.hasUnit("s")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(42)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGauge() {
|
||||
// when
|
||||
Gauge.builder("testPrometheusGauge", () -> 42)
|
||||
.description("This is a test gauge")
|
||||
.tags("tag", "value")
|
||||
.baseUnit("items")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusGauge.items")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test gauge")
|
||||
.hasUnit("items")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(42)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLongTaskTimer() throws InterruptedException {
|
||||
// given
|
||||
LongTaskTimer timer =
|
||||
LongTaskTimer.builder("testPrometheusLongTaskTimer")
|
||||
.description("This is a test long task timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
// when
|
||||
LongTaskTimer.Sample sample = timer.start();
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusLongTaskTimer.seconds.active")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test long task timer")
|
||||
.hasUnit("tasks")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(1)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusLongTaskTimer.seconds.duration")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test long task timer")
|
||||
.hasUnit("s")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasAttributes(attributeEntry("tag", "value"))
|
||||
.satisfies(
|
||||
pointData ->
|
||||
assertThat(pointData.getValue())
|
||||
.isPositive()))));
|
||||
|
||||
// when
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
sample.stop();
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusLongTaskTimer.seconds.active")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(0)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusLongTaskTimer.seconds.duration")
|
||||
.hasDoubleSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(0)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTimer() {
|
||||
// given
|
||||
Timer timer =
|
||||
Timer.builder("testPrometheusTimer")
|
||||
.description("This is a test timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
// when
|
||||
timer.record(1, TimeUnit.SECONDS);
|
||||
timer.record(5, TimeUnit.SECONDS);
|
||||
timer.record(10_789, TimeUnit.MILLISECONDS);
|
||||
|
||||
// then
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusTimer.seconds")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("s")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(16.789)
|
||||
.hasCount(3)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testPrometheusTimer.seconds.max")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("s")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(10.789)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
class TestTimer {
|
||||
int count = 0;
|
||||
long totalTimeNanos = 0;
|
||||
|
||||
void add(long time, TimeUnit unit) {
|
||||
count++;
|
||||
totalTimeNanos += unit.toNanos(time);
|
||||
}
|
||||
|
||||
int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
double getTotalTimeNanos() {
|
||||
return totalTimeNanos;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
count = 0;
|
||||
totalTimeNanos = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@SuppressWarnings("PreferJavaTimeOverload")
|
||||
class TimerSecondsTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing =
|
||||
new MicrometerTestingExtension() {
|
||||
|
||||
@Override
|
||||
OpenTelemetryMeterRegistryBuilder configureOtelRegistry(
|
||||
OpenTelemetryMeterRegistryBuilder registry) {
|
||||
return registry.setBaseTimeUnit(TimeUnit.SECONDS);
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void testTimerWithBaseUnitSeconds() {
|
||||
Timer timer =
|
||||
Timer.builder("testTimerSeconds")
|
||||
.description("This is a test timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
timer.record(1, TimeUnit.SECONDS);
|
||||
timer.record(10, TimeUnit.SECONDS);
|
||||
timer.record(12_345, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimerSeconds")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("s")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(23.345)
|
||||
.hasCount(3)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimerSeconds.max")
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("s")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(12.345)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
Metrics.globalRegistry.remove(timer);
|
||||
timer.record(12, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimerSeconds")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("s")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(23.345)
|
||||
.hasCount(3)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,252 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.micrometer1shim;
|
||||
|
||||
import static io.opentelemetry.micrometer1shim.OpenTelemetryMeterRegistryBuilder.INSTRUMENTATION_NAME;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry;
|
||||
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Timer;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@SuppressWarnings("PreferJavaTimeOverload")
|
||||
class TimerTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final MicrometerTestingExtension testing = new MicrometerTestingExtension();
|
||||
|
||||
@Test
|
||||
void testTimer() {
|
||||
Timer timer =
|
||||
Timer.builder("testTimer")
|
||||
.description("This is a test timer")
|
||||
.tags("tag", "value")
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
timer.record(42, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("ms")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(42_000)
|
||||
.hasCount(1)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer.max")
|
||||
.hasDescription("This is a test timer")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(42_000)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
|
||||
Metrics.globalRegistry.remove(timer);
|
||||
timer.record(12, TimeUnit.SECONDS);
|
||||
|
||||
// Histogram is synchronous and returns previous value after removal, max is asynchronous and is
|
||||
// removed completely.
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(42_000)
|
||||
.hasCount(1)
|
||||
.hasAttributes(attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNanoPrecision() {
|
||||
Timer timer = Timer.builder("testNanoTimer").register(Metrics.globalRegistry);
|
||||
|
||||
timer.record(1_234_000, TimeUnit.NANOSECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testNanoTimer")
|
||||
.hasUnit("ms")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(1.234)
|
||||
.hasCount(1)
|
||||
.hasAttributes(Attributes.empty()))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testNanoTimer.max")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point -> point.hasValue(1.234).hasAttributes(Attributes.empty()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMicrometerHistogram() {
|
||||
// given
|
||||
Timer timer =
|
||||
Timer.builder("testTimer")
|
||||
.description("This is a test timer")
|
||||
.tags("tag", "value")
|
||||
.serviceLevelObjectives(
|
||||
Duration.ofSeconds(1),
|
||||
Duration.ofSeconds(10),
|
||||
Duration.ofSeconds(100),
|
||||
Duration.ofSeconds(1000))
|
||||
.distributionStatisticBufferLength(10)
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
timer.record(500, TimeUnit.MILLISECONDS);
|
||||
timer.record(5, TimeUnit.SECONDS);
|
||||
timer.record(50, TimeUnit.SECONDS);
|
||||
timer.record(500, TimeUnit.SECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("ms")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(555500)
|
||||
.hasCount(4)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer.max")
|
||||
.hasDescription("This is a test timer")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(500000)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer.histogram")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(1)
|
||||
.hasAttributes(
|
||||
attributeEntry("le", "1000"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(2)
|
||||
.hasAttributes(
|
||||
attributeEntry("le", "10000"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(3)
|
||||
.hasAttributes(
|
||||
attributeEntry("le", "100000"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point
|
||||
.hasValue(4)
|
||||
.hasAttributes(
|
||||
attributeEntry("le", "1000000"),
|
||||
attributeEntry("tag", "value")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMicrometerPercentiles() {
|
||||
// given
|
||||
Timer timer =
|
||||
Timer.builder("testTimer")
|
||||
.description("This is a test timer")
|
||||
.tags("tag", "value")
|
||||
.publishPercentiles(0.5, 0.95, 0.99)
|
||||
.register(Metrics.globalRegistry);
|
||||
|
||||
timer.record(50, TimeUnit.MILLISECONDS);
|
||||
timer.record(100, TimeUnit.MILLISECONDS);
|
||||
|
||||
assertThat(testing.collectAllMetrics())
|
||||
.satisfiesExactlyInAnyOrder(
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer")
|
||||
.hasInstrumentationScope(InstrumentationScopeInfo.create(INSTRUMENTATION_NAME))
|
||||
.hasDescription("This is a test timer")
|
||||
.hasUnit("ms")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasSum(150)
|
||||
.hasCount(2)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer.max")
|
||||
.hasDescription("This is a test timer")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(100)
|
||||
.hasAttributes(attributeEntry("tag", "value")))),
|
||||
metric ->
|
||||
assertThat(metric)
|
||||
.hasName("testTimer.percentile")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge ->
|
||||
gauge.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("phi", "0.5"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("phi", "0.95"),
|
||||
attributeEntry("tag", "value")),
|
||||
point ->
|
||||
point.hasAttributes(
|
||||
attributeEntry("phi", "0.99"),
|
||||
attributeEntry("tag", "value")))));
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,6 @@ include(":exporters:zipkin")
|
|||
include(":integration-tests")
|
||||
include(":integration-tests:otlp")
|
||||
include(":integration-tests:tracecontext")
|
||||
include(":micrometer1-shim")
|
||||
include(":opencensus-shim")
|
||||
include(":opentracing-shim")
|
||||
include(":perf-harness")
|
||||
|
|
|
|||
Loading…
Reference in New Issue