Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Metrics incubator APIs to accept advice #1190

Merged
merged 6 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion micrometer-meter-provider/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ otelJava.moduleName.set("io.opentelemetry.contrib.metrics.micrometer")
dependencies {
api("io.opentelemetry:opentelemetry-api")
api("io.opentelemetry:opentelemetry-sdk-metrics")
api("io.opentelemetry:opentelemetry-extension-incubator")

compileOnly("io.micrometer:micrometer-core:1.1.0") // do not auto-update this version
compileOnly("io.micrometer:micrometer-core:1.5.0") // do not auto-update this version
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")

annotationProcessor("com.google.auto.service:auto-service")
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,15 @@ protected final Counter counter(Attributes attributes) {
.register(meterRegistry());
}

protected final void record(double value, Attributes attributes) {
protected final void increment(Attributes attributes, double value) {
if (value >= 0.0) {
counter(attributes).increment(value);
}
}

protected final void setMonotonically(Attributes attributes, double value) {
counterMap
.computeIfAbsent(attributesOrEmpty(attributes), this::createAsyncCounter)
.computeIfAbsent(effectiveAttributes(attributes), this::createAsyncCounter)
.setMonotonically(value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ protected AbstractGauge(InstrumentState instrumentState) {
super(instrumentState);
}

protected final void record(double value, Attributes attributes) {
gaugeMap.computeIfAbsent(attributesOrEmpty(attributes), this::createAsyncGauge).set(value);
protected final void record(Attributes attributes, double value) {
gaugeMap.computeIfAbsent(effectiveAttributes(attributes), this::createAsyncGauge).set(value);
}

private AtomicDoubleCounter createAsyncGauge(Attributes attributes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,36 @@
import io.micrometer.core.instrument.DistributionSummary;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.contrib.metrics.micrometer.internal.state.InstrumentState;
import java.util.List;
import javax.annotation.Nullable;

abstract class AbstractHistogram extends AbstractInstrument {
@Nullable private final List<? extends Number> explicitBucketBoundaries;

protected AbstractHistogram(InstrumentState instrumentState) {
super(instrumentState);
this.explicitBucketBoundaries = instrumentState.explicitBucketBoundariesAdvice();
}

public DistributionSummary distribution(Attributes attributes) {
return DistributionSummary.builder(name())
.tags(attributesToTags(attributes))
.description(description())
.baseUnit(unit())
.serviceLevelObjectives(serviceLevelObjectives(explicitBucketBoundaries))
.register(meterRegistry());
}

@Nullable
private static double[] serviceLevelObjectives(
@Nullable List<? extends Number> explicitBucketBoundaries) {
if (explicitBucketBoundaries == null) {
return null;
}
double[] slos = new double[explicitBucketBoundaries.size()];
for (int i = 0; i < explicitBucketBoundaries.size(); i++) {
slos[i] = explicitBucketBoundaries.get(i).doubleValue();
}
return slos;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,19 @@

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
import io.opentelemetry.contrib.metrics.micrometer.CallbackRegistration;
import io.opentelemetry.contrib.metrics.micrometer.internal.state.InstrumentState;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.logging.Level;
Expand All @@ -28,13 +31,20 @@ abstract class AbstractInstrument {
private final Logger logger;
private final Tag instrumentationNameTag;
private final Tag instrumentationVersionTag;
@Nullable private final Set<AttributeKey<?>> attributeKeySet;
private final Map<Attributes, Iterable<Tag>> attributesTagsCache;

protected AbstractInstrument(InstrumentState instrumentState) {
this.instrumentState = instrumentState;
this.logger = Logger.getLogger(getClass().getName());
this.instrumentationNameTag = instrumentState.instrumentationScopeNameTag();
this.instrumentationVersionTag = instrumentState.instrumentationScopeVersionTag();
List<AttributeKey<?>> attributes = instrumentState.attributesAdvice();
if (attributes != null) {
attributeKeySet = new HashSet<>(attributes);
} else {
attributeKeySet = null;
}
this.attributesTagsCache = new ConcurrentHashMap<>();
}

Expand All @@ -56,19 +66,27 @@ protected final String unit() {
return instrumentState.unit();
}

protected final Attributes attributesOrEmpty(@Nullable Attributes attributes) {
return attributes != null ? attributes : Attributes.empty();
protected final Attributes effectiveAttributes(@Nullable Attributes attributes) {
if (attributes == null) {
return Attributes.empty();
}
if (attributeKeySet == null) {
return attributes;
}
return attributes.toBuilder().removeIf(key -> !attributeKeySet.contains(key)).build();
}

@SuppressWarnings("PreferredInterfaceType")
protected final Iterable<Tag> attributesToTags(Attributes attributes) {
return attributesTagsCache.computeIfAbsent(attributesOrEmpty(attributes), this::calculateTags);
return attributesTagsCache.computeIfAbsent(
effectiveAttributes(attributes), this::calculateTags);
}

@SuppressWarnings("PreferredInterfaceType")
private Iterable<Tag> calculateTags(Attributes attributes) {
List<Tag> list = new ArrayList<>(attributes.size() + 2);
attributes.forEach(
Attributes effectiveAttributes = effectiveAttributes(attributes);
List<Tag> list = new ArrayList<>(effectiveAttributes.size() + 2);
effectiveAttributes.forEach(
(attributeKey, value) -> list.add(Tag.of(attributeKey.getKey(), Objects.toString(value))));

list.add(instrumentationNameTag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,32 @@
package io.opentelemetry.contrib.metrics.micrometer.internal.instruments;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.contrib.metrics.micrometer.internal.state.InstrumentState;
import io.opentelemetry.contrib.metrics.micrometer.internal.state.MeterSharedState;
import java.util.List;
import javax.annotation.Nullable;

abstract class AbstractInstrumentBuilder<BUILDER extends AbstractInstrumentBuilder<BUILDER>> {
protected final MeterSharedState meterSharedState;
protected final String name;
@Nullable protected String description;
@Nullable protected String unit;
@Nullable protected List<AttributeKey<?>> attributes;
@Nullable protected List<? extends Number> explicitBucketBoundaries;

protected AbstractInstrumentBuilder(MeterSharedState meterSharedState, String name) {
this.meterSharedState = meterSharedState;
this.name = name;
}

protected AbstractInstrumentBuilder(
MeterSharedState meterSharedState,
String name,
@Nullable String description,
@Nullable String unit) {
this.meterSharedState = meterSharedState;
this.name = name;
this.description = description;
this.unit = unit;
protected AbstractInstrumentBuilder(AbstractInstrumentBuilder<?> parent) {
this.meterSharedState = parent.meterSharedState;
this.name = parent.name;
this.description = parent.description;
this.unit = parent.unit;
this.attributes = parent.attributes;
this.explicitBucketBoundaries = parent.explicitBucketBoundaries;
}

protected abstract BUILDER self();
Expand All @@ -46,7 +48,20 @@ public BUILDER setUnit(String unit) {
return self();
}

@CanIgnoreReturnValue
public BUILDER setAttributesAdvice(List<AttributeKey<?>> attributes) {
this.attributes = attributes;
return self();
}

@CanIgnoreReturnValue
public BUILDER setExplicitBucketBoundaries(List<? extends Number> explicitBucketBoundaries) {
this.explicitBucketBoundaries = explicitBucketBoundaries;
return self();
}

protected InstrumentState createInstrumentState() {
return new InstrumentState(meterSharedState, name, description, unit);
return new InstrumentState(
meterSharedState, name, description, unit, attributes, explicitBucketBoundaries);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ protected AbstractUpDownCounter(InstrumentState instrumentState) {
}

protected final void add(Attributes attributes, double value) {
counterMap.computeIfAbsent(attributesOrEmpty(attributes), this::createCounter).increment(value);
counter(attributes).increment(value);
}

protected final void record(double value, Attributes attributes) {
counterMap.computeIfAbsent(attributesOrEmpty(attributes), this::createCounter).set(value);
protected final void record(Attributes attributes, double value) {
counter(attributes).set(value);
}

protected final AtomicDoubleCounter counter(Attributes attributes) {
return counterMap.computeIfAbsent(effectiveAttributes(attributes), this::createCounter);
}

private AtomicDoubleCounter createCounter(Attributes attributes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,53 +12,49 @@
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
import io.opentelemetry.context.Context;
import io.opentelemetry.contrib.metrics.micrometer.internal.state.InstrumentState;
import io.opentelemetry.contrib.metrics.micrometer.internal.state.MeterSharedState;
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleCounterBuilder;
import java.util.function.Consumer;
import javax.annotation.Nullable;

final class MicrometerDoubleCounter extends AbstractCounter implements DoubleCounter {
final class MicrometerDoubleCounter extends AbstractCounter
implements DoubleCounter, ObservableDoubleMeasurement {

private MicrometerDoubleCounter(InstrumentState instrumentState) {
super(instrumentState);
}

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

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

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

@Override
public void record(double value) {
setMonotonically(Attributes.empty(), value);
}

public static DoubleCounterBuilder builder(
MeterSharedState meterSharedState,
String name,
@Nullable String description,
@Nullable String unit) {
return new Builder(meterSharedState, name, description, unit);
@Override
public void record(double value, Attributes attributes) {
setMonotonically(attributes, value);
}

private static class Builder extends AbstractInstrumentBuilder<Builder>
implements DoubleCounterBuilder {
private Builder(
MeterSharedState meterSharedState,
String name,
@Nullable String description,
@Nullable String unit) {
super(meterSharedState, name, description, unit);
public static DoubleCounterBuilder builder(MicrometerLongCounter.Builder parent) {
return new Builder(parent);
}

static final class Builder extends AbstractInstrumentBuilder<Builder>
implements DoubleCounterBuilder, ExtendedDoubleCounterBuilder {
private Builder(MicrometerLongCounter.Builder parent) {
super(parent);
}

@Override
Expand All @@ -75,19 +71,7 @@ public MicrometerDoubleCounter build() {
public ObservableDoubleCounter buildWithCallback(
Consumer<ObservableDoubleMeasurement> callback) {
MicrometerDoubleCounter instrument = build();
return instrument.registerDoubleCallback(
callback,
new ObservableDoubleMeasurement() {
@Override
public void record(double value) {
record(value, Attributes.empty());
}

@Override
public void record(double value, Attributes attributes) {
instrument.record(value, attributes);
}
});
return instrument.registerDoubleCallback(callback, instrument);
}
}
}
Loading
Loading