Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,20 @@ OtlpDataPoint doCollect(boolean reset) {
List<Double> binBoundaries;
List<Double> binCounts;
double sum;
double min;
double max;
synchronized (histogram) {
count = histogram.getCount();
binBoundaries = histogram.getBinBoundaries();
binCounts = histogram.getBinCounts();
sum = histogram.getSum();
min = histogram.getMinValue();
max = histogram.getMaxValue();
if (reset) {
histogram.clear();
}
}
return new OtlpHistogramPoint(count, binBoundaries, binCounts, sum);
return new OtlpHistogramPoint(count, binBoundaries, binCounts, sum, min, max);
}

/** Truncate IEEE-754 floating-point value to 10 bits precision. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@ public final class OtlpHistogramPoint extends OtlpDataPoint {
public final List<Double> bucketBoundaries;
public final List<Double> bucketCounts;
public final double sum;
public final double min;
public final double max;

OtlpHistogramPoint(
double count, List<Double> bucketBoundaries, List<Double> bucketCounts, double sum) {
double count,
List<Double> bucketBoundaries,
List<Double> bucketCounts,
double sum,
double min,
double max) {
this.count = count;
this.bucketBoundaries = bucketBoundaries;
this.bucketCounts = bucketCounts;
this.sum = sum;
this.min = min;
this.max = max;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ public static byte[] recordDataPointMessage(GrowableBuffer buf, OtlpDataPoint po
writeI64(buf, (long) histogram.count);
writeTag(buf, 5, I64_WIRE_TYPE);
writeI64(buf, histogram.sum);
writeTag(buf, 11, I64_WIRE_TYPE);
writeI64(buf, histogram.min);
writeTag(buf, 12, I64_WIRE_TYPE);
writeI64(buf, histogram.max);
for (double bucketCount : histogram.bucketCounts) {
writeTag(buf, 6, I64_WIRE_TYPE);
writeI64(buf, (long) bucketCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ public static OtlpDoublePoint doublePoint(double value) {
}

public static OtlpHistogramPoint histogramPoint(
double count, List<Double> bucketBoundaries, List<Double> bucketCounts, double sum) {
return new OtlpHistogramPoint(count, bucketBoundaries, bucketCounts, sum);
double count,
List<Double> bucketBoundaries,
List<Double> bucketCounts,
double sum,
double min,
double max) {
return new OtlpHistogramPoint(count, bucketBoundaries, bucketCounts, sum, min, max);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
* double as_double = 4; sfixed64 as_int = 6; KeyValue attributes = 7; }
* HistogramDataPoint { fixed64 start_time_unix_nano = 2; fixed64 time_unix_nano = 3;
* fixed64 count = 4; double sum = 5; fixed64 bucket_counts = 6;
* double explicit_bounds = 7; KeyValue attributes = 9; }
* double explicit_bounds = 7; KeyValue attributes = 9;
* double min = 11; double max = 12; }
* </pre>
*/
class OtlpMetricsProtoTest {
Expand Down Expand Up @@ -242,14 +243,16 @@ private static MetricSpec histogram(
List<Double> bounds,
List<Double> counts,
double sum,
double min,
double max,
AttrSpec... attrs) {
return new MetricSpec(
name,
null,
null,
OtelInstrumentType.HISTOGRAM,
false,
histogramPoint(count, bounds, counts, sum),
histogramPoint(count, bounds, counts, sum, min, max),
asList(attrs));
}

Expand Down Expand Up @@ -358,20 +361,32 @@ static Stream<Arguments> cases() {
Arguments.of(
"histogram no buckets",
asList(
scope("io.hist", histogram("response.time", 1.0, emptyList(), asList(1.0), 0.5)))),
scope(
"io.hist",
histogram("response.time", 1.0, emptyList(), asList(1.0), 0.5, 0.5, 0.5)))),

// ── histogram — zero count and sum ────────────────────────────────────
Arguments.of(
"histogram zero count and sum",
asList(scope("io.hist", histogram("idle.time", 0.0, emptyList(), asList(0.0), 0.0)))),
asList(
scope(
"io.hist",
histogram("idle.time", 0.0, emptyList(), asList(0.0), 0.0, 0.0, 0.0)))),

// ── histogram — single explicit bound ─────────────────────────────────
Arguments.of(
"histogram single bound",
asList(
scope(
"io.hist",
histogram("request.size", 5.0, asList(100.0), asList(4.0, 1.0), 280.0)))),
histogram(
"request.size",
5.0,
asList(100.0),
asList(4.0, 1.0),
280.0,
20.0,
200.0)))),

// ── histogram — with explicit bounds and attrs ────────────────────────
Arguments.of(
Expand All @@ -385,6 +400,8 @@ static Stream<Arguments> cases() {
asList(1.0, 5.0, 10.0),
asList(2.0, 3.0, 4.0, 1.0),
45.5,
0.5,
12.0,
strAttr("region", "us-east"))))),

// ── histogram — many buckets with multiple attrs ───────────────────────
Expand All @@ -399,6 +416,8 @@ static Stream<Arguments> cases() {
asList(1.0, 2.0, 5.0, 10.0, 25.0, 50.0, 100.0),
asList(5.0, 10.0, 20.0, 30.0, 15.0, 12.0, 6.0, 2.0),
4321.0,
0.5,
150.0,
longAttr("shard", 3L),
boolAttr("cached", false))))),

Expand Down Expand Up @@ -886,12 +905,13 @@ private static void verifyNumberDataPoint(
}

/**
* Parses a {@code HistogramDataPoint} message body and asserts timestamps, count, sum, bucket
* counts, explicit bounds, and attributes.
* Parses a {@code HistogramDataPoint} message body and asserts timestamps, count, sum, min, max,
* bucket counts, explicit bounds, and attributes.
*
* <pre>
* HistogramDataPoint { start_time_unix_nano=2, time_unix_nano=3, count=4,
* sum=5, bucket_counts=6, explicit_bounds=7, attributes=9 }
* sum=5, bucket_counts=6, explicit_bounds=7, attributes=9,
* min=11, max=12 }
* </pre>
*/
private static void verifyHistogramDataPoint(CodedInputStream dp, MetricSpec expected)
Expand All @@ -901,6 +921,8 @@ private static void verifyHistogramDataPoint(CodedInputStream dp, MetricSpec exp
boolean foundEndTime = false;
boolean foundCount = false;
boolean foundSum = false;
boolean foundMin = false;
boolean foundMax = false;
List<Long> parsedBucketCounts = new ArrayList<>();
List<Double> parsedBounds = new ArrayList<>();
List<String> parsedAttrKeys = new ArrayList<>();
Expand Down Expand Up @@ -937,6 +959,20 @@ private static void verifyHistogramDataPoint(CodedInputStream dp, MetricSpec exp
case 9: // attributes (repeated KeyValue)
parsedAttrKeys.add(readKeyValueKey(dp.readBytes().newCodedInput()));
break;
case 11: // min (double via fixed64)
assertEquals(
Double.doubleToRawLongBits(hp.min),
Double.doubleToRawLongBits(dp.readDouble()),
"histogram min");
foundMin = true;
break;
case 12: // max (double via fixed64)
assertEquals(
Double.doubleToRawLongBits(hp.max),
Double.doubleToRawLongBits(dp.readDouble()),
"histogram max");
foundMax = true;
break;
default:
dp.skipField(tag);
}
Expand All @@ -946,6 +982,8 @@ private static void verifyHistogramDataPoint(CodedInputStream dp, MetricSpec exp
assertTrue(foundEndTime, "time_unix_nano required for histogram " + expected.name);
assertTrue(foundCount, "count required for histogram " + expected.name);
assertTrue(foundSum, "sum required for histogram " + expected.name);
assertTrue(foundMin, "min required for histogram " + expected.name);
assertTrue(foundMax, "max required for histogram " + expected.name);

assertEquals(
hp.bucketCounts.size(),
Expand Down
Loading