Observability
View MarkdownA Vertique application answers three operational questions: is it alive, what is it doing, and which request caused this. Each answer comes from a module you compose, with safe defaults:
- A separate management plane. Liveness and readiness probes are served by a dedicated
management server (port
9090by default), separate from the application port. Probes and metrics can therefore sit behind different network policy than application traffic. - Any module can contribute a health check. The health-check SPI lives in the core module, so a capability contributes its own readiness without depending on the management server.
- Backend-agnostic metrics. One injected meter registry is bootstrapped before the runtime and wired into Vert.x’s own metrics. Backends activate by classpath presence. With none present, or with metrics disabled, recording is a safe no-op.
- Per-layer metrics as modules. REST and services metrics ship as their own modules, which
you add when you want them. The built-in
@Timedaspect times any bean method (see AOP and events). - Opt-in distributed tracing. OpenTelemetry bootstraps its own SDK or reuses a javaagent’s, installs the Vert.x tracer, and bridges trace ids into the correlation context so that logs and traces share ids.
- One correlation id across the request path. A request id at the REST edge, an
x-correlation-idheader on Kafka records, and the durable context captured by workflow instances are mirrored into the logging MDC, so a log line names the request it belongs to. - Completion callbacks at every boundary. REST requests, MCP requests, Kafka records, and outbox publish attempts each report their final outcome to a listener the application contributes.
The REST and services starters include the management plane. Metrics and tracing are modules your component names explicitly.
Deployment covers the platform side: where probes are pointed, who scrapes metrics, and where logs ship. This page covers what the application itself emits.
The management plane
Section titled “The management plane”ManagementVerticle serves Kubernetes-style probes on the management port. Each probe is backed
by a qualified health-check set:
| Endpoint | Backing check set | UP response |
DOWN response |
|---|---|---|---|
GET /health/live |
@Liveness-qualified checks |
200 |
503 |
GET /health/ready |
@Readiness-qualified checks |
200 |
503 |
Framework capabilities contribute their own checks. The run on the Services page
shows a managed service deployment reporting through readiness. An application contributes its
own HealthCheck the same way, through a Dagger multibinding. The management server also hosts
operational endpoints contributed by other modules, such as a Prometheus scrape route when that
backend is installed. Applications on vertique-starter-rest or vertique-starter-services
already have ManagementModule in their component. Every other application names it explicitly.
Metrics
Section titled “Metrics”vertique-micrometer-core bootstraps a composite meter registry before the runtime is built,
wires it into Vert.x’s metrics subsystem, and exposes it as an injectable MeterRegistry. Code
records metrics without knowing which backends exist.
Backends are classpath-activated. vertique-micrometer-registry-prometheus contributes the
Prometheus registry and its scrape endpoint on the management plane. Add
vertique-micrometer-rest or vertique-micrometer-services for per-request and per-dispatch
metrics at those layers, and use the @Timed aspect for any bean method.
Add the optional vertique-micrometer-resilience adapter alongside vertique-resilience when
resilience events should become timers and counters in the shared registry. It contributes one
isolated, synchronous observer and follows metrics.enabled. See the
vertique-micrometer-resilience module reference
for the fixed meter names, tags, and cardinality exclusions.
When metrics.enabled is false or no backend is present, the composite is empty and every
recording is a no-op.
Tracing
Section titled “Tracing”vertique-opentelemetry-core provides opt-in distributed tracing. It bootstraps an OpenTelemetry
SDK before the runtime, or reuses an existing global one installed by a javaagent. It then
installs the Vert.x tracing subsystem and emits security lifecycle events as span events.
Trace ids are bridged into the framework’s correlation context, so once tracing is on, logs and
spans share identifiers without further wiring. vertique-opentelemetry-rest and
vertique-opentelemetry-services add the per-layer spans. Tracing owns no metrics and no log
output. Those belong to Micrometer and the logging module, so the three concerns do not overlap.
Correlation
Section titled “Correlation”vertique-correlation owns the correlation context that the rest of the framework reads and
writes: generated or inherited correlation ids, selective mirroring into the logging MDC, and the
adapter that snapshots and restores the context across async boundaries. Because of it, the REST
edge returns an X-Request-Id header, a consumed Kafka record’s x-correlation-id seeds its
dispatch, and a workflow instance’s captured durable context can fill correlation back in when
the instance resumes days later.
Observe request completion
Section titled “Observe request completion”Each transport reports a request once, when it is finished, to listeners the application contributes through a Dagger set multibinding. Use them for your own metrics, audit records, or access logs. The framework’s REST metrics module is itself one of these listeners.
| Request | Listener |
|---|---|
A JAX-RS operation, including one rejected with 401, 403, 415, or a validation 400 |
RestRequestCompletedListener |
A request no transport claimed: 404, 405, a root-level rejection, a failed WebSocket upgrade |
HttpRequestCompletedListener |
| A request the MCP mount handled | McpRequestCompletedListener |
A request produces one event, from the transport that handled it. An MCP request does not also produce a REST event, and a successful WebSocket upgrade produces none.
From the vertique-rest-core module reference, a listener that counts requests by route:
@Provides@IntoSetstatic RestRequestCompletedListener requestMetrics(MeterRegistry registry) { return event -> registry.counter( "http.server.requests", "method", event.method(), "route", event.operation().routeTemplate(), "status", Integer.toString(event.statusCode())) .increment();}A REST event always carries the matched operation, so event.operation() is never null. Both
REST and HTTP events also carry the timing, the status, a safe failure code, the security and
correlation snapshots, and the request origin.
Listeners are unordered and must not block. An exception a listener throws is logged and does not
stop the remaining listeners or change the response. A listener that needs the live request
overrides the two-argument onCompleted(event, routingContext) overload.
The messaging modules follow the same pattern. See Observe every record’s outcome for Kafka consumers and Observe publish attempts for the outbox relay.
Learn more
Section titled “Learn more”vertique-managementmodule reference: the management server, probe aggregation, and theHealthCheckextension point.vertique-micrometer-coremodule reference: the composite registry, backend SPI, and configuration.vertique-micrometer-registry-prometheusmodule reference: the Prometheus backend and scrape endpoint.vertique-opentelemetry-coremodule reference: the SDK lifecycle, tracer installation, and the correlation seam.vertique-correlationmodule reference: the correlation context, MDC mirroring, and async snapshot/restore.vertique-rest-coremodule reference: the completion listeners, their event records, and the isolation rules.- Deployment: the platform side, with probes, scraping, and log shipping.
- AOP and events: the
@Timedaspect. - What is Vertique?
Continue reading
Section titled “Continue reading”- Previous: Testing
- Next: Deployment