Skip to content

Commit 0ba532c

Browse files
Fix merge conflicts and update since field
1 parent c61f1fe commit 0ba532c

File tree

10 files changed

+190
-189
lines changed

10 files changed

+190
-189
lines changed

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

Lines changed: 4 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import io.micrometer.core.ipc.http.HttpUrlConnectionSender;
4141
import io.micrometer.registry.otlp.internal.CumulativeBase2ExponentialHistogram;
4242
import io.micrometer.registry.otlp.internal.DeltaBase2ExponentialHistogram;
43-
import io.micrometer.registry.otlp.internal.ExponentialHistogramSnapShot;
4443
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest;
4544
import io.opentelemetry.proto.common.v1.AnyValue;
4645
import io.opentelemetry.proto.common.v1.KeyValue;
@@ -69,11 +68,6 @@ public class OtlpMeterRegistry extends PushMeterRegistry {
6968

7069
private static final ThreadFactory DEFAULT_THREAD_FACTORY = new NamedThreadFactory("otlp-metrics-publisher");
7170

72-
private static final ExponentialHistogramDataPoint.Buckets EMPTY_EXPONETIAL_HISTOGRAM_BUCKETS = ExponentialHistogramDataPoint.Buckets
73-
.newBuilder()
74-
.addAllBucketCounts(Collections.emptyList())
75-
.build();
76-
7771
private static final double[] EMPTY_SLO_WITH_POSITIVE_INF = new double[] { Double.POSITIVE_INFINITY };
7872

7973
private static final String TELEMETRY_SDK_NAME = "telemetry.sdk.name";
@@ -351,125 +345,6 @@ private long getInitialDelay() {
351345
return stepMillis - (clock.wallTime() % stepMillis) + 1;
352346
}
353347

354-
// VisibleForTesting
355-
Metric writeHistogramSupport(HistogramSupport histogramSupport) {
356-
Metric.Builder metricBuilder = getMetricBuilder(histogramSupport.getId());
357-
boolean isTimeBased = histogramSupport instanceof Timer || histogramSupport instanceof LongTaskTimer;
358-
HistogramSnapshot histogramSnapshot = histogramSupport.takeSnapshot();
359-
360-
Iterable<? extends KeyValue> tags = getTagsForId(histogramSupport.getId());
361-
long startTimeNanos = getStartTimeNanos(histogramSupport);
362-
double total = isTimeBased ? histogramSnapshot.total(getBaseTimeUnit()) : histogramSnapshot.total();
363-
long count = histogramSnapshot.count();
364-
365-
// if percentiles configured, use summary
366-
if (histogramSnapshot.percentileValues().length != 0) {
367-
SummaryDataPoint.Builder summaryData = SummaryDataPoint.newBuilder()
368-
.addAllAttributes(tags)
369-
.setStartTimeUnixNano(startTimeNanos)
370-
.setTimeUnixNano(getTimeUnixNano())
371-
.setSum(total)
372-
.setCount(count);
373-
for (ValueAtPercentile percentile : histogramSnapshot.percentileValues()) {
374-
summaryData.addQuantileValues(SummaryDataPoint.ValueAtQuantile.newBuilder()
375-
.setQuantile(percentile.percentile())
376-
.setValue(TimeUtils.convert(percentile.value(), TimeUnit.NANOSECONDS, getBaseTimeUnit())));
377-
}
378-
metricBuilder.setSummary(Summary.newBuilder().addDataPoints(summaryData));
379-
return metricBuilder.build();
380-
}
381-
382-
ExponentialHistogramSnapShot exponentialHistogramSnapShot = getExponentialHistogramSnapShot(histogramSupport);
383-
if (exponentialHistogramSnapShot != null) {
384-
ExponentialHistogramDataPoint.Builder exponentialDataPoint = ExponentialHistogramDataPoint.newBuilder()
385-
.addAllAttributes(tags)
386-
.setStartTimeUnixNano(startTimeNanos)
387-
.setTimeUnixNano(getTimeUnixNano())
388-
.setCount(count)
389-
.setSum(total)
390-
.setScale(exponentialHistogramSnapShot.scale())
391-
.setZeroCount(exponentialHistogramSnapShot.zeroCount())
392-
.setZeroThreshold(exponentialHistogramSnapShot.zeroThreshold())
393-
.setPositive(ExponentialHistogramDataPoint.Buckets.newBuilder()
394-
.addAllBucketCounts(exponentialHistogramSnapShot.bucketsCount())
395-
.setOffset(exponentialHistogramSnapShot.offset())
396-
.build())
397-
// Micrometer doesn't support negative recordings.
398-
.setNegative(EMPTY_EXPONETIAL_HISTOGRAM_BUCKETS);
399-
400-
if (isDelta()) {
401-
exponentialDataPoint
402-
.setMax(isTimeBased ? histogramSnapshot.max(getBaseTimeUnit()) : histogramSnapshot.max());
403-
}
404-
405-
return metricBuilder
406-
.setExponentialHistogram(ExponentialHistogram.newBuilder()
407-
.setAggregationTemporality(otlpAggregationTemporality)
408-
.addDataPoints(exponentialDataPoint)
409-
.build())
410-
.build();
411-
}
412-
413-
HistogramDataPoint.Builder histogramDataPoint = HistogramDataPoint.newBuilder()
414-
.addAllAttributes(tags)
415-
.setStartTimeUnixNano(startTimeNanos)
416-
.setTimeUnixNano(getTimeUnixNano())
417-
.setSum(total)
418-
.setCount(count);
419-
420-
if (isDelta()) {
421-
histogramDataPoint.setMax(isTimeBased ? histogramSnapshot.max(getBaseTimeUnit()) : histogramSnapshot.max());
422-
}
423-
// if histogram enabled, add histogram buckets
424-
if (histogramSnapshot.histogramCounts().length != 0) {
425-
for (CountAtBucket countAtBucket : histogramSnapshot.histogramCounts()) {
426-
if (countAtBucket.bucket() != Double.POSITIVE_INFINITY) {
427-
// OTLP expects explicit bounds to not contain POSITIVE_INFINITY but
428-
// there should be a
429-
// bucket count representing values between last bucket and
430-
// POSITIVE_INFINITY.
431-
histogramDataPoint.addExplicitBounds(
432-
isTimeBased ? countAtBucket.bucket(getBaseTimeUnit()) : countAtBucket.bucket());
433-
}
434-
histogramDataPoint.addBucketCounts((long) countAtBucket.count());
435-
}
436-
metricBuilder.setHistogram(io.opentelemetry.proto.metrics.v1.Histogram.newBuilder()
437-
.setAggregationTemporality(otlpAggregationTemporality)
438-
.addDataPoints(histogramDataPoint));
439-
return metricBuilder.build();
440-
}
441-
442-
return metricBuilder
443-
.setHistogram(io.opentelemetry.proto.metrics.v1.Histogram.newBuilder()
444-
.setAggregationTemporality(otlpAggregationTemporality)
445-
.addDataPoints(histogramDataPoint))
446-
.build();
447-
}
448-
449-
@Nullable
450-
private static ExponentialHistogramSnapShot getExponentialHistogramSnapShot(
451-
final HistogramSupport histogramSupport) {
452-
if (histogramSupport instanceof OtlpHistogramSupport) {
453-
return ((OtlpHistogramSupport) histogramSupport).getExponentialHistogramSnapShot();
454-
}
455-
456-
return null;
457-
}
458-
459-
// VisibleForTesting
460-
Metric writeFunctionTimer(FunctionTimer functionTimer) {
461-
return getMetricBuilder(functionTimer.getId())
462-
.setHistogram(io.opentelemetry.proto.metrics.v1.Histogram.newBuilder()
463-
.addDataPoints(HistogramDataPoint.newBuilder()
464-
.addAllAttributes(getTagsForId(functionTimer.getId()))
465-
.setStartTimeUnixNano(getStartTimeNanos((functionTimer)))
466-
.setTimeUnixNano(getTimeUnixNano())
467-
.setSum(functionTimer.totalTime(getBaseTimeUnit()))
468-
.setCount((long) functionTimer.count()))
469-
.setAggregationTemporality(otlpAggregationTemporality))
470-
.build();
471-
}
472-
473348
private boolean isCumulative() {
474349
return this.aggregationTemporality == AggregationTemporality.CUMULATIVE;
475350
}
@@ -516,14 +391,15 @@ static Histogram getHistogram(Clock clock, DistributionStatisticConfig distribut
516391

517392
static Histogram getHistogram(final Clock clock, final DistributionStatisticConfig distributionStatisticConfig,
518393
final OtlpConfig otlpConfig, @Nullable final TimeUnit baseTimeUnit) {
519-
// While publishing to OTLP, we export either Histogram datapoint (Explicit Bucket
394+
// While publishing to OTLP, we export either Histogram datapoint (Explicit
395+
// ExponentialBucket
520396
// or Exponential) / Summary
521397
// datapoint. So, we will make the histogram either of them and not both.
522398
// Though AbstractTimer/Distribution Summary prefers publishing percentiles,
523399
// exporting of histograms over percentiles is preferred in OTLP.
524400
if (distributionStatisticConfig.isPublishingHistogram()) {
525-
if (histogramFlavour(otlpConfig.histogramFlavour(),
526-
distributionStatisticConfig) == HistogramFlavour.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM) {
401+
if (HistogramFlavour.BASE2_EXPONENTIAL_BUCKET_HISTOGRAM
402+
.equals(histogramFlavour(otlpConfig.histogramFlavour(), distributionStatisticConfig))) {
527403
Double minimumExpectedValue = distributionStatisticConfig.getMinimumExpectedValueAsDouble();
528404
if (minimumExpectedValue == null) {
529405
minimumExpectedValue = 0.0;

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

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.micrometer.core.instrument.distribution.HistogramSupport;
2525
import io.micrometer.core.instrument.distribution.ValueAtPercentile;
2626
import io.micrometer.core.instrument.util.TimeUtils;
27+
import io.micrometer.registry.otlp.internal.ExponentialHistogramSnapShot;
2728
import io.opentelemetry.proto.common.v1.AnyValue;
2829
import io.opentelemetry.proto.common.v1.KeyValue;
2930
import io.opentelemetry.proto.metrics.v1.*;
@@ -40,6 +41,11 @@
4041
*/
4142
class OtlpMetricConverter {
4243

44+
private static final ExponentialHistogramDataPoint.Buckets EMPTY_EXPONETIAL_HISTOGRAM_BUCKETS = ExponentialHistogramDataPoint.Buckets
45+
.newBuilder()
46+
.addAllBucketCounts(Collections.emptyList())
47+
.build();
48+
4349
private final Clock clock;
4450

4551
private final Duration step;
@@ -122,16 +128,35 @@ private void writeHistogramSupport(HistogramSupport histogramSupport) {
122128
Iterable<KeyValue> tags = getKeyValuesForId(id);
123129
long startTimeNanos = getStartTimeNanos(histogramSupport);
124130
double total = isTimeBased ? histogramSnapshot.total(baseTimeUnit) : histogramSnapshot.total();
131+
double max = isTimeBased ? histogramSnapshot.max(baseTimeUnit) : histogramSnapshot.max();
125132
long count = histogramSnapshot.count();
126133

127134
// if percentiles configured, use summary
128135
if (histogramSnapshot.percentileValues().length != 0) {
129136
buildSummaryDataPoint(histogramSupport, tags, startTimeNanos, total, count, isTimeBased, histogramSnapshot);
137+
return;
138+
}
139+
140+
Optional<ExponentialHistogramSnapShot> exponentialHistogramSnapShot = getExponentialHistogramSnapShot(
141+
histogramSupport);
142+
if (exponentialHistogramSnapShot.isPresent()) {
143+
buildExponentialHistogramDataPoint(histogramSupport, tags, startTimeNanos, total, max, count,
144+
exponentialHistogramSnapShot.get());
130145
}
131146
else {
132-
buildHistogramDataPoint(histogramSupport, tags, startTimeNanos, total, count, isTimeBased,
147+
buildHistogramDataPoint(histogramSupport, tags, startTimeNanos, total, max, count, isTimeBased,
133148
histogramSnapshot);
134149
}
150+
151+
}
152+
153+
private static Optional<ExponentialHistogramSnapShot> getExponentialHistogramSnapShot(
154+
final HistogramSupport histogramSupport) {
155+
if (histogramSupport instanceof OtlpHistogramSupport) {
156+
return Optional.ofNullable(((OtlpHistogramSupport) histogramSupport).getExponentialHistogramSnapShot());
157+
}
158+
159+
return Optional.empty();
135160
}
136161

137162
private void writeFunctionTimer(FunctionTimer functionTimer) {
@@ -151,7 +176,8 @@ private boolean isTimeBasedMeter(Meter.Id id) {
151176
}
152177

153178
private void buildHistogramDataPoint(HistogramSupport histogramSupport, Iterable<KeyValue> tags,
154-
long startTimeNanos, double total, long count, boolean isTimeBased, HistogramSnapshot histogramSnapshot) {
179+
long startTimeNanos, double total, double max, long count, boolean isTimeBased,
180+
HistogramSnapshot histogramSnapshot) {
155181
Metric.Builder metricBuilder = getOrCreateMetricBuilder(histogramSupport.getId(), DataCase.HISTOGRAM);
156182
HistogramDataPoint.Builder histogramDataPoint = HistogramDataPoint.newBuilder()
157183
.addAllAttributes(tags)
@@ -161,7 +187,7 @@ private void buildHistogramDataPoint(HistogramSupport histogramSupport, Iterable
161187
.setCount(count);
162188

163189
if (isDelta()) {
164-
histogramDataPoint.setMax(isTimeBased ? histogramSnapshot.max(baseTimeUnit) : histogramSnapshot.max());
190+
histogramDataPoint.setMax(max);
165191
}
166192

167193
// if histogram enabled, add histogram buckets
@@ -180,6 +206,37 @@ private void buildHistogramDataPoint(HistogramSupport histogramSupport, Iterable
180206
setHistogramDataPoint(metricBuilder, histogramDataPoint.build());
181207
}
182208

209+
private void buildExponentialHistogramDataPoint(HistogramSupport histogramSupport, Iterable<KeyValue> tags,
210+
long startTimeNanos, double total, double max, long count,
211+
ExponentialHistogramSnapShot exponentialHistogramSnapShot) {
212+
Metric.Builder metricBuilder = getOrCreateMetricBuilder(histogramSupport.getId(),
213+
DataCase.EXPONENTIAL_HISTOGRAM);
214+
ExponentialHistogramDataPoint.Builder exponentialDataPoint = ExponentialHistogramDataPoint.newBuilder()
215+
.addAllAttributes(tags)
216+
.setStartTimeUnixNano(startTimeNanos)
217+
.setTimeUnixNano(getTimeUnixNano())
218+
.setCount(count)
219+
.setSum(total)
220+
.setScale(exponentialHistogramSnapShot.scale())
221+
.setZeroCount(exponentialHistogramSnapShot.zeroCount())
222+
.setZeroThreshold(exponentialHistogramSnapShot.zeroThreshold());
223+
224+
// Currently, micrometer doesn't support negative recordings hence we will only
225+
// add positive buckets.
226+
if (!exponentialHistogramSnapShot.positive().isEmpty()) {
227+
exponentialDataPoint.setPositive(ExponentialHistogramDataPoint.Buckets.newBuilder()
228+
.addAllBucketCounts(exponentialHistogramSnapShot.positive().bucketCounts())
229+
.setOffset(exponentialHistogramSnapShot.positive().offset())
230+
.build());
231+
}
232+
233+
if (isDelta()) {
234+
exponentialDataPoint.setMax(max);
235+
}
236+
237+
setExponentialHistogramDataPoint(metricBuilder, exponentialDataPoint.build());
238+
}
239+
183240
private void buildSummaryDataPoint(HistogramSupport histogramSupport, Iterable<KeyValue> tags, long startTimeNanos,
184241
double total, long count, boolean isTimeBased, HistogramSnapshot histogramSnapshot) {
185242
Metric.Builder metricBuilder = getOrCreateMetricBuilder(histogramSupport.getId(), DataCase.SUMMARY);
@@ -220,6 +277,15 @@ private void setHistogramDataPoint(Metric.Builder builder, HistogramDataPoint hi
220277
builder.getHistogramBuilder().addDataPoints(histogramDataPoint);
221278
}
222279

280+
private void setExponentialHistogramDataPoint(Metric.Builder builder,
281+
ExponentialHistogramDataPoint exponentialHistogramDataPoint) {
282+
if (!builder.hasExponentialHistogram()) {
283+
builder.setExponentialHistogram(
284+
ExponentialHistogram.newBuilder().setAggregationTemporality(otlpAggregationTemporality));
285+
}
286+
builder.getExponentialHistogramBuilder().addDataPoints(exponentialHistogramDataPoint);
287+
}
288+
223289
private void setSummaryDataPoint(Metric.Builder builder, SummaryDataPoint.Builder summaryDataPoint) {
224290
if (!builder.hasSummary()) {
225291
builder.setSummary(Summary.newBuilder());

implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/internal/Base2ExponentialHistogram.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package io.micrometer.registry.otlp.internal;
1717

18+
import static io.micrometer.registry.otlp.internal.ExponentialHistogramSnapShot.ExponentialBucket.EMPTY_EXPONENTIAL_BUCKET;
19+
1820
import java.util.Arrays;
1921
import java.util.Collections;
2022
import java.util.List;
@@ -26,17 +28,24 @@
2628
import io.micrometer.core.instrument.distribution.Histogram;
2729
import io.micrometer.core.instrument.distribution.HistogramSnapshot;
2830
import io.micrometer.core.instrument.util.TimeUtils;
31+
import io.micrometer.registry.otlp.internal.ExponentialHistogramSnapShot.ExponentialBucket;
2932

3033
/**
3134
* A ExponentialHistogram implementation that compresses bucket boundaries using an
3235
* exponential formula (Base2 exponent), making it suitable for conveying high dynamic
3336
* range data with small relative error. This is an implementation of the <a href=
3437
* "https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/data-model.md#exponentialhistogram">Exponential
3538
* Histogram</a> as per the OTLP specification. The internal implementations uses the
36-
* techniques outlined in the OTLP specification mentioned above.
39+
* techniques outlined in the OTLP specification mentioned above. This implementation
40+
* supports only recording positive values (enforced by
41+
* {@link io.micrometer.core.instrument.AbstractTimer#record(long, TimeUnit)}).
42+
* <p>
43+
* <strong> This is an internal class and might have breaking changes, external
44+
* implementations SHOULD NOT rely on this implementation. </strong>
45+
* </p>
3746
*
3847
* @author Lenin Jaganathan
39-
* @since 1.12.0
48+
* @since 1.14.0
4049
*/
4150
public abstract class Base2ExponentialHistogram implements Histogram {
4251

@@ -115,8 +124,8 @@ public HistogramSnapshot takeSnapshot(final long count, final double total, fina
115124
ExponentialHistogramSnapShot getCurrentValuesSnapshot() {
116125
return (circularCountHolder.isEmpty() && zeroCount.longValue() == 0)
117126
? DefaultExponentialHistogramSnapShot.getEmptySnapshotForScale(scale)
118-
: new DefaultExponentialHistogramSnapShot(scale, getOffset(), zeroCount.longValue(), zeroThreshold,
119-
getBucketCounts());
127+
: new DefaultExponentialHistogramSnapShot(scale, zeroCount.longValue(), zeroThreshold,
128+
new ExponentialBucket(getOffset(), getBucketCounts()), EMPTY_EXPONENTIAL_BUCKET);
120129
}
121130

122131
/**

implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/internal/CumulativeBase2ExponentialHistogram.java

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

2222
/**
2323
* A {@link Base2ExponentialHistogram} that tracks values cumulatively from first recorded
24-
* value.
24+
* value. *
25+
* <p>
26+
* * <strong> This is an internal class and might have breaking changes, external *
27+
* implementations SHOULD NOT rely on this implementation. </strong> *
28+
* </p>
2529
*
2630
* @author Lenin Jaganathan
27-
* @since 1.12.0
31+
* @since 1.14.0
2832
*/
2933
public class CumulativeBase2ExponentialHistogram extends Base2ExponentialHistogram {
3034

0 commit comments

Comments
 (0)