Class VirtualThreadExecutorMetrics

java.lang.Object
ubic.gemma.core.metrics.binder.VirtualThreadExecutorMetrics
All Implemented Interfaces:
io.micrometer.core.instrument.binder.MeterBinder

@ParametersAreNonnullByDefault public class VirtualThreadExecutorMetrics extends Object implements io.micrometer.core.instrument.binder.MeterBinder
Micrometer binder for virtual-thread-per-task executors (JDK 21+).

Mirrors the ThreadPoolExecutorMetrics shape (pool-tagged counters and gauges) but works for any ExecutorService — in particular Executors.newVirtualThreadPerTaskExecutor(), which is not a ThreadPoolExecutor and therefore cannot be bound via GenericExecutorMetrics.

Usage: construct with a pool name, call wrap(ExecutorService) to obtain an instrumented executor (delegating; submission and execution counters increment around Executor.execute(Runnable) and submit*), then register this binder with a MeterRegistry (typically by adding it to the binder list in MetricsConfig).

Metrics emitted, all tagged pool=<name>:

  • gemma.executor.vt.submitted — total tasks submitted via execute / submit*
  • gemma.executor.vt.active — tasks currently executing
  • gemma.executor.vt.completed — total tasks that finished (success or failure)
  • gemma.executor.vt.failed — tasks that completed by throwing
  • gemma.executor.vt.queued — tasks submitted but not yet started (typically near zero for VT-per-task since each submission spawns a thread immediately; published for symmetry with platform-pool dashboards)
  • gemma.executor.vt.task.duration — distribution of task execution time
Author:
claude
  • Constructor Details

    • VirtualThreadExecutorMetrics

      public VirtualThreadExecutorMetrics(String name)
  • Method Details

    • bindTo

      public void bindTo(io.micrometer.core.instrument.MeterRegistry registry)
      Specified by:
      bindTo in interface io.micrometer.core.instrument.binder.MeterBinder
    • wrap

      public ExecutorService wrap(ExecutorService delegate)
      Wrap a virtual-thread executor so that execute and submit* increment the counters bound by bindTo(MeterRegistry). All other ExecutorService methods (lifecycle, invokeAll/Any) pass through to the delegate; tasks scheduled through invokeAll/invokeAny are instrumented at the submit* layer because those methods are implemented in terms of submit on the JDK VT executor — to keep the accounting unambiguous, this wrapper instruments at the boundary callers actually use (execute and submit*).