Class TracingExecutor

java.lang.Object
com.vaadin.observability.micrometer.trace.TracingExecutor
All Implemented Interfaces:
Executor

public class TracingExecutor extends Object implements Executor
Wraps the Vaadin service Executor so that
  1. the trace context (and any other ThreadLocalAccessor-backed state) active when a task is submitted is restored when the task runs; and
  2. each task gets its own vaadin.executor.task span when an ObservationRegistry is supplied. The span is parented to the propagated trace, so work handed to the executor from a request thread ends up with a continuous trace tree across the thread hop.

The scope is tasks submitted to the Vaadin service executor: the signal effects Vaadin re-evaluates on it directly, the signal result notifications it dispatches through it, and the background tasks applications are expected to hand to it. It is not every UI.access(...): a plain call from a background thread queues a command that whichever thread unlocks the session drains, so it never passes through this executor and gets no span of its own. A notification task is itself a UI.access call, so its span always covers the dispatch, but covers the notification body only when the session lock happens to be free; otherwise the task returns as soon as the command is enqueued and the body runs later on the unlocking thread, outside the span.

Use wrap(Executor, ObservationRegistry) rather than the constructors so that an ExecutorService delegate keeps its lifecycle methods: Vaadin shuts its default executor down on service destroy, and only does so when the executor still is an ExecutorService.

  • Constructor Details

    • TracingExecutor

      public TracingExecutor(Executor delegate)
    • TracingExecutor

      public TracingExecutor(Executor delegate, io.micrometer.observation.ObservationRegistry observationRegistry)
  • Method Details

    • wrap

      public static Executor wrap(Executor delegate, io.micrometer.observation.ObservationRegistry observationRegistry)
      Wraps the given executor for tracing, preserving the ExecutorService contract when the delegate implements it.

      Wrapping is idempotent: an executor that already traces is returned as-is.

      Parameters:
      delegate - the executor to wrap, not null
      observationRegistry - the registry used to create the per-task span, may be null to only propagate the context
      Returns:
      the tracing executor
    • execute

      public void execute(Runnable command)
      Specified by:
      execute in interface Executor
    • instrument

      protected final Runnable instrument(Runnable command)
      Captures the current context and returns a task that restores it and opens a vaadin.executor.task span before running command.

      Must be called on the submitting thread, since that is where the context to propagate lives.

      Parameters:
      command - the task to instrument, not null
      Returns:
      the instrumented task
    • instrument

      protected final <T> Callable<T> instrument(Callable<T> task)
      Callable counterpart of instrument(Runnable), used by the ExecutorService submission methods.
      Type Parameters:
      T - the task result type
      Parameters:
      task - the task to instrument, not null
      Returns:
      the instrumented task