diff --git a/opentelemetry/src/main/scala/zio/telemetry/opentelemetry/metrics/internal/Instrument.scala b/opentelemetry/src/main/scala/zio/telemetry/opentelemetry/metrics/internal/Instrument.scala index 8fc0875e..c80aac87 100644 --- a/opentelemetry/src/main/scala/zio/telemetry/opentelemetry/metrics/internal/Instrument.scala +++ b/opentelemetry/src/main/scala/zio/telemetry/opentelemetry/metrics/internal/Instrument.scala @@ -102,7 +102,15 @@ object Instrument { unit.foreach(builder.setUnit) description.foreach(builder.setDescription) - boundaries.foreach(seq => builder.setExplicitBucketBoundariesAdvice(seq.map(Double.box).asJava)) + boundaries.foreach { seq => + builder.setExplicitBucketBoundariesAdvice( + seq + // ZIO uses explicit Double.MaxValue boundary as upper bound. OTEL uses internal "inf" value instead + .filter(_ != Double.MaxValue) + .map(Double.box) + .asJava + ) + } Histogram.double(builder.build(), ctxStorage, logAnnotated) } diff --git a/opentelemetry/src/test/scala/zio/telemetry/opentelemetry/metrics/MeterTest.scala b/opentelemetry/src/test/scala/zio/telemetry/opentelemetry/metrics/MeterTest.scala index 828017f3..e3e2d3e7 100644 --- a/opentelemetry/src/test/scala/zio/telemetry/opentelemetry/metrics/MeterTest.scala +++ b/opentelemetry/src/test/scala/zio/telemetry/opentelemetry/metrics/MeterTest.scala @@ -12,6 +12,7 @@ import zio.telemetry.opentelemetry.metrics.internal.Instrument import zio.telemetry.opentelemetry.tracing.{Tracing, TracingTest} import zio.test.{TestEnvironment, ZIOSpecDefault, _} +import java.time.temporal.ChronoUnit import scala.jdk.CollectionConverters._ object MeterTest extends ZIOSpecDefault { @@ -225,7 +226,7 @@ object MeterTest extends ZIOSpecDefault { private val zioMetricsSpec = suite("ZIO metrics integration")( test("histogram boundaries should be passed to OTEL") { - val histogram = Metric.histogram("test_histogram", Boundaries(Chunk(1, 2, 3))) + val histogram = Metric.histogram("test_histogram", Boundaries.fromChunk(Chunk(1, 2, 3))) for { reader <- ZIO.service[InMemoryMetricReader] @@ -234,6 +235,17 @@ object MeterTest extends ZIOSpecDefault { metricPoint = metric.getHistogramData().getPoints().asScala.toList.head boundaries = metricPoint.getBoundaries.asScala.map(_.toDouble).toSeq } yield assertTrue(boundaries == Seq(1.0, 2.0, 3.0)) + }, + test("timer boundaries should be passed to OTEL") { + val timer = Metric.timer("test_timer", ChronoUnit.SECONDS, Chunk(1.0, 2.0, 3.0)) + + for { + reader <- ZIO.service[InMemoryMetricReader] + _ <- timer.update(Duration.fromSeconds(2)) + metric = reader.collectAllMetrics().asScala.find(_.getName == "test_timer").get + metricPoint = metric.getHistogramData().getPoints().asScala.toList.head + boundaries = metricPoint.getBoundaries.asScala.map(_.toDouble).toSeq + } yield assertTrue(boundaries == Seq(1.0, 2.0, 3.0)) } ).provide(inMemoryMetricReaderLayer, meterLayer(), ContextStorage.fiberRef, OpenTelemetry.zioMetrics)