Skip to content

Commit

Permalink
Merge branch '1.11.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
shakuzen committed Jul 6, 2023
2 parents 0841345 + f4f02ee commit a83c2c2
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
Expand Down Expand Up @@ -72,6 +73,8 @@ public class OtlpMeterRegistry extends PushMeterRegistry {

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

private static final double[] EMPTY_SLO_WITH_POSITIVE_INF = new double[] { Double.POSITIVE_INFINITY };

private final InternalLogger logger = InternalLoggerFactory.getInstance(OtlpMeterRegistry.class);

private final OtlpConfig config;
Expand Down Expand Up @@ -389,8 +392,14 @@ Metric writeHistogramSupport(HistogramSupport histogramSupport) {
// if histogram enabled, add histogram buckets
if (histogramSnapshot.histogramCounts().length != 0) {
for (CountAtBucket countAtBucket : histogramSnapshot.histogramCounts()) {
histogramDataPoint
.addExplicitBounds(isTimeBased ? countAtBucket.bucket(getBaseTimeUnit()) : countAtBucket.bucket());
if (countAtBucket.bucket() != Double.POSITIVE_INFINITY) {
// OTLP expects explicit bounds to not contain POSITIVE_INFINITY but
// there should be a
// bucket count representing values between last bucket and
// POSITIVE_INFINITY.
histogramDataPoint.addExplicitBounds(
isTimeBased ? countAtBucket.bucket(getBaseTimeUnit()) : countAtBucket.bucket());
}
histogramDataPoint.addBucketCounts((long) countAtBucket.count());
}
metricBuilder.setHistogram(io.opentelemetry.proto.metrics.v1.Histogram.newBuilder()
Expand Down Expand Up @@ -499,17 +508,24 @@ static Histogram getHistogram(Clock clock, DistributionStatisticConfig distribut
// Though AbstractTimer/Distribution Summary prefers publishing percentiles,
// exporting of histograms over percentiles is preferred in OTLP.
if (distributionStatisticConfig.isPublishingHistogram()) {
double[] sloWithPositiveInf = getSloWithPositiveInf(distributionStatisticConfig);
if (AggregationTemporality.isCumulative(aggregationTemporality)) {
return new TimeWindowFixedBoundaryHistogram(clock, DistributionStatisticConfig.builder()
// effectively never roll over
.expiry(Duration.ofDays(1825))
.serviceLevelObjectives(sloWithPositiveInf)
.percentiles()
.bufferLength(1)
.build()
.merge(distributionStatisticConfig), true, false);
}
if (AggregationTemporality.isDelta(aggregationTemporality) && stepMillis > 0) {
return new OtlpStepBucketHistogram(clock, stepMillis, distributionStatisticConfig, true, false);
return new OtlpStepBucketHistogram(clock, stepMillis,
DistributionStatisticConfig.builder()
.serviceLevelObjectives(sloWithPositiveInf)
.build()
.merge(distributionStatisticConfig),
true, false);
}
}

Expand All @@ -519,4 +535,25 @@ static Histogram getHistogram(Clock clock, DistributionStatisticConfig distribut
return NoopHistogram.INSTANCE;
}

// VisibleForTesting
static double[] getSloWithPositiveInf(DistributionStatisticConfig distributionStatisticConfig) {
double[] sloBoundaries = distributionStatisticConfig.getServiceLevelObjectiveBoundaries();
if (sloBoundaries == null || sloBoundaries.length == 0) {
// When there are no SLO's associated with DistributionStatisticConfig we will
// add one with Positive
// Infinity. This will make sure we always have POSITIVE_INFINITY, and the
// NavigableSet will make sure
// duplicates if any will be ignored.
return EMPTY_SLO_WITH_POSITIVE_INF;
}

boolean containsPositiveInf = Arrays.stream(sloBoundaries).anyMatch(value -> value == Double.POSITIVE_INFINITY);
if (containsPositiveInf)
return sloBoundaries;

double[] sloWithPositiveInf = Arrays.copyOf(sloBoundaries, sloBoundaries.length + 1);
sloWithPositiveInf[sloWithPositiveInf.length - 1] = Double.POSITIVE_INFINITY;
return sloWithPositiveInf;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,14 @@ void timerWithHistogram() {
timer.record(10, TimeUnit.MILLISECONDS);
timer.record(77, TimeUnit.MILLISECONDS);
timer.record(111, TimeUnit.MILLISECONDS);
timer.record(1, TimeUnit.MINUTES);
clock.add(otlpConfig().step());
timer.record(4, TimeUnit.MILLISECONDS);

assertThat(writeToMetric(timer).toString())
.isEqualTo("name: \"http.client.requests\"\n" + "unit: \"milliseconds\"\n" + "histogram {\n"
+ " data_points {\n" + " start_time_unix_nano: 1000000\n" + " time_unix_nano: 60001000000\n"
+ " count: 4\n" + " sum: 202.0\n" + " bucket_counts: 0\n" + " bucket_counts: 0\n"
+ " count: 5\n" + " sum: 60202.0\n" + " bucket_counts: 0\n" + " bucket_counts: 0\n"
+ " bucket_counts: 0\n" + " bucket_counts: 0\n" + " bucket_counts: 0\n"
+ " bucket_counts: 0\n" + " bucket_counts: 0\n" + " bucket_counts: 0\n"
+ " bucket_counts: 0\n" + " bucket_counts: 0\n" + " bucket_counts: 1\n"
Expand All @@ -133,7 +134,7 @@ void timerWithHistogram() {
+ " bucket_counts: 0\n" + " bucket_counts: 0\n" + " bucket_counts: 0\n"
+ " bucket_counts: 0\n" + " bucket_counts: 0\n" + " bucket_counts: 0\n"
+ " bucket_counts: 0\n" + " bucket_counts: 0\n" + " bucket_counts: 0\n"
+ " explicit_bounds: 1.0\n" + " explicit_bounds: 1.048576\n"
+ " bucket_counts: 1\n" + " explicit_bounds: 1.0\n" + " explicit_bounds: 1.048576\n"
+ " explicit_bounds: 1.398101\n" + " explicit_bounds: 1.747626\n"
+ " explicit_bounds: 2.097151\n" + " explicit_bounds: 2.446676\n"
+ " explicit_bounds: 2.796201\n" + " explicit_bounds: 3.145726\n"
Expand Down Expand Up @@ -448,8 +449,7 @@ void distributionSummaryWithHistogramBuckets() {
+ " explicit_bounds: 2.305843009213694E18\n" + " explicit_bounds: 2.6901501774159764E18\n"
+ " explicit_bounds: 3.0744573456182584E18\n" + " explicit_bounds: 3.4587645138205409E18\n"
+ " explicit_bounds: 3.8430716820228234E18\n" + " explicit_bounds: 4.2273788502251054E18\n"
+ " explicit_bounds: Infinity\n" + " }\n"
+ " aggregation_temporality: AGGREGATION_TEMPORALITY_CUMULATIVE\n" + "}\n";
+ " }\n" + " aggregation_temporality: AGGREGATION_TEMPORALITY_CUMULATIVE\n" + "}\n";
String[] expectedLines = expected.split("\n");
String actual = writeToMetric(size).toString();
String[] actualLines = actual.split("\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package io.micrometer.registry.otlp;

import io.micrometer.core.instrument.*;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
import io.opentelemetry.proto.metrics.v1.HistogramDataPoint;
import io.opentelemetry.proto.metrics.v1.Metric;
import io.opentelemetry.proto.metrics.v1.NumberDataPoint;
Expand Down Expand Up @@ -161,6 +162,30 @@ void distributionWithHistogramShouldWriteHistogramDataPoint() {
assertThat(writeToMetric(ds).getDataCase().getNumber()).isEqualTo(Metric.DataCase.HISTOGRAM.getNumber());
}

@Test
void testGetSloWithPositiveInf() {
DistributionStatisticConfig distributionStatisticConfig = DistributionStatisticConfig.builder()
.percentilesHistogram(true)
.build();

assertThat(OtlpMeterRegistry.getSloWithPositiveInf(distributionStatisticConfig))
.containsExactly(Double.POSITIVE_INFINITY);

DistributionStatisticConfig distributionStatisticConfigWithSlo = DistributionStatisticConfig.builder()
.serviceLevelObjectives(1, 10, 100)
.build();
assertThat(OtlpMeterRegistry.getSloWithPositiveInf(distributionStatisticConfigWithSlo))
.contains(Double.POSITIVE_INFINITY);
assertThat(OtlpMeterRegistry.getSloWithPositiveInf(distributionStatisticConfigWithSlo)).hasSize(4);

DistributionStatisticConfig distributionStatisticConfigWithInf = DistributionStatisticConfig.builder()
.serviceLevelObjectives(1, 10, 100, Double.POSITIVE_INFINITY)
.build();
assertThat(OtlpMeterRegistry.getSloWithPositiveInf(distributionStatisticConfigWithInf))
.contains(Double.POSITIVE_INFINITY);
assertThat(OtlpMeterRegistry.getSloWithPositiveInf(distributionStatisticConfigWithInf)).hasSize(4);
}

@Test
abstract void testMetricsStartAndEndTime();

Expand All @@ -177,6 +202,9 @@ protected void stepOverNStep(int numStepsToSkip) {

protected void assertHistogram(Metric metric, long startTime, long endTime, String unit, long count, double sum,
double max) {
assertThat(metric.getHistogram().getAggregationTemporality())
.isEqualTo(AggregationTemporality.toOtlpAggregationTemporality(otlpConfig().aggregationTemporality()));

HistogramDataPoint histogram = metric.getHistogram().getDataPoints(0);
assertThat(metric.getName()).isEqualTo(METER_NAME);
assertThat(metric.getDescription()).isEqualTo(METER_DESCRIPTION);
Expand All @@ -185,12 +213,19 @@ protected void assertHistogram(Metric metric, long startTime, long endTime, Stri
assertThat(histogram.getTimeUnixNano()).isEqualTo(endTime);
assertThat(histogram.getCount()).isEqualTo(count);
assertThat(histogram.getSum()).isEqualTo(sum);
assertThat(histogram.getMax()).isEqualTo(max);

assertThat(histogram.getAttributesCount()).isEqualTo(1);
assertThat(histogram.getAttributes(0).getKey()).isEqualTo(meterTag.getKey());
assertThat(histogram.getAttributes(0).getValue().getStringValue()).isEqualTo(meterTag.getValue());
assertThat(metric.getHistogram().getAggregationTemporality())
.isEqualTo(AggregationTemporality.toOtlpAggregationTemporality(otlpConfig().aggregationTemporality()));

if (histogram.getExplicitBoundsCount() > 0) {
assertThat(histogram.getBucketCountsList().stream().mapToLong(Long::longValue).sum()).isEqualTo(count);
assertThat(histogram.getExplicitBoundsCount() + 1).isEqualTo(histogram.getBucketCountsCount());
}

if (otlpConfig().aggregationTemporality() == AggregationTemporality.DELTA) {
assertThat(histogram.getMax()).isEqualTo(max);
}
}

protected void assertSum(Metric metric, long startTime, long endTime, double expectedValue) {
Expand Down

0 comments on commit a83c2c2

Please sign in to comment.