Observability & Admin UI

Enable the built-in admin UI to inspect and recover workflows, and wire up metrics to Prometheus or your own backend to monitor the engine.

Skipper ships with a built-in admin UI for inspecting and recovering workflow instances, plus a pluggable metrics hook for monitoring the engine itself.

Enabling the Admin UI

The admin UI is a standard JAX-RS resource — AdminResource, served under the path /skipper/admin. Obtain it from your SkipperRuntime (see the Quickstart) and register it with your application’s JAX-RS / HTTP server alongside your other resources:

val runtime = SkipperRuntime(config)

// AdminResource is a JAX-RS resource — register it with your server's JAX-RS runtime
// (Jersey, Dropwizard, RESTEasy, …).
val admin = runtime.adminResource.get()
jaxrs.register(admin)
SkipperRuntime runtime = new SkipperRuntime(config);

// AdminResource is a JAX-RS resource — register it with your server's JAX-RS runtime
// (Jersey, Dropwizard, RESTEasy, …).
AdminResource admin = runtime.getAdminResource().get();
jaxrs.register(admin);

Because it is a plain JAX-RS resource, it drops into any JAX-RS-compatible stack — there is nothing Skipper-specific about how you mount it. Its endpoints serialize their own JSON, so the host needs no JSON provider (and no particular ObjectMapper configuration) for the UI to work.

Then open the UI in a browser:

http://<your-service-host>/skipper/admin/

For a service running remotely, forward its port to your machine first, then open the path locally.

What the Admin UI gives you

The UI — and the JSON API behind it — lets you:

  • View dashboard stats and search workflow instances by type and status.
  • Inspect a single instance’s status and history — GET /skipper/admin/workflows/{id}.
  • Cancel a running instance — POST /skipper/admin/workflows/{id}/cancel.
  • Review workflows that exhausted their retries and the scheduler dead-letter queue, and requeue stuck tasks.
  • See the scheduler cluster: the live members and the range of task-ID buckets each one fetches from, and whether task partitioning is active on this instance — GET /skipper/admin/cluster.
  • List and replay durable signals:
GET  /skipper/admin/workflows/{id}/signals
POST /skipper/admin/workflows/{id}/signals/{signalId}/replay

These endpoints back the same operations available programmatically through WorkflowsService.

Metrics

Skipper reports engine metrics through a pluggable Metrics interface. It is a no-op by default, so to collect metrics, supply an implementation on the config before creating the runtime. A Prometheus backend ships as a separate artifact, so skipper-core never drags a metrics client onto your classpath; or implement Metrics yourself against any other registry.

Every metric is named as a dotted path of a component and an operation (mysqlWorkflowStore.persistSignal, schedulerManager.handledTasks) and may carry tags such as result and error.

Prometheus

skipper-metrics-prometheus registers collectors with a PrometheusRegistry from the 1.x prometheus-metrics-core client. Names become skipper_<component>_<operation>, tags become labels, counters get the usual _total suffix, timers are histograms in seconds (..._seconds), and gauges read their value on every scrape. Expose the registry through the scrape endpoint you already have, for example prometheus-metrics-exporter-httpserver.

// build.gradle.kts: implementation("com.airbnb.skipper:skipper-metrics-prometheus:<version>")
config.metrics = ComponentFactory { PrometheusMetrics(PrometheusRegistry.defaultRegistry) }
config.setMetrics(cfg -> new PrometheusMetrics(PrometheusRegistry.defaultRegistry));

Histogram bucket boundaries for timers and for value histograms are constructor parameters if the defaults (1 ms to 60 s, and powers of four from 1 to about 4 million) do not fit your workload.

Your own backend

Implement Metrics and install it the same way:

config.metrics = ComponentFactory { MyMetrics() }
config.setMetrics(cfg -> new MyMetrics());

Your implementation receives metrics covering actions, the scheduler, storage, and overall workflow throughput — forward them to your existing pipeline and dashboards to track:

  • Workflow counts by status (running, waiting, completed, errored).
  • Action execution and failure rates.
  • Scheduler and storage latency and error rates.

Watching workflow status counts and the size of the dead-letter queue is usually the fastest way to spot a problem in production.