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

Dismantle AbstractInstrumentBuilder inheritance hierarchy #5820

Merged
merged 11 commits into from
Oct 13, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -5,105 +5,65 @@

package io.opentelemetry.sdk.metrics;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
import io.opentelemetry.sdk.metrics.internal.descriptor.Advice;
import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.descriptor.MutableInstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.state.CallbackRegistration;
import io.opentelemetry.sdk.metrics.internal.state.MeterProviderSharedState;
import io.opentelemetry.sdk.metrics.internal.state.MeterSharedState;
import io.opentelemetry.sdk.metrics.internal.state.SdkObservableMeasurement;
import io.opentelemetry.sdk.metrics.internal.state.WriteableMetricStorage;
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;

/** Helper to make implementing builders easier. */
abstract class AbstractInstrumentBuilder<BuilderT extends AbstractInstrumentBuilder<?>> {

static final String DEFAULT_UNIT = "";
final class InstrumentBuilder {

private final MeterProviderSharedState meterProviderSharedState;
private final InstrumentType type;
private final InstrumentValueType valueType;
private String description;
private String unit;

protected final MeterSharedState meterSharedState;
protected final String instrumentName;
protected final Advice.AdviceBuilder adviceBuilder;

AbstractInstrumentBuilder(
MeterProviderSharedState meterProviderSharedState,
MeterSharedState meterSharedState,
InstrumentType type,
InstrumentValueType valueType,
String name,
String description,
String unit) {
this(
meterProviderSharedState,
meterSharedState,
type,
valueType,
name,
description,
unit,
Advice.builder());
}
private final MeterSharedState meterSharedState;
private final MutableInstrumentDescriptor descriptor;

AbstractInstrumentBuilder(
InstrumentBuilder(
MeterProviderSharedState meterProviderSharedState,
MeterSharedState meterSharedState,
InstrumentType type,
InstrumentValueType valueType,
String name,
String description,
String unit,
Advice.AdviceBuilder adviceBuilder) {
this.type = type;
this.valueType = valueType;
this.instrumentName = name;
this.description = description;
this.unit = unit;
MutableInstrumentDescriptor descriptor) {
this.meterProviderSharedState = meterProviderSharedState;
this.meterSharedState = meterSharedState;
this.adviceBuilder = adviceBuilder;
this.descriptor = descriptor;
}

protected abstract BuilderT getThis();

public BuilderT setUnit(String unit) {
this.unit = unit;
return getThis();
public void setUnit(String unit) {
descriptor.setUnit(unit);
}

public BuilderT setDescription(String description) {
this.description = description;
return getThis();
public void setDescription(String description) {
descriptor.setDescription(description);
}

protected <T> T swapBuilder(SwapBuilder<T> swapper) {
<T> T swapBuilder(SwapBuilder<T> swapper) {
return swapper.newBuilder(
meterProviderSharedState,
meterSharedState,
instrumentName,
description,
unit,
adviceBuilder);
descriptor.getName(),
descriptor.getDescription(),
descriptor.getUnit(),
descriptor.getAdviceBuilder());
}

final <I extends AbstractInstrument> I buildSynchronousInstrument(
<I extends AbstractInstrument> I buildSynchronousInstrument(
BiFunction<InstrumentDescriptor, WriteableMetricStorage, I> instrumentFactory) {
InstrumentDescriptor descriptor =
InstrumentDescriptor.create(
instrumentName, description, unit, type, valueType, adviceBuilder.build());
InstrumentDescriptor descriptor = this.descriptor.toImmutable();
WriteableMetricStorage storage =
meterSharedState.registerSynchronousMetricStorage(descriptor, meterProviderSharedState);
return instrumentFactory.apply(descriptor, storage);
}

final SdkObservableInstrument registerDoubleAsynchronousInstrument(
SdkObservableInstrument buildDoubleAsynchronousInstrument(
InstrumentType type, Consumer<ObservableDoubleMeasurement> updater) {
SdkObservableMeasurement sdkObservableMeasurement = buildObservableMeasurement(type);
Runnable runnable = () -> updater.accept(sdkObservableMeasurement);
Expand All @@ -113,7 +73,7 @@ final SdkObservableInstrument registerDoubleAsynchronousInstrument(
return new SdkObservableInstrument(meterSharedState, callbackRegistration);
}

final SdkObservableInstrument registerLongAsynchronousInstrument(
SdkObservableInstrument buildLongAsynchronousInstrument(
InstrumentType type, Consumer<ObservableLongMeasurement> updater) {
SdkObservableMeasurement sdkObservableMeasurement = buildObservableMeasurement(type);
Runnable runnable = () -> updater.accept(sdkObservableMeasurement);
Expand All @@ -123,20 +83,19 @@ final SdkObservableInstrument registerLongAsynchronousInstrument(
return new SdkObservableInstrument(meterSharedState, callbackRegistration);
}

final SdkObservableMeasurement buildObservableMeasurement(InstrumentType type) {
InstrumentDescriptor descriptor =
InstrumentDescriptor.create(
instrumentName, description, unit, type, valueType, adviceBuilder.build());
SdkObservableMeasurement buildObservableMeasurement(InstrumentType type) {
this.descriptor.setType(type);
InstrumentDescriptor descriptor = this.descriptor.toImmutable();
return meterSharedState.registerObservableMeasurement(descriptor);
}

@Override
public String toString() {
return this.getClass().getSimpleName()
+ "{descriptor="
+ InstrumentDescriptor.create(
instrumentName, description, unit, type, valueType, adviceBuilder.build())
+ "}";
return toStringHelper(getClass().getSimpleName());
}

String toStringHelper(String className) {
return className + "{descriptor=" + descriptor.toImmutable() + "}";
}

@FunctionalInterface
Expand All @@ -149,4 +108,12 @@ T newBuilder(
String unit,
Advice.AdviceBuilder adviceBuilder);
}

void setAdviceAttributes(List<AttributeKey<?>> attributes) {
descriptor.setAdviceAttributes(attributes);
}

void setExplicitBucketBoundaries(List<Double> bucketBoundaries) {
descriptor.setExplicitBucketBoundaries(bucketBoundaries);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleCounter;
import io.opentelemetry.api.metrics.DoubleCounterBuilder;
import io.opentelemetry.api.metrics.ObservableDoubleCounter;
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
import io.opentelemetry.context.Context;
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleCounterBuilder;
import io.opentelemetry.sdk.internal.ThrottlingLogger;
import io.opentelemetry.sdk.metrics.internal.descriptor.Advice;
import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.descriptor.MutableInstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.state.MeterProviderSharedState;
import io.opentelemetry.sdk.metrics.internal.state.MeterSharedState;
import io.opentelemetry.sdk.metrics.internal.state.WriteableMetricStorage;
Expand Down Expand Up @@ -57,9 +59,9 @@
add(increment, Attributes.empty());
}

static final class SdkDoubleCounterBuilder
extends AbstractInstrumentBuilder<SdkDoubleCounterBuilder>
implements ExtendedDoubleCounterBuilder {
static final class SdkDoubleCounterBuilder implements ExtendedDoubleCounterBuilder {

private final InstrumentBuilder builder;

SdkDoubleCounterBuilder(
MeterProviderSharedState meterProviderSharedState,
Expand All @@ -68,42 +70,54 @@
String description,
String unit,
Advice.AdviceBuilder adviceBuilder) {
super(
meterProviderSharedState,
sharedState,
InstrumentType.COUNTER,
InstrumentValueType.DOUBLE,
name,
description,
unit,
adviceBuilder);
MutableInstrumentDescriptor descriptor =
MutableInstrumentDescriptor.create(
name,
InstrumentType.COUNTER,
InstrumentValueType.DOUBLE,
description,
unit,
adviceBuilder);
this.builder = new InstrumentBuilder(meterProviderSharedState, sharedState, descriptor);
}

@Override
public SdkDoubleCounter build() {
return builder.buildSynchronousInstrument(SdkDoubleCounter::new);
}

@Override
protected SdkDoubleCounterBuilder getThis() {
public DoubleCounterBuilder setDescription(String description) {
builder.setDescription(description);
return this;
}

@Override
public SdkDoubleCounter build() {
return buildSynchronousInstrument(SdkDoubleCounter::new);
public DoubleCounterBuilder setUnit(String unit) {
builder.setUnit(unit);
return this;
}

@Override
public ObservableDoubleCounter buildWithCallback(
Consumer<ObservableDoubleMeasurement> callback) {
return registerDoubleAsynchronousInstrument(InstrumentType.OBSERVABLE_COUNTER, callback);
return builder.buildDoubleAsynchronousInstrument(InstrumentType.OBSERVABLE_COUNTER, callback);
}

@Override
public ObservableDoubleMeasurement buildObserver() {
return buildObservableMeasurement(InstrumentType.OBSERVABLE_COUNTER);
return builder.buildObservableMeasurement(InstrumentType.OBSERVABLE_COUNTER);
}

@Override
public ExtendedDoubleCounterBuilder setAttributesAdvice(List<AttributeKey<?>> attributes) {
adviceBuilder.setAttributes(attributes);
builder.setAdviceAttributes(attributes);
return this;
}

@Override
public String toString() {
breedx-splk marked this conversation as resolved.
Show resolved Hide resolved
return builder.toStringHelper(getClass().getSimpleName());

Check warning on line 120 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleCounter.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleCounter.java#L120

Added line #L120 was not covered by tests
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.DoubleGaugeBuilder;
import io.opentelemetry.api.metrics.LongGaugeBuilder;
import io.opentelemetry.api.metrics.ObservableDoubleGauge;
import io.opentelemetry.api.metrics.ObservableDoubleMeasurement;
import io.opentelemetry.context.Context;
import io.opentelemetry.extension.incubator.metrics.DoubleGauge;
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleGaugeBuilder;
import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.descriptor.MutableInstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.state.MeterProviderSharedState;
import io.opentelemetry.sdk.metrics.internal.state.MeterSharedState;
import io.opentelemetry.sdk.metrics.internal.state.WriteableMetricStorage;
Expand All @@ -39,55 +41,64 @@
set(increment, Attributes.empty());
}

static final class SdkDoubleGaugeBuilder extends AbstractInstrumentBuilder<SdkDoubleGaugeBuilder>
implements ExtendedDoubleGaugeBuilder {
static final class SdkDoubleGaugeBuilder implements ExtendedDoubleGaugeBuilder {
private final InstrumentBuilder builder;

SdkDoubleGaugeBuilder(
MeterProviderSharedState meterProviderSharedState,
MeterSharedState meterSharedState,
String name) {
super(
meterProviderSharedState,
meterSharedState,
// TODO: use InstrumentType.GAUGE when available
breedx-splk marked this conversation as resolved.
Show resolved Hide resolved
InstrumentType.OBSERVABLE_GAUGE,
InstrumentValueType.DOUBLE,
name,
"",
DEFAULT_UNIT);

MutableInstrumentDescriptor descriptor =
MutableInstrumentDescriptor.create(
// TODO: use InstrumentType.GAUGE when available
name, InstrumentType.OBSERVABLE_GAUGE, InstrumentValueType.DOUBLE);
builder = new InstrumentBuilder(meterProviderSharedState, meterSharedState, descriptor);
}

@Override
public DoubleGaugeBuilder setDescription(String description) {
builder.setDescription(description);
return this;
}

@Override
protected SdkDoubleGaugeBuilder getThis() {
public DoubleGaugeBuilder setUnit(String unit) {
builder.setUnit(unit);
return this;
}

@Override
public SdkDoubleGauge build() {
return buildSynchronousInstrument(SdkDoubleGauge::new);
return builder.buildSynchronousInstrument(SdkDoubleGauge::new);
}

@Override
public ExtendedDoubleGaugeBuilder setAttributesAdvice(List<AttributeKey<?>> attributes) {
adviceBuilder.setAttributes(attributes);
builder.setAdviceAttributes(attributes);
return this;
}

@Override
public LongGaugeBuilder ofLongs() {
return swapBuilder(SdkLongGauge.SdkLongGaugeBuilder::new);
return builder.swapBuilder(SdkLongGauge.SdkLongGaugeBuilder::new);
}

@Override
public ObservableDoubleGauge buildWithCallback(Consumer<ObservableDoubleMeasurement> callback) {
// TODO: use InstrumentType.GAUGE when available
return registerDoubleAsynchronousInstrument(InstrumentType.OBSERVABLE_GAUGE, callback);
return builder.buildDoubleAsynchronousInstrument(InstrumentType.OBSERVABLE_GAUGE, callback);
}

@Override
public ObservableDoubleMeasurement buildObserver() {
// TODO: use InstrumentType.GAUGE when available
return buildObservableMeasurement(InstrumentType.OBSERVABLE_GAUGE);
return builder.buildObservableMeasurement(InstrumentType.OBSERVABLE_GAUGE);
}

@Override
public String toString() {
return builder.toStringHelper(getClass().getSimpleName());

Check warning on line 101 in sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleGauge.java

View check run for this annotation

Codecov / codecov/patch

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/SdkDoubleGauge.java#L101

Added line #L101 was not covered by tests
}
}
}
Loading