Metrics | Runtime

otel4s-sdk-contrib-metrics can register runtime metrics for all supported platforms:

These metrics are not enabled by the SDK autoconfiguration automatically. You register them explicitly in your application, and they are exported by whatever metric reader/exporter configuration your SDK already uses.

Getting started

Add the runtime metrics module:

libraryDependencies ++= Seq(
  "org.typelevel" %%% "otel4s-sdk-contrib-metrics" % "0.19.3" // <1>
)
//> using dep "org.typelevel::otel4s-sdk-contrib-metrics::0.19.3" // <1>
  1. Add the runtime metrics module

Registering runtime metrics

Runtime metrics use the same MeterProvider[F] as the rest of your application. The returned Resource manages the lifecycle of all registered observers and background tasks.

import cats.effect.{IO, IOApp}
import org.typelevel.otel4s.metrics.MeterProvider
import org.typelevel.otel4s.sdk.OpenTelemetrySdk
import org.typelevel.otel4s.sdk.contrib.metrics.runtime.RuntimeMetrics

object Main extends IOApp.Simple {

  def run: IO[Unit] =
    OpenTelemetrySdk.autoConfigured[IO]().use { autoConfigured =>
      implicit val meterProvider: MeterProvider[IO] =
        autoConfigured.sdk.meterProvider

      RuntimeMetrics.register[IO].surround {
        program
      }
    }

  private def program: IO[Unit] =
    IO.never
}

If you already export application metrics through OTLP, Prometheus, or another configured exporter, runtime metrics are exported the same way. Exporter and reader settings are documented in SDK configuration.

Configuration model

Runtime metrics are configured in code via RuntimeMetrics.Config.

There are no dedicated environment variables or system properties for enabling or disabling individual runtime metric groups. Runtime metric collection itself is controlled in code; export behavior is controlled by the SDK metric configuration.

Platform support

JVM

Available config switches:

Example:

import cats.effect.{IO, Resource}
import org.typelevel.otel4s.metrics.{BucketBoundaries, MeterProvider}
import org.typelevel.otel4s.sdk.contrib.metrics.runtime.RuntimeMetrics

val config =
  RuntimeMetrics.Config.disabledAll
    .withCpuMetricsEnabled
    .withMemoryPoolMetricsEnabled
    .withGcMetricsEnabled
    .withGcMetricsBucketBoundaries(BucketBoundaries(0.005, 0.01, 0.05, 0.1, 1.0))

def register(implicit provider: MeterProvider[IO]): Resource[IO, Unit] = 
  RuntimeMetrics.register[IO](config)

Exported metrics:

Notes:

Scala.js

Scala.js runtime metrics target Node.js runtimes. They depend on Node APIs such as node:perf_hooks, so they are not intended for browser environments.

Available config switches:

Example:

import cats.effect.{IO, Resource}
import org.typelevel.otel4s.metrics.MeterProvider
import org.typelevel.otel4s.sdk.contrib.metrics.runtime.RuntimeMetrics

import scala.concurrent.duration._

val config =
  RuntimeMetrics.Config.enabledAll
    .withEventLoopMonitoringPrecision(20.millis)
    .withNodeGcMetricsDisabled

def register(implicit provider: MeterProvider[IO]): Resource[IO, Unit] = 
  RuntimeMetrics.register[IO](config)

Exported metrics:

Notes:

Scala Native

Available config switches:

Example:

import cats.effect.{IO, Resource}
import org.typelevel.otel4s.metrics.{BucketBoundaries, MeterProvider}
import org.typelevel.otel4s.sdk.contrib.metrics.runtime.RuntimeMetrics

import scala.concurrent.duration._

val config =
  RuntimeMetrics.Config.enabledAll
    .withGcMetricsRefreshRate(1.second)
    .withGcMetricsBucketBoundaries(BucketBoundaries(0.01, 0.1, 1.0, 5.0))

def register(implicit provider: MeterProvider[IO]): Resource[IO, Unit] = 
  RuntimeMetrics.register[IO](config)

Exported metrics:

Notes:

What gets exported

Runtime metrics are regular SDK metrics:

If you use OpenTelemetrySdk.autoConfigured, runtime metrics inherit:

The instrumentation scope used by these metrics is:

org.typelevel.otel4s.sdk.runtime

If your resource detectors are enabled, exported metrics will also include process and runtime resource attributes such as process.runtime.name, process.runtime.version, and process.runtime.description where supported. See SDK configuration for resource detector settings.