Instrumented Dispatcher
A CoroutineDispatcher that wraps delegate and records how many blocks were dispatched, how many ran concurrently at peak, and the longest queue delay (dispatch to block start). Useful to detect saturated dispatchers while diagnosing slow or starved coroutines.
It is a convenience over TracingDispatcher plus StatsSink: it owns one of each and reports DispatcherStats, a three-number view of DispatcherMetrics. For richer data (latency histograms and percentiles, pending and failure counts, signals, thread information) build a TracingDispatcher with a StatsSink directly.
Diagnostic tool, opt-in, not meant for production. Wrapping a dispatcher such as Dispatchers.IO hides its limitedParallelism and elasticity hints from the coroutines machinery, so behavior can differ slightly from the unwrapped dispatcher. It also costs a few tens of nanoseconds and some allocation per dispatch (rough, unbenchmarked measurement on JVM).
It also forwards Delay: when delegate has its own delay implementation (for example a TestDispatcher, whose virtual time delay and withTimeout must honor), timers are scheduled on it. Otherwise the standard default delay is used. Either way the coroutine resumes through this dispatcher, so the resume is counted exactly once.
Counters are thread-safe and lock-free; read them with snapshot and zero them with reset.
Example:
val io = InstrumentedDispatcher(Dispatchers.ioCompat, "io")
withContext(io) { api.fetch() }
println(io.snapshot()) // DispatcherStats(label=io, totalDispatched=1, ...)Rules: DISPATCH_005 (dispatchers are injected, so they can be wrapped). See docs/BEST_PRACTICES_COROUTINES.md section 3.5.
Requires opting in to ExperimentalStructuredCoroutines.
Parameters
the dispatcher that actually runs the blocks.
name reported in DispatcherStats.label.
See also
Properties
Functions
Zeroes the counters. Blocks that are running while this is called finish without being counted again, but they are no longer part of the concurrency level seen by later blocks, so DispatcherStats.peakConcurrency right after a reset under load can be lower than the true overlap with them.
Returns the stats observed so far. Cheap and safe to call from any thread; the returned DispatcherStats is an immutable copy and is not updated afterwards.