diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/MetricAdapter.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/MetricAdapter.java index 00217c900a2..da976cc3c36 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/MetricAdapter.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/otlp/internal/MetricAdapter.java @@ -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; @@ -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(); @@ -225,6 +233,30 @@ static List toSummaryDataPoints( return result; } + static Collection toDoubleHistogramDataPoints( + Collection points) { + List 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 boundaries = doubleHistogramPoint.getBoundaries(); + if (!boundaries.isEmpty()) { + builder.addAllExplicitBounds(boundaries); + } + Collection 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( diff --git a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/MetricAdapterTest.java b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/MetricAdapterTest.java index 69fec8485bf..f0156e06558 100644 --- a/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/MetricAdapterTest.java +++ b/exporters/otlp/common/src/test/java/io/opentelemetry/exporter/otlp/internal/MetricAdapterTest.java @@ -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; @@ -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( @@ -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"));