Skip to content

Commit 2524b48

Browse files
Mateusz RzeszutekRashmiRam
authored andcommitted
Change the way Micrometer LongTaskTimer is bridged (open-telemetry#5338)
1 parent a1a15bb commit 2524b48

File tree

12 files changed

+170
-202
lines changed

12 files changed

+170
-202
lines changed

instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/internal/AsyncInstrumentRegistry.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public static AsyncInstrumentRegistry getOrCreate(Meter meter) {
6464
private final Map<String, LongMeasurementsRecorder> longCounters = new ConcurrentHashMap<>();
6565
private final Map<String, DoubleMeasurementsRecorder> upDownDoubleCounters =
6666
new ConcurrentHashMap<>();
67+
private final Map<String, LongMeasurementsRecorder> upDownLongCounters =
68+
new ConcurrentHashMap<>();
6769

6870
AsyncInstrumentRegistry(Meter meter) {
6971
this.meter = new WeakReference<>(meter);
@@ -150,7 +152,7 @@ public <T> AsyncMeasurementHandle buildUpDownDoubleCounter(
150152
String description,
151153
String baseUnit,
152154
Attributes attributes,
153-
T obj,
155+
@Nullable T obj,
154156
ToDoubleFunction<T> objMetric) {
155157

156158
DoubleMeasurementsRecorder recorder =
@@ -171,6 +173,31 @@ public <T> AsyncMeasurementHandle buildUpDownDoubleCounter(
171173
return new AsyncMeasurementHandle(recorder, attributes);
172174
}
173175

176+
public <T> AsyncMeasurementHandle buildUpDownLongCounter(
177+
String name,
178+
String description,
179+
String baseUnit,
180+
Attributes attributes,
181+
@Nullable T obj,
182+
ToLongFunction<T> objMetric) {
183+
184+
LongMeasurementsRecorder recorder =
185+
upDownLongCounters.computeIfAbsent(
186+
name,
187+
n -> {
188+
LongMeasurementsRecorder recorderCallback = new LongMeasurementsRecorder();
189+
otelMeter()
190+
.upDownCounterBuilder(name)
191+
.setDescription(description)
192+
.setUnit(baseUnit)
193+
.buildWithCallback(recorderCallback);
194+
return recorderCallback;
195+
});
196+
recorder.addMeasurement(attributes, new LongMeasurementSource<>(obj, objMetric));
197+
198+
return new AsyncMeasurementHandle(recorder, attributes);
199+
}
200+
174201
private Meter otelMeter() {
175202
Meter otelMeter = meter.get();
176203
if (otelMeter == null) {

instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/Bridging.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,7 @@ static Attributes tagsAsAttributes(Meter.Id id, NamingConvention namingConventio
3333
}
3434

3535
static String name(Meter.Id id, NamingConvention namingConvention) {
36-
return name(id.getName(), id, namingConvention);
37-
}
38-
39-
private static String name(String name, Meter.Id id, NamingConvention namingConvention) {
40-
return namingConvention.name(name, id.getType(), id.getBaseUnit());
36+
return namingConvention.name(id.getName(), id.getType(), id.getBaseUnit());
4137
}
4238

4339
static String description(Meter.Id id) {
@@ -56,7 +52,7 @@ static String statisticInstrumentName(
5652
// use "total_time" instead of "total" to avoid clashing with Statistic.TOTAL
5753
String statisticStr =
5854
statistic == Statistic.TOTAL_TIME ? "total_time" : statistic.getTagValueRepresentation();
59-
return name(prefix + statisticStr, id, namingConvention);
55+
return namingConvention.name(prefix + statisticStr, id.getType(), id.getBaseUnit());
6056
}
6157

6258
private Bridging() {}

instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryDistributionSummary.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@
88
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.baseUnit;
99
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description;
1010
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name;
11-
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName;
1211
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes;
1312

1413
import io.micrometer.core.instrument.AbstractDistributionSummary;
1514
import io.micrometer.core.instrument.Clock;
1615
import io.micrometer.core.instrument.DistributionSummary;
1716
import io.micrometer.core.instrument.Measurement;
18-
import io.micrometer.core.instrument.Statistic;
1917
import io.micrometer.core.instrument.config.NamingConvention;
2018
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
2119
import io.micrometer.core.instrument.distribution.NoopHistogram;
@@ -59,15 +57,17 @@ final class OpenTelemetryDistributionSummary extends AbstractDistributionSummary
5957
max = new TimeWindowMax(clock, distributionStatisticConfig);
6058

6159
this.attributes = tagsAsAttributes(id, namingConvention);
60+
61+
String conventionName = name(id, namingConvention);
6262
this.otelHistogram =
6363
otelMeter
64-
.histogramBuilder(name(id, namingConvention))
64+
.histogramBuilder(conventionName)
6565
.setDescription(description(id))
6666
.setUnit(baseUnit(id))
6767
.build();
6868
this.maxHandle =
6969
asyncInstrumentRegistry.buildGauge(
70-
statisticInstrumentName(id, Statistic.MAX, namingConvention),
70+
conventionName + ".max",
7171
description(id),
7272
baseUnit(id),
7373
attributes,

instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryFunctionTimer.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
package io.opentelemetry.instrumentation.micrometer.v1_5;
77

88
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description;
9-
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName;
9+
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name;
1010
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes;
1111
import static io.opentelemetry.instrumentation.micrometer.v1_5.TimeUnitHelper.getUnitString;
1212

1313
import io.micrometer.core.instrument.FunctionTimer;
1414
import io.micrometer.core.instrument.Measurement;
15-
import io.micrometer.core.instrument.Statistic;
1615
import io.micrometer.core.instrument.config.NamingConvention;
1716
import io.micrometer.core.instrument.util.MeterEquivalence;
1817
import io.micrometer.core.instrument.util.TimeUtils;
@@ -46,8 +45,8 @@ final class OpenTelemetryFunctionTimer<T> implements FunctionTimer, RemovableMet
4645
this.id = id;
4746
this.baseTimeUnit = baseTimeUnit;
4847

49-
String countMeterName = statisticInstrumentName(id, Statistic.COUNT, namingConvention);
50-
String totalTimeMeterName = statisticInstrumentName(id, Statistic.TOTAL_TIME, namingConvention);
48+
String countMeterName = name(id, namingConvention) + ".count";
49+
String totalTimeMeterName = name(id, namingConvention) + ".sum";
5150
Attributes attributes = tagsAsAttributes(id, namingConvention);
5251

5352
countMeasurementHandle =

instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryLongTaskTimer.java

Lines changed: 25 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7,72 +7,55 @@
77

88
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description;
99
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name;
10-
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName;
1110
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes;
1211
import static io.opentelemetry.instrumentation.micrometer.v1_5.TimeUnitHelper.getUnitString;
1312

1413
import io.micrometer.core.instrument.Clock;
1514
import io.micrometer.core.instrument.Measurement;
16-
import io.micrometer.core.instrument.Statistic;
1715
import io.micrometer.core.instrument.config.NamingConvention;
1816
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
1917
import io.micrometer.core.instrument.internal.DefaultLongTaskTimer;
20-
import io.micrometer.core.instrument.util.TimeUtils;
2118
import io.opentelemetry.api.common.Attributes;
22-
import io.opentelemetry.api.metrics.DoubleHistogram;
23-
import io.opentelemetry.api.metrics.LongUpDownCounter;
24-
import io.opentelemetry.api.metrics.Meter;
19+
import io.opentelemetry.instrumentation.api.internal.AsyncInstrumentRegistry;
20+
import io.opentelemetry.instrumentation.api.internal.AsyncInstrumentRegistry.AsyncMeasurementHandle;
2521
import java.util.Collections;
2622
import java.util.concurrent.TimeUnit;
2723

2824
final class OpenTelemetryLongTaskTimer extends DefaultLongTaskTimer implements RemovableMeter {
2925

30-
private final TimeUnit baseTimeUnit;
3126
private final DistributionStatisticConfig distributionStatisticConfig;
32-
// TODO: use bound instruments when they're available
33-
private final DoubleHistogram otelHistogram;
34-
private final LongUpDownCounter otelActiveTasksCounter;
35-
private final Attributes attributes;
36-
37-
private volatile boolean removed = false;
27+
private final AsyncMeasurementHandle activeTasksHandle;
28+
private final AsyncMeasurementHandle durationHandle;
3829

3930
OpenTelemetryLongTaskTimer(
4031
Id id,
4132
NamingConvention namingConvention,
4233
Clock clock,
4334
TimeUnit baseTimeUnit,
4435
DistributionStatisticConfig distributionStatisticConfig,
45-
Meter otelMeter) {
36+
AsyncInstrumentRegistry asyncInstrumentRegistry) {
4637
super(id, clock, baseTimeUnit, distributionStatisticConfig, false);
4738

48-
this.baseTimeUnit = baseTimeUnit;
4939
this.distributionStatisticConfig = distributionStatisticConfig;
5040

51-
this.otelHistogram =
52-
otelMeter
53-
.histogramBuilder(name(id, namingConvention))
54-
.setDescription(description(id))
55-
.setUnit(getUnitString(baseTimeUnit))
56-
.build();
57-
this.otelActiveTasksCounter =
58-
otelMeter
59-
.upDownCounterBuilder(
60-
statisticInstrumentName(id, Statistic.ACTIVE_TASKS, namingConvention))
61-
.setDescription(description(id))
62-
.setUnit("tasks")
63-
.build();
64-
this.attributes = tagsAsAttributes(id, namingConvention);
65-
}
66-
67-
@Override
68-
public Sample start() {
69-
Sample original = super.start();
70-
if (removed) {
71-
return original;
72-
}
73-
74-
otelActiveTasksCounter.add(1, attributes);
75-
return new OpenTelemetrySample(original);
41+
String conventionName = name(id, namingConvention);
42+
Attributes attributes = tagsAsAttributes(id, namingConvention);
43+
this.activeTasksHandle =
44+
asyncInstrumentRegistry.buildUpDownLongCounter(
45+
conventionName + ".active",
46+
description(id),
47+
"tasks",
48+
attributes,
49+
this,
50+
DefaultLongTaskTimer::activeTasks);
51+
this.durationHandle =
52+
asyncInstrumentRegistry.buildUpDownDoubleCounter(
53+
conventionName + ".duration",
54+
description(id),
55+
getUnitString(baseTimeUnit),
56+
attributes,
57+
this,
58+
t -> t.duration(baseTimeUnit));
7659
}
7760

7861
@Override
@@ -83,41 +66,12 @@ public Iterable<Measurement> measure() {
8366

8467
@Override
8568
public void onRemove() {
86-
removed = true;
69+
activeTasksHandle.remove();
70+
durationHandle.remove();
8771
}
8872

8973
boolean isUsingMicrometerHistograms() {
9074
return distributionStatisticConfig.isPublishingPercentiles()
9175
|| distributionStatisticConfig.isPublishingHistogram();
9276
}
93-
94-
private final class OpenTelemetrySample extends Sample {
95-
96-
private final Sample original;
97-
private volatile boolean stopped = false;
98-
99-
private OpenTelemetrySample(Sample original) {
100-
this.original = original;
101-
}
102-
103-
@Override
104-
public long stop() {
105-
if (stopped) {
106-
return -1;
107-
}
108-
stopped = true;
109-
long durationNanos = original.stop();
110-
if (!removed) {
111-
otelActiveTasksCounter.add(-1, attributes);
112-
double time = TimeUtils.nanosToUnit(durationNanos, baseTimeUnit);
113-
otelHistogram.record(time, attributes);
114-
}
115-
return durationNanos;
116-
}
117-
118-
@Override
119-
public double duration(TimeUnit unit) {
120-
return stopped ? -1 : original.duration(unit);
121-
}
122-
}
12377
}

instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryMeterRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ protected LongTaskTimer newLongTaskTimer(
8787
clock,
8888
getBaseTimeUnit(),
8989
distributionStatisticConfig,
90-
otelMeter);
90+
asyncInstrumentRegistry);
9191
if (timer.isUsingMicrometerHistograms()) {
9292
HistogramGauges.registerWithCommonFormat(timer, this);
9393
}

instrumentation/micrometer/micrometer-1.5/library/src/main/java/io/opentelemetry/instrumentation/micrometer/v1_5/OpenTelemetryTimer.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@
77

88
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.description;
99
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.name;
10-
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.statisticInstrumentName;
1110
import static io.opentelemetry.instrumentation.micrometer.v1_5.Bridging.tagsAsAttributes;
1211
import static io.opentelemetry.instrumentation.micrometer.v1_5.TimeUnitHelper.getUnitString;
1312

1413
import io.micrometer.core.instrument.AbstractTimer;
1514
import io.micrometer.core.instrument.Clock;
1615
import io.micrometer.core.instrument.Measurement;
17-
import io.micrometer.core.instrument.Statistic;
1816
import io.micrometer.core.instrument.config.NamingConvention;
1917
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
2018
import io.micrometer.core.instrument.distribution.NoopHistogram;
@@ -62,15 +60,17 @@ final class OpenTelemetryTimer extends AbstractTimer implements RemovableMeter {
6260

6361
this.baseTimeUnit = baseTimeUnit;
6462
this.attributes = tagsAsAttributes(id, namingConvention);
63+
64+
String conventionName = name(id, namingConvention);
6565
this.otelHistogram =
6666
otelMeter
67-
.histogramBuilder(name(id, namingConvention))
67+
.histogramBuilder(conventionName)
6868
.setDescription(description(id))
6969
.setUnit(getUnitString(baseTimeUnit))
7070
.build();
7171
this.maxHandle =
7272
asyncInstrumentRegistry.buildGauge(
73-
statisticInstrumentName(id, Statistic.MAX, namingConvention),
73+
conventionName + ".max",
7474
description(id),
7575
getUnitString(baseTimeUnit),
7676
attributes,

instrumentation/micrometer/micrometer-1.5/library/src/test/java/io/opentelemetry/instrumentation/micrometer/v1_5/NamingConventionTest.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import io.micrometer.core.instrument.Counter;
1212
import io.micrometer.core.instrument.DistributionSummary;
13+
import io.micrometer.core.instrument.LongTaskTimer;
1314
import io.micrometer.core.instrument.Meter;
1415
import io.micrometer.core.instrument.MeterRegistry;
1516
import io.micrometer.core.instrument.Metrics;
@@ -178,7 +179,7 @@ void renameFunctionTimer() {
178179
.containsOnly(attributeEntry("test.tag", "test.value")))));
179180
testing.waitAndAssertMetrics(
180181
INSTRUMENTATION_NAME,
181-
"test.renamedFunctionTimer.total_time",
182+
"test.renamedFunctionTimer.sum",
182183
metrics ->
183184
metrics.anySatisfy(
184185
metric ->
@@ -214,6 +215,43 @@ void renameGauge() {
214215
.containsOnly(attributeEntry("test.tag", "test.value")))));
215216
}
216217

218+
@Test
219+
void renameLongTaskTimer() {
220+
// when
221+
LongTaskTimer timer = Metrics.more().longTaskTimer("renamedLongTaskTimer", "tag", "value");
222+
timer.start().stop();
223+
224+
// then
225+
testing.waitAndAssertMetrics(
226+
INSTRUMENTATION_NAME,
227+
"test.renamedLongTaskTimer.active",
228+
metrics ->
229+
metrics.anySatisfy(
230+
metric ->
231+
assertThat(metric)
232+
.hasLongSum()
233+
.points()
234+
.satisfiesExactly(
235+
point ->
236+
assertThat(point)
237+
.attributes()
238+
.containsOnly(attributeEntry("test.tag", "test.value")))));
239+
testing.waitAndAssertMetrics(
240+
INSTRUMENTATION_NAME,
241+
"test.renamedLongTaskTimer.duration",
242+
metrics ->
243+
metrics.anySatisfy(
244+
metric ->
245+
assertThat(metric)
246+
.hasDoubleSum()
247+
.points()
248+
.satisfiesExactly(
249+
point ->
250+
assertThat(point)
251+
.attributes()
252+
.containsOnly(attributeEntry("test.tag", "test.value")))));
253+
}
254+
217255
@Test
218256
void renameTimer() {
219257
// when

0 commit comments

Comments
 (0)