Skip to content

Commit

Permalink
Add experimental synchronous gauge (#5506)
Browse files Browse the repository at this point in the history
  • Loading branch information
jack-berg committed Sep 7, 2023
1 parent 43ee51c commit a5889a6
Show file tree
Hide file tree
Showing 13 changed files with 902 additions and 360 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.extension.incubator.metrics;

import io.opentelemetry.api.common.Attributes;
import javax.annotation.concurrent.ThreadSafe;

/** A gauge instrument that synchronously records {@code double} values. */
@ThreadSafe
public interface DoubleGauge {
/**
* Set the gauge value.
*
* @param value The current gauge value.
*/
void set(double value);

/**
* Records a value with a set of attributes.
*
* @param value The current gauge value.
* @param attributes A set of attributes to associate with the value.
*/
void set(double value, Attributes attributes);

// TODO(jack-berg): should we add overload with Context argument?
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
/** Extended {@link DoubleGaugeBuilder} with experimental APIs. */
public interface ExtendedDoubleGaugeBuilder extends DoubleGaugeBuilder {

/**
* Builds and returns a DoubleGauge instrument with the configuration.
*
* <p>NOTE: This produces a synchronous gauge which records gauge values as they occur. Most users
* will want to instead register an {@link #buildWithCallback(Consumer)} to asynchronously observe
* the value of the gauge when metrics are collected.
*
* @return The DoubleGauge instrument.
*/
DoubleGauge build();

/** Specify advice for gauge implementations. */
default DoubleGaugeBuilder setAdvice(Consumer<DoubleGaugeAdviceConfigurer> adviceConsumer) {
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
/** Extended {@link LongGaugeBuilder} with experimental APIs. */
public interface ExtendedLongGaugeBuilder extends LongGaugeBuilder {

/**
* Builds and returns a LongGauge instrument with the configuration.
*
* <p>NOTE: This produces a synchronous gauge which records gauge values as they occur. Most users
* will want to instead register an {@link #buildWithCallback(Consumer)} to asynchronously observe
* the value of the gauge when metrics are collected.
*
* @return The LongGauge instrument.
*/
LongGauge build();

/** Specify advice for gauge implementations. */
default LongGaugeBuilder setAdvice(Consumer<LongGaugeAdviceConfigurer> adviceConsumer) {
return this;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.extension.incubator.metrics;

import io.opentelemetry.api.common.Attributes;
import javax.annotation.concurrent.ThreadSafe;

/** A gauge instrument that synchronously records {@code long} values. */
@ThreadSafe
public interface LongGauge {
/**
* Set the gauge value.
*
* @param value The current gauge value.
*/
void set(long value);

/**
* Records a value with a set of attributes.
*
* @param value The current gauge value.
* @param attributes A set of attributes to associate with the value.
*/
void set(long value, Attributes attributes);

// TODO(jack-berg): should we add overload with Context argument?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.metrics;

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.DoubleGaugeAdviceConfigurer;
import io.opentelemetry.extension.incubator.metrics.ExtendedDoubleGaugeBuilder;
import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.state.MeterProviderSharedState;
import io.opentelemetry.sdk.metrics.internal.state.MeterSharedState;
import io.opentelemetry.sdk.metrics.internal.state.WriteableMetricStorage;
import java.util.List;
import java.util.function.Consumer;

final class SdkDoubleGauge extends AbstractInstrument implements DoubleGauge {

private final WriteableMetricStorage storage;

private SdkDoubleGauge(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
super(descriptor);
this.storage = storage;
}

@Override
public void set(double increment, Attributes attributes) {
storage.recordDouble(increment, attributes, Context.root());
}

@Override
public void set(double increment) {
set(increment, Attributes.empty());
}

static final class SdkDoubleGaugeBuilder extends AbstractInstrumentBuilder<SdkDoubleGaugeBuilder>
implements ExtendedDoubleGaugeBuilder, DoubleGaugeAdviceConfigurer {

SdkDoubleGaugeBuilder(
MeterProviderSharedState meterProviderSharedState,
MeterSharedState meterSharedState,
String name) {
super(
meterProviderSharedState,
meterSharedState,
// TODO: use InstrumentType.GAUGE when available
InstrumentType.OBSERVABLE_GAUGE,
InstrumentValueType.DOUBLE,
name,
"",
DEFAULT_UNIT);
}

@Override
protected SdkDoubleGaugeBuilder getThis() {
return this;
}

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

@Override
public DoubleGaugeBuilder setAdvice(Consumer<DoubleGaugeAdviceConfigurer> adviceConsumer) {
adviceConsumer.accept(this);
return this;
}

@Override
public DoubleGaugeAdviceConfigurer setAttributes(List<AttributeKey<?>> attributes) {
adviceBuilder.setAttributes(attributes);
return this;
}

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

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

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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.metrics;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongGaugeBuilder;
import io.opentelemetry.api.metrics.ObservableLongGauge;
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
import io.opentelemetry.context.Context;
import io.opentelemetry.extension.incubator.metrics.ExtendedLongGaugeBuilder;
import io.opentelemetry.extension.incubator.metrics.LongGauge;
import io.opentelemetry.extension.incubator.metrics.LongGaugeAdviceConfigurer;
import io.opentelemetry.sdk.metrics.internal.descriptor.Advice;
import io.opentelemetry.sdk.metrics.internal.descriptor.InstrumentDescriptor;
import io.opentelemetry.sdk.metrics.internal.state.MeterProviderSharedState;
import io.opentelemetry.sdk.metrics.internal.state.MeterSharedState;
import io.opentelemetry.sdk.metrics.internal.state.WriteableMetricStorage;
import java.util.List;
import java.util.function.Consumer;

final class SdkLongGauge extends AbstractInstrument implements LongGauge {

private final WriteableMetricStorage storage;

private SdkLongGauge(InstrumentDescriptor descriptor, WriteableMetricStorage storage) {
super(descriptor);
this.storage = storage;
}

@Override
public void set(long increment, Attributes attributes) {
storage.recordLong(increment, attributes, Context.root());
}

@Override
public void set(long increment) {
set(increment, Attributes.empty());
}

static final class SdkLongGaugeBuilder extends AbstractInstrumentBuilder<SdkLongGaugeBuilder>
implements ExtendedLongGaugeBuilder, LongGaugeAdviceConfigurer {

SdkLongGaugeBuilder(
MeterProviderSharedState meterProviderSharedState,
MeterSharedState sharedState,
String name,
String description,
String unit,
Advice.AdviceBuilder adviceBuilder) {
super(
meterProviderSharedState,
sharedState,
// TODO: use InstrumentType.GAUGE when available
InstrumentType.OBSERVABLE_GAUGE,
InstrumentValueType.LONG,
name,
description,
unit,
adviceBuilder);
}

@Override
protected SdkLongGaugeBuilder getThis() {
return this;
}

@Override
public SdkLongGauge build() {
return buildSynchronousInstrument(SdkLongGauge::new);
}

@Override
public LongGaugeBuilder setAdvice(Consumer<LongGaugeAdviceConfigurer> adviceConsumer) {
adviceConsumer.accept(this);
return this;
}

@Override
public LongGaugeAdviceConfigurer setAttributes(List<AttributeKey<?>> attributes) {
adviceBuilder.setAttributes(attributes);
return this;
}

@Override
public ObservableLongGauge buildWithCallback(Consumer<ObservableLongMeasurement> callback) {
// TODO: use InstrumentType.GAUGE when available
return registerLongAsynchronousInstrument(InstrumentType.OBSERVABLE_GAUGE, callback);
}

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

0 comments on commit a5889a6

Please sign in to comment.