Skip to content

Commit

Permalink
Switch UpDownCounters to Micrometer Gauge, memoize MeterRegistry supp…
Browse files Browse the repository at this point in the history
…lier, randomize measurements during tests
  • Loading branch information
HaloFour committed May 20, 2022
1 parent 9da6968 commit befdef4
Show file tree
Hide file tree
Showing 21 changed files with 608 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,12 @@ void longUpDownCounter() {
String output = prometheusMeterRegistry.scrape();

assertThat(output)
.contains("# HELP longUpDownCounter_units_total LongUpDownCounter test")
.contains("# TYPE longUpDownCounter_units_total counter")
.contains("# HELP longUpDownCounter_units LongUpDownCounter test")
.contains("# TYPE longUpDownCounter_units gauge")
.contains(
"longUpDownCounter_units_total{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.0")
"longUpDownCounter_units{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.0")
.contains(
"longUpDownCounter_units_total{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 2.0");
"longUpDownCounter_units{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 2.0");

longUpDownCounter.add(1, Attributes.of(KEY1, "value1"));
longUpDownCounter.add(2, Attributes.of(KEY1, "value2"));
Expand All @@ -182,9 +182,9 @@ void longUpDownCounter() {

assertThat(output)
.contains(
"longUpDownCounter_units_total{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 2.0")
"longUpDownCounter_units{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 2.0")
.contains(
"longUpDownCounter_units_total{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 4.0");
"longUpDownCounter_units{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 4.0");
}

@Test
Expand All @@ -204,12 +204,12 @@ void observableLongUpDownCounter() {
assertThat(output)
.contains("# HELP otel_polling_meter")
.contains("# TYPE otel_polling_meter untyped")
.contains("# TYPE longUpDownCounter_units_total counter")
.contains("# HELP longUpDownCounter_units_total LongUpDownCounter test")
.contains("# TYPE longUpDownCounter_units gauge")
.contains("# HELP longUpDownCounter_units LongUpDownCounter test")
.contains(
"longUpDownCounter_units_total{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.0")
"longUpDownCounter_units{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.0")
.contains(
"longUpDownCounter_units_total{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} -2.0");
"longUpDownCounter_units{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} -2.0");
}
}

Expand All @@ -229,12 +229,12 @@ void doubleUpDownCounter() {
String output = prometheusMeterRegistry.scrape();

assertThat(output)
.contains("# HELP doubleUpDownCounter_units_total DoubleUpDownCounter test")
.contains("# TYPE doubleUpDownCounter_units_total counter")
.contains("# HELP doubleUpDownCounter_units DoubleUpDownCounter test")
.contains("# TYPE doubleUpDownCounter_units gauge")
.contains(
"doubleUpDownCounter_units_total{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.5")
"doubleUpDownCounter_units{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.5")
.contains(
"doubleUpDownCounter_units_total{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 2.5");
"doubleUpDownCounter_units{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 2.5");

doubleUpDownCounter.add(0.5, Attributes.of(KEY1, "value1"));
doubleUpDownCounter.add(-1.5, Attributes.of(KEY1, "value2"));
Expand All @@ -243,9 +243,9 @@ void doubleUpDownCounter() {

assertThat(output)
.contains(
"doubleUpDownCounter_units_total{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 2.0")
"doubleUpDownCounter_units{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 2.0")
.contains(
"doubleUpDownCounter_units_total{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.0");
"doubleUpDownCounter_units{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.0");
}

@Test
Expand All @@ -267,12 +267,12 @@ void observableDoubleUpDownCounter() {
assertThat(output)
.contains("# HELP otel_polling_meter")
.contains("# TYPE otel_polling_meter untyped")
.contains("# TYPE doubleUpDownCounter_units_total counter")
.contains("# HELP doubleUpDownCounter_units_total DoubleUpDownCounter test")
.contains("# TYPE doubleUpDownCounter_units gauge")
.contains("# HELP doubleUpDownCounter_units DoubleUpDownCounter test")
.contains(
"doubleUpDownCounter_units_total{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.5")
"doubleUpDownCounter_units{key1=\"value1\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} 1.5")
.contains(
"doubleUpDownCounter_units_total{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} -2.5");
"doubleUpDownCounter_units{key1=\"value2\",otel_instrumentation_name=\"integrationTest\",otel_instrumentation_version=\"1.0\",} -2.5");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.micrometer.core.instrument.MeterRegistry;
import io.opentelemetry.api.metrics.MeterBuilder;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.contrib.metrics.micrometer.internal.MemoizingSupplier;
import io.opentelemetry.contrib.metrics.micrometer.internal.state.MeterProviderSharedState;
import java.util.Objects;
import java.util.function.Supplier;
Expand Down Expand Up @@ -56,9 +57,12 @@ public static MicrometerMeterProviderBuilder builder(MeterRegistry meterRegistry
/**
* Returns a new builder instance for this provider with a {@link Supplier} for a {@link
* MeterRegistry}.
*
* <p>This method should be used when the {@link MeterRegistry} must be lazily initialized.
*/
public static MicrometerMeterProviderBuilder builder(Supplier<MeterRegistry> meterRegistry) {
Objects.requireNonNull(meterRegistry, "meterRegistry");
return new MicrometerMeterProviderBuilder(meterRegistry);
public static MicrometerMeterProviderBuilder builder(
Supplier<MeterRegistry> meterRegistrySupplier) {
Objects.requireNonNull(meterRegistrySupplier, "meterRegistrySupplier");
return new MicrometerMeterProviderBuilder(new MemoizingSupplier<>(meterRegistrySupplier));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public class Constants {
public final class Constants {
public static final String OTEL_INSTRUMENTATION_NAME = "otel.instrumentation.name";
public static final String OTEL_INSTRUMENTATION_VERSION = "otel.instrumentation.version";
public static final Tag UNKNOWN_INSTRUMENTATION_VERSION_TAG =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.metrics.micrometer.internal;

import java.util.function.Supplier;
import javax.annotation.Nullable;

/**
* Delegating implementation of {@link Supplier Supplier<T>} that ensures that the {@link
* Supplier#get()} method is called at most once and the result is memoized for subsequent
* invocations.
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public final class MemoizingSupplier<T> implements Supplier<T> {
private final Supplier<T> delegate;
private volatile boolean initialized;
@Nullable private volatile T cachedResult;

public MemoizingSupplier(Supplier<T> delegate) {
this.delegate = delegate;
}

@Override
@SuppressWarnings("NullAway")
public T get() {
T result = cachedResult;
if (!initialized) {
synchronized (this) {
if (!initialized) {
result = delegate.get();
cachedResult = result;
initialized = true;
return result;
}
}
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import io.opentelemetry.contrib.metrics.micrometer.internal.state.MeterSharedState;
import javax.annotation.Nullable;

abstract class AbstractInstrumentBuilder<BuilderT extends AbstractInstrumentBuilder<BuilderT>> {
abstract class AbstractInstrumentBuilder<BUILDER extends AbstractInstrumentBuilder<BUILDER>> {
protected final MeterSharedState meterSharedState;
protected final String name;
@Nullable protected String description;
Expand All @@ -31,14 +31,14 @@ protected AbstractInstrumentBuilder(
this.unit = unit;
}

protected abstract BuilderT self();
protected abstract BUILDER self();

public BuilderT setDescription(String description) {
public BUILDER setDescription(String description) {
this.description = description;
return self();
}

public BuilderT setUnit(String unit) {
public BUILDER setUnit(String unit) {
this.unit = unit;
return self();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package io.opentelemetry.contrib.metrics.micrometer.internal.instruments;

import io.micrometer.core.instrument.FunctionCounter;
import io.micrometer.core.instrument.Gauge;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.contrib.metrics.micrometer.internal.state.InstrumentState;
import java.util.Map;
Expand All @@ -28,7 +28,7 @@ protected final void record(double value, Attributes attributes) {

private AtomicDoubleCounter createCounter(Attributes attributes) {
AtomicDoubleCounter counter = new AtomicDoubleCounter();
FunctionCounter.builder(name(), counter, AtomicDoubleCounter::current)
Gauge.builder(name(), counter, AtomicDoubleCounter::current)
.tags(attributesToTags(attributes))
.description(description())
.baseUnit(unit())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ final class AtomicDoubleCounter {
@SuppressWarnings("UnusedVariable")
private volatile long doubleBits;

public double current() {
double current() {
return Double.longBitsToDouble(doubleBits);
}

public boolean increment(double increment) {
boolean increment(double increment) {
while (true) {
double current = current();
double update = current + increment;
Expand All @@ -28,12 +28,12 @@ public boolean increment(double increment) {
}
}

public boolean set(double value) {
boolean set(double value) {
BITS_UPDATER.set(this, Double.doubleToRawLongBits(value));
return true;
}

public boolean setMonotonically(double value) {
boolean setMonotonically(double value) {
while (true) {
double current = current();
if (current > value) {
Expand All @@ -45,7 +45,7 @@ public boolean setMonotonically(double value) {
}
}

public boolean compareAndSet(double expected, double update) {
boolean compareAndSet(double expected, double update) {
long expectedBits = Double.doubleToRawLongBits(expected);
long updateBits = Double.doubleToRawLongBits(update);
return BITS_UPDATER.compareAndSet(this, expectedBits, updateBits);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,23 @@ private MicrometerDoubleCounter(InstrumentState instrumentState) {

@Override
public void add(double value) {
counter(Attributes.empty()).increment(value);
if (value >= 0.0) {
counter(Attributes.empty()).increment(value);
}
}

@Override
public void add(double value, Attributes attributes) {
counter(attributes).increment(value);
if (value >= 0.0) {
counter(attributes).increment(value);
}
}

@Override
public void add(double value, Attributes attributes, Context context) {
counter(attributes).increment(value);
if (value >= 0.0) {
counter(attributes).increment(value);
}
}

public static DoubleCounterBuilder builder(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,23 @@ private MicrometerLongCounter(InstrumentState instrumentState) {

@Override
public void add(long value) {
counter(Attributes.empty()).increment((double) value);
if (value > 0L) {
counter(Attributes.empty()).increment((double) value);
}
}

@Override
public void add(long value, Attributes attributes) {
counter(attributes).increment((double) value);
if (value > 0L) {
counter(attributes).increment((double) value);
}
}

@Override
public void add(long value, Attributes attributes, Context context) {
counter(attributes).increment((double) value);
if (value > 0L) {
counter(attributes).increment((double) value);
}
}

public static LongCounterBuilder builder(MeterSharedState meterSharedState, String name) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.metrics.micrometer.internal;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class MemoizingSupplierTest {

@Mock Supplier<String> supplier;

@Test
void callsGetOnlyOnce() {
when(supplier.get()).thenReturn("RESULT");

Supplier<String> underTest = new MemoizingSupplier<>(supplier);

verifyNoInteractions(supplier);

assertThat(underTest.get()).isEqualTo("RESULT");
verify(supplier, times(1)).get();

assertThat(underTest.get()).isEqualTo("RESULT");
verifyNoMoreInteractions(supplier);
}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit befdef4

Please sign in to comment.