Metrics | Cats Effect IO runtime
Available metrics
CPU Starvation
Platforms: JVM, Scala.js, Scala Native.
These metrics could help identify performance bottlenecks caused by an overloaded compute pool, excessive task scheduling, or lack of CPU resources.
Name | Description | Unit |
---|---|---|
cats.effect.runtime.cpu.starvation.clock.drift.current | The current CPU drift in milliseconds. | ms |
cats.effect.runtime.cpu.starvation.clock.drift.max | The max CPU drift in milliseconds. | ms |
cats.effect.runtime.cpu.starvation.count | The number of CPU starvation events. |
Work-stealing thread pool - compute
Platforms: JVM.
Built-in attributes:
pool.id
- the id of the work-stealing thread pool
These metrics provide insights about fibers and threads within the compute pool. They help diagnose load distribution, identify bottlenecks, and monitor the pool’s efficiency in handling tasks.
Name | Description | Unit |
---|---|---|
cats.effect.runtime.wstp.compute.fiber.enqueued.count | The total number of fibers enqueued on all local queues. | {fiber} |
cats.effect.runtime.wstp.compute.fiber.suspended.count | The number of fibers which are currently asynchronously suspended. | {fiber} |
cats.effect.runtime.wstp.compute.thread.active.count | The number of active worker thread instances currently executing fibers on the compute thread pool. | {thread} |
cats.effect.runtime.wstp.compute.thread.blocked.count | The number of worker thread instances that can run blocking actions on the compute thread pool. | {thread} |
cats.effect.runtime.wstp.compute.thread.count | The number of worker thread instances backing the work-stealing thread pool (WSTP). | {thread} |
cats.effect.runtime.wstp.compute.thread.searching.count | The number of worker thread instances currently searching for fibers to steal from other worker threads. | {thread} |
Work-stealing thread pool - thread
Platforms: JVM.
Built-in attributes:
pool.id
- the id of the work-stealing thread pool the worker is used byworker.index
- the index of the worker thread-
thread.event
- the thread eventparked
- a thread is parkedpolled
- a thread is polled for I/O eventsblocked
- a thread is switched to a blocking thread and been replacedrespawn
- a thread is replaced by a newly spawned thread
These metrics provide detailed information about threads state within the compute pool.
Name | Description | Unit |
---|---|---|
cats.effect.runtime.wstp.worker.thread.event.count | The total number of events that happened to this WorkerThread. | {event} |
cats.effect.runtime.wstp.worker.thread.idle.duration | The total amount of time in nanoseconds that this WorkerThread has been idle. | ns |
Work-stealing thread pool - local queue
Platforms: JVM.
Built-in attributes:
pool.id
- the id of the work-stealing thread pool the queue is used byworker.index
- the index of the worker thread the queue is used by
These metrics provide a detailed view of fiber distribution within the pool. They help diagnose load imbalances and system inefficiency.
Name | Description | Unit |
---|---|---|
cats.effect.runtime.wstp.worker.localqueue.fiber.count | The total number of fibers enqueued during the lifetime of the local queue. | {fiber} |
cats.effect.runtime.wstp.worker.localqueue.fiber.enqueued.count | The current number of enqueued fibers. | {fiber} |
cats.effect.runtime.wstp.worker.localqueue.fiber.spillover.count | The total number of fibers spilt over to the external queue. | {fiber} |
cats.effect.runtime.wstp.worker.localqueue.fiber.steal_attempt.count | The total number of successful steal attempts by other worker threads. | {fiber} |
cats.effect.runtime.wstp.worker.localqueue.fiber.stolen.count | The total number of stolen fibers by other worker threads. | {fiber} |
Work-stealing thread pool - timer heap
Platforms: JVM.
Built-in attributes:
pool.id
- the id of the work-stealing thread pool the timer heap is used byworker.index
- the index of the worker thread the timer heap is used by-
timer.state
- the state of the timerexecuted
- the successfully executed timerscheduled
- the scheduled timercanceled
- the canceled timer
These metrics provide a detailed view of timer stats within the pool.
Name | Description | Unit |
---|---|---|
cats.effect.runtime.wstp.worker.timerheap.next.due | Returns the time in nanoseconds till the next due to fire. | ns |
cats.effect.runtime.wstp.worker.timerheap.outstanding.count | The current number of the outstanding timers, that remain to be executed. | {timer} |
cats.effect.runtime.wstp.worker.timerheap.packed.count | The total number of times the heap packed itself to remove canceled timers. | {event} |
cats.effect.runtime.wstp.worker.timerheap.timer.count | The total number of the timers per state. | {timer} |
Work-stealing thread pool - poller
Platforms: JVM.
Built-in attributes:
pool.id
- the id of the work-stealing thread pool the poller is used byworker.index
- the index of the worker thread the poller is used by-
poller.operation
- the operation performed by the polleraccept
connect
read
write
-
poller.operation.status
- the status of the operationsubmitted
- the operation has been submittedsucceeded
- the operation has errorederrored
- the operation has erroredcanceled
- the operation has been canceled
These metrics provide a detailed view of poller stats within the pool.
Name | Description | Unit |
---|---|---|
cats.effect.runtime.wstp.worker.poller.operation.count | The total number of the operations per category and outcome. | {operation} |
cats.effect.runtime.wstp.worker.poller.operation.outstanding.count | The current number of outstanding operations per category and outcome. | {operation} |
Getting started
Add the following configuration to the favorite build tool:
Add settings to the build.sbt
:
libraryDependencies ++= Seq(
"org.typelevel" %%% "otel4s-instrumentation-metrics" % "0.12.0-RC2" // <1>
)
Add directives to the *.scala
file:
//> using dep "org.typelevel::otel4s-instrumentation-metrics::0.12.0-RC2" // <1>
- Add the
otel4s-instrumentation-metrics
library
Registering metrics collectors
IORuntimeMetrics.register
takes care of the metrics lifecycle management.
import cats.effect._
import org.typelevel.otel4s.instrumentation.ce.IORuntimeMetrics
import org.typelevel.otel4s.metrics.MeterProvider
import org.typelevel.otel4s.trace.TracerProvider
import org.typelevel.otel4s.oteljava.OtelJava
object Main extends IOApp.Simple {
def run: IO[Unit] =
OtelJava.autoConfigured[IO]().use { otel4s =>
implicit val mp: MeterProvider[IO] = otel4s.meterProvider
IORuntimeMetrics
.register[IO](runtime.metrics, IORuntimeMetrics.Config.default)
.surround {
program(otel4s.meterProvider, otel4s.tracerProvider)
}
}
def program(
meterProvider: MeterProvider[IO],
tracerProvider: TracerProvider[IO]
): IO[Unit] = {
val _ = (meterProvider, tracerProvider)
IO.unit
}
}
import cats.effect._
import org.typelevel.otel4s.instrumentation.ce.IORuntimeMetrics
import org.typelevel.otel4s.metrics.MeterProvider
import org.typelevel.otel4s.trace.TracerProvider
import org.typelevel.otel4s.sdk.OpenTelemetrySdk
object Main extends IOApp.Simple {
def run: IO[Unit] =
OpenTelemetrySdk.autoConfigured[IO]().use { autoConfigured =>
val sdk = autoConfigured.sdk
implicit val mp: MeterProvider[IO] = sdk.meterProvider
IORuntimeMetrics
.register[IO](runtime.metrics, IORuntimeMetrics.Config.default)
.surround {
program(sdk.meterProvider, sdk.tracerProvider)
}
}
def program(
meterProvider: MeterProvider[IO],
tracerProvider: TracerProvider[IO]
): IO[Unit] = {
val _ = (meterProvider, tracerProvider)
IO.unit
}
}
Grafana dashboard
You can use a Grafana dashboard to visualize collected metrics.
Customization
The behavior of the IORuntimeMetrics.register
can be customized via IORuntimeMetrics.Config
.
CPU Starvation
To disable CPU starvation metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
IORuntimeMetrics.Config(
CpuStarvationConfig.disabled, // disable CPU starvation metrics
WorkStealingThreadPoolConfig.enabled
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
To attach attributes to CPU starvation metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled(
Attributes(Attribute("key", "value")) // the attributes
),
WorkStealingThreadPoolConfig.enabled
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
Work-stealing thread pool - compute
To disable worker metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.disabled, // disable compute metrics
WorkStealingThreadPoolConfig.WorkerThreadsConfig.enabled
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
To attach attributes to compute metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled(
Attributes(Attribute("key", "value")) // attributes
),
WorkStealingThreadPoolConfig.WorkerThreadsConfig.enabled
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
Work-stealing thread pool - thread
To disable thread metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled,
WorkerThreadsConfig(
WorkerThreadsConfig.ThreadConfig.disabled, // disable worker thread metrics
WorkerThreadsConfig.LocalQueueConfig.enabled,
WorkerThreadsConfig.TimerHeapConfig.enabled,
WorkerThreadsConfig.PollerConfig.enabled
)
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
To attach attributes to thread metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled,
WorkerThreadsConfig(
WorkerThreadsConfig.ThreadConfig.enabled(
Attributes(Attribute("key", "value")) // the attributes
),
WorkerThreadsConfig.LocalQueueConfig.enabled,
WorkerThreadsConfig.TimerHeapConfig.enabled,
WorkerThreadsConfig.PollerConfig.enabled
)
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
Work-stealing thread pool - local queue
To disable local queue metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled,
WorkerThreadsConfig(
WorkerThreadsConfig.ThreadConfig.enabled,
WorkerThreadsConfig.LocalQueueConfig.disabled, // disable local queue metrics
WorkerThreadsConfig.TimerHeapConfig.enabled,
WorkerThreadsConfig.PollerConfig.enabled
)
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
To attach attributes to local queue metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled,
WorkerThreadsConfig(
WorkerThreadsConfig.ThreadConfig.enabled,
WorkerThreadsConfig.LocalQueueConfig.enabled(
Attributes(Attribute("key", "value")) // the attributes
),
WorkerThreadsConfig.TimerHeapConfig.enabled,
WorkerThreadsConfig.PollerConfig.enabled
)
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
Work-stealing thread pool - timer heap
To disable timer heap metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled,
WorkerThreadsConfig(
WorkerThreadsConfig.ThreadConfig.enabled,
WorkerThreadsConfig.LocalQueueConfig.enabled,
WorkerThreadsConfig.TimerHeapConfig.enabled, // disable timer heap metrics
WorkerThreadsConfig.PollerConfig.enabled
)
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
To attach attributes to timer heap metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled,
WorkerThreadsConfig(
WorkerThreadsConfig.ThreadConfig.enabled,
WorkerThreadsConfig.LocalQueueConfig.enabled,
WorkerThreadsConfig.TimerHeapConfig.enabled(
Attributes(Attribute("key", "value")) // the attributes
),
WorkerThreadsConfig.PollerConfig.enabled
)
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
Work-stealing thread pool - poller
To disable poller metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled,
WorkerThreadsConfig(
WorkerThreadsConfig.ThreadConfig.enabled,
WorkerThreadsConfig.LocalQueueConfig.enabled,
WorkerThreadsConfig.TimerHeapConfig.enabled,
WorkerThreadsConfig.PollerConfig.disabled // disable poller metrics
)
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)
To attach attributes to poller metrics:
val config: IORuntimeMetrics.Config = {
import IORuntimeMetrics.Config._
import WorkStealingThreadPoolConfig._
IORuntimeMetrics.Config(
CpuStarvationConfig.enabled,
WorkStealingThreadPoolConfig(
ComputeConfig.enabled,
WorkerThreadsConfig(
WorkerThreadsConfig.ThreadConfig.enabled,
WorkerThreadsConfig.LocalQueueConfig.enabled,
WorkerThreadsConfig.TimerHeapConfig.enabled,
WorkerThreadsConfig.PollerConfig.enabled(
Attributes(Attribute("key", "value")) // the attributes
)
)
)
)
}
IORuntimeMetrics.register[IO](runtime.metrics, config)