Create metrics from semantic metric specs

Use a generated metric constructor when you are implementing a metric defined by the OpenTelemetry semantic conventions. The constructor applies the canonical metric name, unit, and description.

Prerequisites

1. Add the stable metrics module

libraryDependencies +=
  "org.typelevel" %% "otel4s-semconv-metrics" % "1.1.0"
//> using dep "org.typelevel::otel4s-semconv-metrics:1.1.0"

The stable metric specs are available under org.typelevel.otel4s.semconv.metrics. This artifact also brings in the stable semantic attributes used by those specs.

2. Call the generated constructor

Get a Meter, then call create on the generated metric object. Histogram constructors take explicit bucket boundaries because the appropriate distribution depends on the values produced by your application.

import cats.effect.{IO, IOApp}
import org.typelevel.otel4s.metrics.{BucketBoundaries, Meter}
import org.typelevel.otel4s.oteljava.OtelJava
import org.typelevel.otel4s.semconv.attributes.{HttpAttributes, ServerAttributes}
import org.typelevel.otel4s.semconv.metrics.HttpMetrics

object Main extends IOApp.Simple {
  def run: IO[Unit] =
    OtelJava.autoConfigured[IO]().use { otel4s =>
      otel4s.meterProvider.get("http-client").flatMap { implicit meter =>
        recordRequestDuration(0.125)
      }
    }

  def recordRequestDuration(seconds: Double)(implicit meter: Meter[IO]): IO[Unit] =
    HttpMetrics.ClientRequestDuration
      .create[IO, Double](
        BucketBoundaries(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0)
      )
      .flatMap { duration =>
        duration.record(
          seconds,
          HttpAttributes.HttpRequestMethod("GET"),
          ServerAttributes.ServerAddress("example.com"),
          ServerAttributes.ServerPort(443L),
        )
      }
}

HttpMetrics.ClientRequestDuration defines the instrument as http.client.request.duration, with unit s and the description from the semantic convention. The example records seconds and uses bucket boundaries in the same unit.

3. Supply the attributes required by the metric spec

The generated constructor configures the instrument metadata. It does not add attributes to measurements.

Use the metric object's attributeSpecs to see which attributes are required, conditionally required, recommended, or opt-in. Add the applicable generated attributes each time you record a measurement.

What's next