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,6 +5,7 @@

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;
Expand All @@ -15,95 +16,64 @@
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 String name;
private final MeterProviderSharedState meterProviderSharedState;
private final InstrumentType type;
private final MeterSharedState meterSharedState;
private final InstrumentValueType valueType;
private String description;
private String unit;

protected final MeterSharedState meterSharedState;
protected final String instrumentName;
protected final Advice.AdviceBuilder adviceBuilder;
private InstrumentType type;
private Advice.AdviceBuilder adviceBuilder = Advice.builder();
private String description = "";
private String unit = "";

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

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

protected abstract BuilderT getThis();

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

InstrumentBuilder setAdviceBuilder(Advice.AdviceBuilder adviceBuilder) {
this.adviceBuilder = adviceBuilder;
return this;
}

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

protected <T> T swapBuilder(SwapBuilder<T> swapper) {
<T> T swapBuilder(SwapBuilder<T> swapper) {
return swapper.newBuilder(
meterProviderSharedState,
meterSharedState,
instrumentName,
description,
unit,
adviceBuilder);
meterProviderSharedState, meterSharedState, name, description, unit, adviceBuilder);
}

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 = newDescriptor();
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 +83,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 +93,24 @@ 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.type = type;
InstrumentDescriptor descriptor = newDescriptor();
return meterSharedState.registerObservableMeasurement(descriptor);
}

private InstrumentDescriptor newDescriptor() {
return InstrumentDescriptor.create(
name, description, unit, type, valueType, adviceBuilder.build());
}

@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=" + newDescriptor() + "}";
}

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

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

void setExplicitBucketBoundaries(List<Double> bucketBoundaries) {
adviceBuilder.setExplicitBucketBoundaries(bucketBoundaries);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
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;
Expand Down Expand Up @@ -57,9 +58,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 +69,55 @@
String description,
String unit,
Advice.AdviceBuilder adviceBuilder) {
super(
meterProviderSharedState,
sharedState,
InstrumentType.COUNTER,
InstrumentValueType.DOUBLE,
name,
description,
unit,
adviceBuilder);
this.builder =
new InstrumentBuilder(
name,
InstrumentType.COUNTER,
InstrumentValueType.DOUBLE,
meterProviderSharedState,
sharedState)
.setUnit(unit)
.setDescription(description)
.setAdviceBuilder(adviceBuilder);
}

@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,6 +7,7 @@

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;
Expand Down Expand Up @@ -39,55 +40,67 @@
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);

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

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

@Override
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 103 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#L103

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