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 @@ -25,6 +25,8 @@
import io.opentelemetry.proto.metrics.v1.ResourceMetrics;
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
import io.opentelemetry.sdk.metrics.data.DoubleGaugeData;
import io.opentelemetry.sdk.metrics.data.DoubleHistogramData;
import io.opentelemetry.sdk.metrics.data.DoubleHistogramPointData;
import io.opentelemetry.sdk.metrics.data.DoublePointData;
import io.opentelemetry.sdk.metrics.data.DoubleSumData;
import io.opentelemetry.sdk.metrics.data.DoubleSummaryData;
Expand Down Expand Up @@ -150,7 +152,13 @@ static Metric toProtoMetric(MetricData metricData) {
.build());
break;
case HISTOGRAM:
// no-op, will add in the following PRs
DoubleHistogramData doubleHistogramData = metricData.getDoubleHistogramData();
builder.setDoubleHistogram(
DoubleHistogram.newBuilder()
.setAggregationTemporality(
mapToTemporality(doubleHistogramData.getAggregationTemporality()))
.addAllDataPoints(toDoubleHistogramDataPoints(doubleHistogramData.getPoints()))
.build());
break;
}
return builder.build();
Expand Down Expand Up @@ -225,6 +233,30 @@ static List<DoubleHistogramDataPoint> toSummaryDataPoints(
return result;
}

static Collection<DoubleHistogramDataPoint> toDoubleHistogramDataPoints(
Collection<DoubleHistogramPointData> points) {
List<DoubleHistogramDataPoint> result = new ArrayList<>(points.size());
for (DoubleHistogramPointData doubleHistogramPoint : points) {
DoubleHistogramDataPoint.Builder builder =
DoubleHistogramDataPoint.newBuilder()
.setStartTimeUnixNano(doubleHistogramPoint.getStartEpochNanos())
.setTimeUnixNano(doubleHistogramPoint.getEpochNanos())
.setCount(doubleHistogramPoint.getCount())
.setSum(doubleHistogramPoint.getSum())
.addAllBucketCounts(doubleHistogramPoint.getCounts());
List<Double> boundaries = doubleHistogramPoint.getBoundaries();
if (!boundaries.isEmpty()) {
builder.addAllExplicitBounds(boundaries);
}
Comment on lines +247 to +250

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Counts as well. So we add boundaries and counts if boundaries not empty, otherwise the counts will be a list with one long equivalent with count.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

counts will be a list with one long equivalent with count.

that looks like a valid OTLP histogram point to me according to https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/metrics/v1/metrics.proto#L428.

boundaries and counts both being empty might be a problem to the downstream consumers since it's not in the contract.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is written with the mindset that there will be more options to define the boundaries like linear or exponential

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if I follow. seems to me that the minimal size of buckets should be one according to https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/metrics/v1/metrics.proto#L414

// The number of elements in bucket_counts array must be by one greater than
// the number of elements in explicit_bounds array.

and the service we built treats histogram data points without buckets invalid.

Collection<StringKeyValue> labels = toProtoLabels(doubleHistogramPoint.getLabels());
if (!labels.isEmpty()) {
builder.addAllLabels(labels);
}
result.add(builder.build());
}
return result;
}

// TODO: Consider to pass the Builder and directly add values.
@SuppressWarnings("MixedMutabilityReturnType")
static void addBucketValues(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import io.opentelemetry.sdk.common.InstrumentationLibraryInfo;
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
import io.opentelemetry.sdk.metrics.data.DoubleGaugeData;
import io.opentelemetry.sdk.metrics.data.DoubleHistogramData;
import io.opentelemetry.sdk.metrics.data.DoubleHistogramPointData;
import io.opentelemetry.sdk.metrics.data.DoublePointData;
import io.opentelemetry.sdk.metrics.data.DoubleSumData;
import io.opentelemetry.sdk.metrics.data.DoubleSummaryData;
Expand Down Expand Up @@ -206,6 +208,41 @@ void toSummaryDataPoints() {
.build());
}

@Test
void toHistogramDataPoints() {
assertThat(
MetricAdapter.toDoubleHistogramDataPoints(
ImmutableList.of(
DoubleHistogramPointData.create(
123,
456,
Labels.of("k", "v"),
14.2,
ImmutableList.of(1.0),
ImmutableList.of(1L, 5L)),
DoubleHistogramPointData.create(
123, 456, Labels.empty(), 15.3, ImmutableList.of(), ImmutableList.of(7L)))))
.containsExactly(
DoubleHistogramDataPoint.newBuilder()
.setStartTimeUnixNano(123)
.setTimeUnixNano(456)
.addAllLabels(
singletonList(StringKeyValue.newBuilder().setKey("k").setValue("v").build()))
.setCount(6)
.setSum(14.2)
.addBucketCounts(1)
.addBucketCounts(5)
.addExplicitBounds(1.0)
.build(),
DoubleHistogramDataPoint.newBuilder()
.setStartTimeUnixNano(123)
.setTimeUnixNano(456)
.setCount(7)
.setSum(15.3)
.addBucketCounts(7)
.build());
}

@Test
void toProtoMetric_monotonic() {
assertThat(
Expand Down Expand Up @@ -462,6 +499,52 @@ void toProtoMetric_summary() {
.build());
}

@Test
void toProtoMetric_histogram() {
assertThat(
MetricAdapter.toProtoMetric(
MetricData.createDoubleHistogram(
Resource.empty(),
InstrumentationLibraryInfo.empty(),
"name",
"description",
"1",
DoubleHistogramData.create(
AggregationTemporality.DELTA,
singletonList(
DoubleHistogramPointData.create(
123,
456,
Labels.of("k", "v"),
4.0,
ImmutableList.of(),
ImmutableList.of(33L)))))))
.isEqualTo(
Metric.newBuilder()
.setName("name")
.setDescription("description")
.setUnit("1")
.setDoubleHistogram(
DoubleHistogram.newBuilder()
.setAggregationTemporality(AGGREGATION_TEMPORALITY_DELTA)
.addDataPoints(
DoubleHistogramDataPoint.newBuilder()
.setStartTimeUnixNano(123)
.setTimeUnixNano(456)
.addAllLabels(
singletonList(
StringKeyValue.newBuilder()
.setKey("k")
.setValue("v")
.build()))
.setCount(33)
.setSum(4.0)
.addBucketCounts(33)
.build())
.build())
.build());
}

@Test
void toProtoResourceMetrics() {
Resource resource = Resource.create(Attributes.of(stringKey("ka"), "va"));
Expand Down