Skip to content

Commit c7d472a

Browse files
authored
Stabilize synchronous gauge (#6419)
1 parent ca79821 commit c7d472a

File tree

21 files changed

+346
-136
lines changed

21 files changed

+346
-136
lines changed

api/all/src/main/java/io/opentelemetry/api/metrics/DefaultMeter.java

+39-4
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,10 @@ public LongHistogram build() {
320320
}
321321

322322
private static class NoopDoubleGaugeBuilder implements DoubleGaugeBuilder {
323-
private static final ObservableDoubleGauge NOOP = new ObservableDoubleGauge() {};
323+
private static final ObservableDoubleGauge NOOP_OBSERVABLE_GAUGE =
324+
new ObservableDoubleGauge() {};
324325
private static final LongGaugeBuilder NOOP_LONG_GAUGE_BUILDER = new NoopLongGaugeBuilder();
326+
private static final NoopDoubleGauge NOOP_GAUGE = new NoopDoubleGauge();
325327

326328
@Override
327329
public DoubleGaugeBuilder setDescription(String description) {
@@ -340,17 +342,34 @@ public LongGaugeBuilder ofLongs() {
340342

341343
@Override
342344
public ObservableDoubleGauge buildWithCallback(Consumer<ObservableDoubleMeasurement> callback) {
343-
return NOOP;
345+
return NOOP_OBSERVABLE_GAUGE;
344346
}
345347

346348
@Override
347349
public ObservableDoubleMeasurement buildObserver() {
348350
return NOOP_OBSERVABLE_DOUBLE_MEASUREMENT;
349351
}
352+
353+
@Override
354+
public DoubleGauge build() {
355+
return NOOP_GAUGE;
356+
}
357+
}
358+
359+
private static class NoopDoubleGauge implements DoubleGauge {
360+
@Override
361+
public void set(double value) {}
362+
363+
@Override
364+
public void set(double value, Attributes attributes) {}
365+
366+
@Override
367+
public void set(double value, Attributes attributes, Context context) {}
350368
}
351369

352370
private static class NoopLongGaugeBuilder implements LongGaugeBuilder {
353-
private static final ObservableLongGauge NOOP = new ObservableLongGauge() {};
371+
private static final ObservableLongGauge NOOP_OBSERVABLE_GAUGE = new ObservableLongGauge() {};
372+
private static final NoopLongGauge NOOP_GAUGE = new NoopLongGauge();
354373

355374
@Override
356375
public LongGaugeBuilder setDescription(String description) {
@@ -364,13 +383,29 @@ public LongGaugeBuilder setUnit(String unit) {
364383

365384
@Override
366385
public ObservableLongGauge buildWithCallback(Consumer<ObservableLongMeasurement> callback) {
367-
return NOOP;
386+
return NOOP_OBSERVABLE_GAUGE;
368387
}
369388

370389
@Override
371390
public ObservableLongMeasurement buildObserver() {
372391
return NOOP_OBSERVABLE_LONG_MEASUREMENT;
373392
}
393+
394+
@Override
395+
public LongGauge build() {
396+
return NOOP_GAUGE;
397+
}
398+
}
399+
400+
private static class NoopLongGauge implements LongGauge {
401+
@Override
402+
public void set(long value) {}
403+
404+
@Override
405+
public void set(long value, Attributes attributes) {}
406+
407+
@Override
408+
public void set(long value, Attributes attributes, Context context) {}
374409
}
375410

376411
private static class NoopObservableDoubleMeasurement implements ObservableDoubleMeasurement {

api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/DoubleGauge.java renamed to api/all/src/main/java/io/opentelemetry/api/metrics/DoubleGauge.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
package io.opentelemetry.api.incubator.metrics;
6+
package io.opentelemetry.api.metrics;
77

88
import io.opentelemetry.api.common.Attributes;
9+
import io.opentelemetry.context.Context;
910
import javax.annotation.concurrent.ThreadSafe;
1011

1112
/** A gauge instrument that synchronously records {@code double} values. */
@@ -26,5 +27,12 @@ public interface DoubleGauge {
2627
*/
2728
void set(double value, Attributes attributes);
2829

29-
// TODO(jack-berg): should we add overload with Context argument?
30+
/**
31+
* Records a value with a set of attributes.
32+
*
33+
* @param value The current gauge value.
34+
* @param attributes A set of attributes to associate with the value.
35+
* @param context The explicit context to associate with this measurement.
36+
*/
37+
void set(double value, Attributes attributes, Context context);
3038
}

api/all/src/main/java/io/opentelemetry/api/metrics/DoubleGaugeBuilder.java

+16
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,20 @@ public interface DoubleGaugeBuilder {
6565
default ObservableDoubleMeasurement buildObserver() {
6666
return DefaultMeter.getInstance().gaugeBuilder("noop").buildObserver();
6767
}
68+
69+
/**
70+
* Builds and returns a DoubleGauge instrument with the configuration.
71+
*
72+
* <p>NOTE: This produces a synchronous gauge which records gauge values as they occur. Most users
73+
* will want to instead register an {@link #buildWithCallback(Consumer)} to asynchronously observe
74+
* the value of the gauge when metrics are collected.
75+
*
76+
* <p>If using the OpenTelemetry SDK, by default gauges use last value aggregation, such that only
77+
* the value of the last recorded measurement is exported.
78+
*
79+
* @return The DoubleGauge instrument.
80+
*/
81+
default DoubleGauge build() {
82+
return DefaultMeter.getInstance().gaugeBuilder("noop").build();
83+
}
6884
}

api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/LongGauge.java renamed to api/all/src/main/java/io/opentelemetry/api/metrics/LongGauge.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
package io.opentelemetry.api.incubator.metrics;
6+
package io.opentelemetry.api.metrics;
77

88
import io.opentelemetry.api.common.Attributes;
9+
import io.opentelemetry.context.Context;
910
import javax.annotation.concurrent.ThreadSafe;
1011

1112
/** A gauge instrument that synchronously records {@code long} values. */
@@ -26,5 +27,12 @@ public interface LongGauge {
2627
*/
2728
void set(long value, Attributes attributes);
2829

29-
// TODO(jack-berg): should we add overload with Context argument?
30+
/**
31+
* Records a value with a set of attributes.
32+
*
33+
* @param value The current gauge value.
34+
* @param attributes A set of attributes to associate with the value.
35+
* @param context The explicit context to associate with this measurement.
36+
*/
37+
void set(long value, Attributes attributes, Context context);
3038
}

api/all/src/main/java/io/opentelemetry/api/metrics/LongGaugeBuilder.java

+16
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,20 @@ public interface LongGaugeBuilder {
6262
default ObservableLongMeasurement buildObserver() {
6363
return DefaultMeter.getInstance().gaugeBuilder("noop").ofLongs().buildObserver();
6464
}
65+
66+
/**
67+
* Builds and returns a LongGauge instrument with the configuration.
68+
*
69+
* <p>NOTE: This produces a synchronous gauge which records gauge values as they occur. Most users
70+
* will want to instead register an {@link #buildWithCallback(Consumer)} to asynchronously observe
71+
* the value of the gauge when metrics are collected.
72+
*
73+
* <p>If using the OpenTelemetry SDK, by default gauges use last value aggregation, such that only
74+
* the value of the last recorded measurement is exported.
75+
*
76+
* @return The LongGauge instrument.
77+
*/
78+
default LongGauge build() {
79+
return DefaultMeter.getInstance().gaugeBuilder("noop").ofLongs().build();
80+
}
6581
}

api/all/src/test/java/io/opentelemetry/api/metrics/DefaultMeterTest.java

+27
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,20 @@ void noopDoubleHistogram_doesNotThrow() {
9393
histogram.record(1.0e-1, Attributes.of(stringKey("thing"), "car"), Context.current());
9494
}
9595

96+
@Test
97+
void noopLongGauage_doesNotThrow() {
98+
LongGauge gauge =
99+
METER
100+
.gaugeBuilder("temperature")
101+
.ofLongs()
102+
.setDescription("The current temperature")
103+
.setUnit("C")
104+
.build();
105+
gauge.set(1);
106+
gauge.set(2, Attributes.of(stringKey("thing"), "engine"));
107+
gauge.set(2, Attributes.of(stringKey("thing"), "engine"), Context.current());
108+
}
109+
96110
@Test
97111
void noopObservableLongGauage_doesNotThrow() {
98112
METER
@@ -107,6 +121,19 @@ void noopObservableLongGauage_doesNotThrow() {
107121
});
108122
}
109123

124+
@Test
125+
void noopDoubleGauage_doesNotThrow() {
126+
DoubleGauge gauge =
127+
METER
128+
.gaugeBuilder("temperature")
129+
.setDescription("The current temperature")
130+
.setUnit("C")
131+
.build();
132+
gauge.set(1);
133+
gauge.set(2, Attributes.of(stringKey("thing"), "engine"));
134+
gauge.set(2, Attributes.of(stringKey("thing"), "engine"), Context.current());
135+
}
136+
110137
@Test
111138
void noopObservableDoubleGauage_doesNotThrow() {
112139
METER

api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedDoubleGaugeBuilder.java

-12
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,10 @@
88
import io.opentelemetry.api.common.AttributeKey;
99
import io.opentelemetry.api.metrics.DoubleGaugeBuilder;
1010
import java.util.List;
11-
import java.util.function.Consumer;
1211

1312
/** Extended {@link DoubleGaugeBuilder} with experimental APIs. */
1413
public interface ExtendedDoubleGaugeBuilder extends DoubleGaugeBuilder {
1514

16-
/**
17-
* Builds and returns a DoubleGauge instrument with the configuration.
18-
*
19-
* <p>NOTE: This produces a synchronous gauge which records gauge values as they occur. Most users
20-
* will want to instead register an {@link #buildWithCallback(Consumer)} to asynchronously observe
21-
* the value of the gauge when metrics are collected.
22-
*
23-
* @return The DoubleGauge instrument.
24-
*/
25-
DoubleGauge build();
26-
2715
/**
2816
* Specify the attribute advice, which suggests the recommended set of attribute keys to be used
2917
* for this gauge.

api/incubator/src/main/java/io/opentelemetry/api/incubator/metrics/ExtendedLongGaugeBuilder.java

-12
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,10 @@
88
import io.opentelemetry.api.common.AttributeKey;
99
import io.opentelemetry.api.metrics.LongGaugeBuilder;
1010
import java.util.List;
11-
import java.util.function.Consumer;
1211

1312
/** Extended {@link LongGaugeBuilder} with experimental APIs. */
1413
public interface ExtendedLongGaugeBuilder extends LongGaugeBuilder {
1514

16-
/**
17-
* Builds and returns a LongGauge instrument with the configuration.
18-
*
19-
* <p>NOTE: This produces a synchronous gauge which records gauge values as they occur. Most users
20-
* will want to instead register an {@link #buildWithCallback(Consumer)} to asynchronously observe
21-
* the value of the gauge when metrics are collected.
22-
*
23-
* @return The LongGauge instrument.
24-
*/
25-
LongGauge build();
26-
2715
/**
2816
* Specify the attribute advice, which suggests the recommended set of attribute keys to be used
2917
* for this gauge.

api/incubator/src/test/java/io/opentelemetry/api/incubator/metrics/ExtendedMetricsApiUsageTest.java

-42
Original file line numberDiff line numberDiff line change
@@ -23,48 +23,6 @@
2323
/** Demonstrating usage of extended Metrics API. */
2424
class ExtendedMetricsApiUsageTest {
2525

26-
@Test
27-
void synchronousGaugeUsage() {
28-
// Setup SdkMeterProvider
29-
InMemoryMetricReader reader = InMemoryMetricReader.create();
30-
SdkMeterProvider meterProvider =
31-
SdkMeterProvider.builder()
32-
// Default resource used for demonstration purposes
33-
.setResource(Resource.getDefault())
34-
// In-memory reader used for demonstration purposes
35-
.registerMetricReader(reader)
36-
.build();
37-
38-
// Get a Meter for a scope
39-
Meter meter = meterProvider.get("org.foo.my-scope");
40-
41-
// Cast GaugeBuilder to ExtendedDoubleGaugeBuilder
42-
DoubleGauge gauge = ((ExtendedDoubleGaugeBuilder) meter.gaugeBuilder("my-gauge")).build();
43-
44-
// Call set synchronously to set the value
45-
gauge.set(1.0, Attributes.builder().put("key", "value1").build());
46-
gauge.set(2.0, Attributes.builder().put("key", "value2").build());
47-
48-
assertThat(reader.collectAllMetrics())
49-
.satisfiesExactly(
50-
metricData ->
51-
assertThat(metricData)
52-
.hasName("my-gauge")
53-
.hasDoubleGaugeSatisfying(
54-
gaugeAssert ->
55-
gaugeAssert.hasPointsSatisfying(
56-
point ->
57-
point
58-
.hasValue(1.0)
59-
.hasAttributes(
60-
Attributes.builder().put("key", "value1").build()),
61-
point ->
62-
point
63-
.hasValue(2.0)
64-
.hasAttributes(
65-
Attributes.builder().put("key", "value2").build()))));
66-
}
67-
6826
@Test
6927
void attributesAdvice() {
7028
// Setup SdkMeterProvider
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,19 @@
11
Comparing source compatibility of against
2-
No changes.
2+
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.api.metrics.DoubleGauge (not serializable)
3+
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
4+
+++ NEW SUPERCLASS: java.lang.Object
5+
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void set(double)
6+
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void set(double, io.opentelemetry.api.common.Attributes)
7+
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void set(double, io.opentelemetry.api.common.Attributes, io.opentelemetry.context.Context)
8+
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.api.metrics.DoubleGaugeBuilder (not serializable)
9+
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
10+
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.metrics.DoubleGauge build()
11+
+++ NEW INTERFACE: PUBLIC(+) ABSTRACT(+) io.opentelemetry.api.metrics.LongGauge (not serializable)
12+
+++ CLASS FILE FORMAT VERSION: 52.0 <- n.a.
13+
+++ NEW SUPERCLASS: java.lang.Object
14+
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void set(long)
15+
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void set(long, io.opentelemetry.api.common.Attributes)
16+
+++ NEW METHOD: PUBLIC(+) ABSTRACT(+) void set(long, io.opentelemetry.api.common.Attributes, io.opentelemetry.context.Context)
17+
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.api.metrics.LongGaugeBuilder (not serializable)
18+
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
19+
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.api.metrics.LongGauge build()

docs/apidiffs/current_vs_latest/opentelemetry-sdk-metrics.txt

+3
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ Comparing source compatibility of against
55
*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector (not serializable)
66
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
77
+++ NEW METHOD: PUBLIC(+) STATIC(+) java.lang.String asString(io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector)
8+
*** MODIFIED ENUM: PUBLIC FINAL io.opentelemetry.sdk.metrics.InstrumentType (compatible)
9+
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
10+
+++ NEW FIELD: PUBLIC(+) STATIC(+) FINAL(+) io.opentelemetry.sdk.metrics.InstrumentType GAUGE

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/InstrumentType.java

+1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ public enum InstrumentType {
1717
OBSERVABLE_COUNTER,
1818
OBSERVABLE_UP_DOWN_COUNTER,
1919
OBSERVABLE_GAUGE,
20+
GAUGE,
2021
}

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

+9-7
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
import io.opentelemetry.api.common.AttributeKey;
99
import io.opentelemetry.api.common.Attributes;
10-
import io.opentelemetry.api.incubator.metrics.DoubleGauge;
1110
import io.opentelemetry.api.incubator.metrics.ExtendedDoubleGaugeBuilder;
11+
import io.opentelemetry.api.metrics.DoubleGauge;
1212
import io.opentelemetry.api.metrics.DoubleGaugeBuilder;
1313
import io.opentelemetry.api.metrics.LongGaugeBuilder;
1414
import io.opentelemetry.api.metrics.ObservableDoubleGauge;
@@ -31,8 +31,13 @@ private SdkDoubleGauge(InstrumentDescriptor descriptor, WriteableMetricStorage s
3131
}
3232

3333
@Override
34-
public void set(double increment, Attributes attributes) {
35-
storage.recordDouble(increment, attributes, Context.root());
34+
public void set(double value, Attributes attributes) {
35+
storage.recordDouble(value, attributes, Context.current());
36+
}
37+
38+
@Override
39+
public void set(double value, Attributes attributes, Context context) {
40+
storage.recordDouble(value, attributes, context);
3641
}
3742

3843
@Override
@@ -48,11 +53,10 @@ static final class SdkDoubleGaugeBuilder implements ExtendedDoubleGaugeBuilder {
4853
MeterSharedState meterSharedState,
4954
String name) {
5055

51-
// TODO: use InstrumentType.GAUGE when available
5256
builder =
5357
new InstrumentBuilder(
5458
name,
55-
InstrumentType.OBSERVABLE_GAUGE,
59+
InstrumentType.GAUGE,
5660
InstrumentValueType.DOUBLE,
5761
meterProviderSharedState,
5862
meterSharedState);
@@ -88,13 +92,11 @@ public LongGaugeBuilder ofLongs() {
8892

8993
@Override
9094
public ObservableDoubleGauge buildWithCallback(Consumer<ObservableDoubleMeasurement> callback) {
91-
// TODO: use InstrumentType.GAUGE when available
9295
return builder.buildDoubleAsynchronousInstrument(InstrumentType.OBSERVABLE_GAUGE, callback);
9396
}
9497

9598
@Override
9699
public ObservableDoubleMeasurement buildObserver() {
97-
// TODO: use InstrumentType.GAUGE when available
98100
return builder.buildObservableMeasurement(InstrumentType.OBSERVABLE_GAUGE);
99101
}
100102

0 commit comments

Comments
 (0)