Skip to content

Commit b828fe3

Browse files
Add capability to have configurable aggregation temporality for OTLP Registry (#3625)
OTLP format supports delta and cumulative temporality. This adds the capability to export meters with delta temporality. Below are some behaviours this PR includes * capability to configure aggregation Temporality via property `otlp.aggregationTemporality` * Delta Temporality is supported by using StepMeters wherever applicable * Capability to export max as part of the HistogramDataPoint for Delta Temporality There are some remaining issues with using delta temporality. Fixes for these will be made as follow-ups. * max value in histogram is not right * histogram counts are not right * partial steps may not publish correct values Closes gh-3145 Co-authored-by: Jonatan Ivanov <[email protected]>
1 parent 3c6e834 commit b828fe3

14 files changed

+752
-88
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2023 VMware, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.micrometer.registry.otlp;
17+
18+
/**
19+
* AggregationTemporality defines the way additive values are expressed.
20+
*
21+
* @see <a href=
22+
* "https://opentelemetry.io/docs/reference/specification/metrics/data-model/#temporality">OTLP
23+
* Temporality</a>
24+
* @author Lenin Jaganathan
25+
* @since 1.11.0
26+
*/
27+
public enum AggregationTemporality {
28+
29+
/**
30+
* Reported values do not incorporate previous measurements.
31+
*/
32+
DELTA,
33+
34+
/**
35+
* Reported values incorporate previous measurements.
36+
*/
37+
CUMULATIVE;
38+
39+
public static io.opentelemetry.proto.metrics.v1.AggregationTemporality toOtlpAggregationTemporality(
40+
AggregationTemporality aggregationTemporality) {
41+
switch (aggregationTemporality) {
42+
case DELTA:
43+
return io.opentelemetry.proto.metrics.v1.AggregationTemporality.AGGREGATION_TEMPORALITY_DELTA;
44+
case CUMULATIVE:
45+
return io.opentelemetry.proto.metrics.v1.AggregationTemporality.AGGREGATION_TEMPORALITY_CUMULATIVE;
46+
default:
47+
return io.opentelemetry.proto.metrics.v1.AggregationTemporality.UNRECOGNIZED;
48+
}
49+
}
50+
51+
}

implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@
2626
import static io.micrometer.core.instrument.config.MeterRegistryConfigValidator.*;
2727
import static io.micrometer.core.instrument.config.validate.PropertyValidator.getString;
2828
import static io.micrometer.core.instrument.config.validate.PropertyValidator.getUrlString;
29+
import static io.micrometer.core.instrument.config.validate.PropertyValidator.getEnum;
2930

3031
/**
3132
* Config for {@link OtlpMeterRegistry}.
3233
*
3334
* @author Tommy Ludwig
35+
* @author Lenin Jaganathan
3436
* @since 1.9.0
3537
*/
3638
public interface OtlpConfig extends PushRegistryConfig {
@@ -88,6 +90,21 @@ default Map<String, String> resourceAttributes() {
8890
return resourceAttributes;
8991
}
9092

93+
/**
94+
* {@link AggregationTemporality} of the OtlpMeterRegistry. This determines whether
95+
* the meters should be cumulative(AGGREGATION_TEMPORALITY_CUMULATIVE) or
96+
* step/delta(AGGREGATION_TEMPORALITY_DELTA).
97+
* @return the aggregationTemporality for OtlpRegistry
98+
* @see <a href=
99+
* "https://opentelemetry.io/docs/reference/specification/metrics/data-model/#temporality">OTLP
100+
* Temporality</a>
101+
* @since 1.11.0
102+
*/
103+
default AggregationTemporality aggregationTemporality() {
104+
return getEnum(this, AggregationTemporality.class, "aggregationTemporality")
105+
.orElse(AggregationTemporality.CUMULATIVE);
106+
}
107+
91108
/**
92109
* Additional headers to send with exported metrics. This may be needed for
93110
* authorization headers, for example.
@@ -128,7 +145,8 @@ default Map<String, String> headers() {
128145
@Override
129146
default Validated<?> validate() {
130147
return checkAll(this, c -> PushRegistryConfig.validate(c), checkRequired("url", OtlpConfig::url),
131-
check("resourceAttributes", OtlpConfig::resourceAttributes));
148+
check("resourceAttributes", OtlpConfig::resourceAttributes),
149+
check("aggregationTemporality", OtlpConfig::aggregationTemporality));
132150
}
133151

134152
}

implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpCounter.java renamed to implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpCumulativeCounter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020

2121
import java.util.concurrent.TimeUnit;
2222

23-
class OtlpCounter extends CumulativeCounter implements StartTimeAwareMeter {
23+
class OtlpCumulativeCounter extends CumulativeCounter implements StartTimeAwareMeter {
2424

2525
private final long startTimeNanos;
2626

27-
OtlpCounter(Id id, Clock clock) {
27+
OtlpCumulativeCounter(Id id, Clock clock) {
2828
super(id);
2929
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
3030
}
Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 VMware, Inc.
2+
* Copyright 2023 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,7 +23,7 @@
2323
import java.time.Duration;
2424
import java.util.concurrent.TimeUnit;
2525

26-
class OtlpDistributionSummary extends CumulativeDistributionSummary implements StartTimeAwareMeter {
26+
class OtlpCumulativeDistributionSummary extends CumulativeDistributionSummary implements StartTimeAwareMeter {
2727

2828
private static final CountAtBucket[] EMPTY_HISTOGRAM = new CountAtBucket[0];
2929

@@ -32,19 +32,13 @@ class OtlpDistributionSummary extends CumulativeDistributionSummary implements S
3232
@Nullable
3333
private final Histogram monotonicBucketCountHistogram;
3434

35-
OtlpDistributionSummary(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig, double scale,
36-
boolean supportsAggregablePercentiles) {
35+
OtlpCumulativeDistributionSummary(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig,
36+
double scale, boolean supportsAggregablePercentiles) {
3737
super(id, clock, DistributionStatisticConfig.builder()
38-
.percentilesHistogram(false) // avoid
39-
// a
40-
// histogram
41-
// for
42-
// percentiles/SLOs
43-
// in
44-
// the
45-
// super
46-
.serviceLevelObjectives() // we will use a different implementation here
47-
// instead
38+
// avoid a histogram for percentiles/SLOs in the super
39+
.percentilesHistogram(false)
40+
// we will use a different implementation here instead
41+
.serviceLevelObjectives()
4842
.build()
4943
.merge(distributionStatisticConfig), scale, false);
5044
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
@@ -55,10 +49,8 @@ class OtlpDistributionSummary extends CumulativeDistributionSummary implements S
5549
if (distributionStatisticConfig.isPublishingHistogram()) {
5650
this.monotonicBucketCountHistogram = new TimeWindowFixedBoundaryHistogram(clock,
5751
DistributionStatisticConfig.builder()
58-
.expiry(Duration.ofDays(1825)) // effectively
59-
// never
60-
// roll
61-
// over
52+
// effectively never roll over
53+
.expiry(Duration.ofDays(1825))
6254
.bufferLength(1)
6355
.build()
6456
.merge(distributionStatisticConfig),
@@ -84,13 +76,9 @@ public HistogramSnapshot takeSnapshot() {
8476
return snapshot;
8577
}
8678

79+
CountAtBucket[] histogramCounts = this.monotonicBucketCountHistogram.takeSnapshot(0, 0, 0).histogramCounts();
8780
return new HistogramSnapshot(snapshot.count(), snapshot.total(), snapshot.max(), snapshot.percentileValues(),
88-
histogramCounts(), snapshot::outputSummary);
89-
}
90-
91-
private CountAtBucket[] histogramCounts() {
92-
return this.monotonicBucketCountHistogram == null ? EMPTY_HISTOGRAM
93-
: this.monotonicBucketCountHistogram.takeSnapshot(0, 0, 0).histogramCounts();
81+
histogramCounts, snapshot::outputSummary);
9482
}
9583

9684
@Override

implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpFunctionCounter.java renamed to implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpCumulativeFunctionCounter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
import java.util.concurrent.TimeUnit;
2222
import java.util.function.ToDoubleFunction;
2323

24-
class OtlpFunctionCounter<T> extends CumulativeFunctionCounter<T> implements StartTimeAwareMeter {
24+
class OtlpCumulativeFunctionCounter<T> extends CumulativeFunctionCounter<T> implements StartTimeAwareMeter {
2525

2626
private final long startTimeNanos;
2727

28-
OtlpFunctionCounter(Id id, T obj, ToDoubleFunction<T> f, Clock clock) {
28+
OtlpCumulativeFunctionCounter(Id id, T obj, ToDoubleFunction<T> f, Clock clock) {
2929
super(id, obj, f);
3030
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
3131
}

implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpFunctionTimer.java renamed to implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpCumulativeFunctionTimer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
import java.util.function.ToDoubleFunction;
2323
import java.util.function.ToLongFunction;
2424

25-
class OtlpFunctionTimer<T> extends CumulativeFunctionTimer<T> implements StartTimeAwareMeter {
25+
class OtlpCumulativeFunctionTimer<T> extends CumulativeFunctionTimer<T> implements StartTimeAwareMeter {
2626

2727
private final long startTimeNanos;
2828

29-
OtlpFunctionTimer(Id id, T obj, ToLongFunction<T> countFunction, ToDoubleFunction<T> totalTimeFunction,
29+
OtlpCumulativeFunctionTimer(Id id, T obj, ToLongFunction<T> countFunction, ToDoubleFunction<T> totalTimeFunction,
3030
TimeUnit totalTimeFunctionUnit, TimeUnit baseTimeUnit, Clock clock) {
3131
super(id, obj, countFunction, totalTimeFunction, totalTimeFunctionUnit, baseTimeUnit);
3232
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());

implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpLongTaskTimer.java renamed to implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpCumulativeLongTaskTimer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121

2222
import java.util.concurrent.TimeUnit;
2323

24-
class OtlpLongTaskTimer extends CumulativeHistogramLongTaskTimer implements StartTimeAwareMeter {
24+
class OtlpCumulativeLongTaskTimer extends CumulativeHistogramLongTaskTimer implements StartTimeAwareMeter {
2525

2626
private final long startTimeNanos;
2727

28-
OtlpLongTaskTimer(Id id, Clock clock, TimeUnit baseTimeUnit,
28+
OtlpCumulativeLongTaskTimer(Id id, Clock clock, TimeUnit baseTimeUnit,
2929
DistributionStatisticConfig distributionStatisticConfig) {
3030
super(id, clock, baseTimeUnit, distributionStatisticConfig);
3131
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());

implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpTimer.java renamed to implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpCumulativeTimer.java

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022 VMware, Inc.
2+
* Copyright 2023 VMware, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,26 +25,20 @@
2525
import java.time.Duration;
2626
import java.util.concurrent.TimeUnit;
2727

28-
class OtlpTimer extends CumulativeTimer implements StartTimeAwareMeter {
28+
class OtlpCumulativeTimer extends CumulativeTimer implements StartTimeAwareMeter {
2929

3030
private final long startTimeNanos;
3131

3232
@Nullable
3333
private final Histogram monotonicCountBucketHistogram;
3434

35-
OtlpTimer(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig, PauseDetector pauseDetector,
36-
TimeUnit baseTimeUnit) {
35+
OtlpCumulativeTimer(Id id, Clock clock, DistributionStatisticConfig distributionStatisticConfig,
36+
PauseDetector pauseDetector, TimeUnit baseTimeUnit) {
3737
super(id, clock, DistributionStatisticConfig.builder()
38-
.percentilesHistogram(false) // avoid
39-
// a
40-
// histogram
41-
// for
42-
// percentiles/SLOs
43-
// in
44-
// the
45-
// super
46-
.serviceLevelObjectives() // we will use a different implementation here
47-
// instead
38+
// avoid a histogram for percentiles/SLOs in the super
39+
.percentilesHistogram(false)
40+
// we will use a different implementation here instead
41+
.serviceLevelObjectives()
4842
.build()
4943
.merge(distributionStatisticConfig), pauseDetector, baseTimeUnit, false);
5044
this.startTimeNanos = TimeUnit.MILLISECONDS.toNanos(clock.wallTime());
@@ -54,10 +48,8 @@ class OtlpTimer extends CumulativeTimer implements StartTimeAwareMeter {
5448
if (distributionStatisticConfig.isPublishingHistogram()) {
5549
this.monotonicCountBucketHistogram = new TimeWindowFixedBoundaryHistogram(clock,
5650
DistributionStatisticConfig.builder()
57-
.expiry(Duration.ofDays(1825)) // effectively
58-
// never
59-
// roll
60-
// over
51+
// effectively never roll over
52+
.expiry(Duration.ofDays(1825))
6153
.bufferLength(1)
6254
.build()
6355
.merge(distributionStatisticConfig),

0 commit comments

Comments
 (0)