Docs

Observability Kit Reference

The metrics and tracing spans Observability Kit records, with their types, tags, and attributes.

Observability Kit instruments the Vaadin runtime and records everything into your application’s Micrometer MeterRegistry. Metrics are plain Micrometer meters; tracing spans are emitted through the Micrometer Observation API. Both flow to whatever backend you’ve configured — see the Integrations page.

Each group of meters and spans is controlled by a feature toggle (for example vaadin.observability.sessions). See the Configuration page for how to turn features on or off.

Note
Naming Conventions
Meter names follow Micrometer’s dotted, lowercase convention (for example vaadin.request.duration). How a name appears in your backend depends on that its conventions — Prometheus, for instance, renders vaadin.request.duration as vaadin_request_duration_seconds with a _count, _sum, and bucket suffixes.

Metrics

A meter is a measurement recorded at runtime. Observability Kit records the meter types Micrometer provides:

Counter

A value that only increases, such as the number of sessions created.

Gauge

A value sampled at a point in time, such as the number of active sessions.

Timer

Records both a count of events and the distribution of their durations.

Distribution summary

Records both a count of events and the distribution of a non-time measurement, such as the number of rows read from a query.

Session Metrics

Controlled by vaadin.observability.sessions.

Meter Type Description

vaadin.sessions.active

Gauge

Currently active sessions.

vaadin.sessions.created

Counter

Sessions created since startup.

vaadin.sessions.duration

Timer

Session lifetime, recorded when a session ends.

vaadin.session.lock.wait

Timer

Time spent waiting to acquire the session lock. Tagged by context.

vaadin.session.lock.hold

Timer

Time the session lock is held. Tagged by context.

The context tag is request when the lock is taken during request handling, or access when it’s taken through UI.access().

UI Metrics

Controlled by vaadin.observability.uis.

Meter Type Description

vaadin.ui.active

Gauge

Currently active UIs.

vaadin.ui.created

Counter

UIs created since startup.

Controlled by vaadin.observability.navigation.

Meter Type Description

vaadin.navigation

Timer

Navigation duration, from beforeEnter to afterNavigation. Tagged by route and outcome.

A navigation is recorded when it completes, so outcome is currently always success. When a beforeEnter() listener reroutes or forwards, the navigation is recorded once, against the route it ended up on.

Request Metrics

Controlled by vaadin.observability.requests.

Meter Type Description

vaadin.request.duration

Timer

Server-side request handling time. Tagged by outcome.

vaadin.rpc.duration

Timer

Server-side RPC invocation time. Tagged by type and outcome.

Note
Extra Request Tags When Tracing Is Enabled

With tracing on — the default — vaadin.request.duration is produced from the request observation, so it also carries that span’s low-cardinality attributes as tags: vaadin.request.type, vaadin.interaction, and http.method, plus Micrometer’s own error tag. All of these have a bounded set of values. The span’s ui.id and vaadin.client.location attributes are unbounded and are deliberately kept off the timer. With tracing off, the timer carries outcome alone.

Resync Metrics

Controlled by vaadin.observability.resync. These track UIDL message-recovery events, which indicate a flaky client-server connection.

Meter Type Description

vaadin.resync

Counter

Client-server message-recovery events. Tagged by type: resend when the client re-sends a request it never got a response for (the server replays its cached response), or resync when the client gives up on a missing server message and asks for a full UI-state rebuild.

Error Metrics

Controlled by vaadin.observability.errors.

Meter Type Description

vaadin.errors

Counter

Exceptions that propagate out of Vaadin request handling. Tagged by exception (the exception’s simple class name).

Important
What This Counter Does and Doesn’t Count

This counter tracks exceptions that escape request handling — for example one thrown by a custom RequestHandler. It does not count exceptions thrown inside a component listener, such as a button-click or value-change listener. Flow catches those and routes them to the session’s ErrorHandler, so they never reach the request interceptor. Such a failure is still visible in tracing: the vaadin.rpc.<type> span records the error and its outcome tag becomes error, and it carries the component and event that triggered it. It is also visible in vaadin.rpc.duration as an outcome=error sample.

Client Metrics

Controlled by vaadin.observability.client. These are observed in the browser and reported back to the server, subject to the per-session rate limit (see vaadin.observability.client-rate-per-session).

Meter Type Description

vaadin.client.bootstrap.duration

Timer

Browser application bootstrap time.

vaadin.client.navigation.duration

Timer

Browser-observed navigation time.

vaadin.client.web_vitals.lcp

Timer

Largest Contentful Paint.

vaadin.client.web_vitals.fcp

Timer

First Contentful Paint.

vaadin.client.errors

Counter

Errors reported by the browser.

vaadin.client.dropped

Counter

Client samples dropped before recording.

vaadin.client.throttled

Counter

Client samples rejected by the per-session rate limit.

Server round-trip timing isn’t collected in the browser. Use the server-side vaadin.request.duration and vaadin.rpc.duration timers for that.

Database Metrics

Controlled by vaadin.observability.database (off by default, Spring Boot starter only). When enabled, every DataSource bean is wrapped so that JDBC access — Spring Data, JdbcTemplate, or raw JDBC — is measured, attributed to the Vaadin route that triggered it. See Database Monitoring for how this works and when to use it.

Meter Type Description

vaadin.db.fetch.rows

Distribution summary

Rows read from a JDBC result set. Tagged by route.

vaadin.db.query

Timer

JDBC query duration. Tagged by route. Produced alongside the vaadin.db.query span when both database monitoring and tracing are enabled.

Common Tag Values

Tag Values

outcome

success or error.

route

The target route template. Distinct values are capped by vaadin.observability.route-cardinality-limit; beyond the limit they collapse to _other, and an unresolvable route is _unknown.

context

request or access.

type

On RPC meters and spans, the RPC invocation type as reported by Flow. On vaadin.resync, the recovery kind: resend or resync.

exception

The simple class name of the handled exception.

Note
JVM, Process, and Connection-Pool Metrics
Observability Kit doesn’t record JVM, process, or database connection-pool metrics itself. Those come from Micrometer’s standard binders — Spring Boot Actuator registers them out of the box, and you can add others as needed. The kit’s own database metrics above measure query behavior per route, not the connection pool.

Tracing

When tracing is enabled (vaadin.observability.traces, the default) and an ObservationRegistry is available, the kit drives the core request lifecycle through the Observation API. Each observation produces a tracing span and, through Micrometer’s DefaultMeterObservationHandler, the matching timer above — one measurement, recorded two ways.

To export spans, add a Micrometer tracing bridge (for example OpenTelemetry or Zipkin); see the Integrations page.

The kit produces the following spans:

Span Description

vaadin.request

The root span for each Vaadin request. Carries the request-level attributes below.

vaadin.navigation <route>

A navigation, nested under the request that triggered it.

vaadin.rpc.<type>

A server-side RPC invocation (DOM event, @ClientCallable, property sync, or return channel), nested under the request.

vaadin.db.query

A single JDBC query, nested under the request or RPC span that ran it. Emitted only when database monitoring is enabled (see Database Monitoring).

Spans cover work done on the request-handling thread. Work handed to another thread — for example a background task that later calls UI.access() — isn’t linked to the request that started it, and the UI.access() command itself is recorded under whichever request thread runs it.

Span Attributes

The root vaadin.request span carries these attributes:

Attribute Description

vaadin.request.type

The protocol-level request type: uidl, heartbeat, push, static, or other.

vaadin.interaction

What the request actually did: poll, navigation, or rpc, and none for requests where no interaction applies, such as heartbeats and static resources.

http.method

The HTTP method of the request.

outcome

success or error.

ui.id

The ID of the UI associated with the request, or _unknown. Span-only, since UI IDs are unbounded.

vaadin.client.location

The browser location the request was sent from, or _unknown. Span-only: it’s the literal path, not a route template. For templated, cardinality-capped view attribution, use the route tag on the navigation meters.

The nested spans carry the tags of their corresponding meters: vaadin.navigation <route> carries route and outcome; vaadin.rpc.<type> carries type.

The RPC span additionally carries two span-only, high-cardinality attributes when they can be resolved: vaadin.rpc.event (the invocation name, such as a DOM event name, invoked method name, or navigation location) and vaadin.rpc.component (the class name of the targeted Component). These are attached to the span only, never as timer tags, because of their cardinality. Together they let you trace a failure back to the interaction that caused it — which component, and which event.

Flow doesn’t report an invocation name for property syncs, which is how a field’s value change arrives at the server. Those spans carry type and vaadin.rpc.component, but no vaadin.rpc.event.

The vaadin.db.query span carries route, a db.rows attribute with the number of rows read, and — when vaadin.observability.database-statement is enabled — the parameterized SQL as db.statement.

Errors

When a request or a nested operation fails, its observation is marked as error, so the span records the exception and the outcome tag becomes error.

For an exception thrown inside a component listener, this happens on the vaadin.rpc.<type> span — the one that also carries the component and event — rather than on the enclosing vaadin.request span, which still ends as success. Flow hands such an exception to the session’s ErrorHandler instead of letting it escape request handling, which is also why it doesn’t increment the vaadin.errors counter. See Error Metrics for what that counter measures.

Database Monitoring

With the Spring Boot starter, the kit can watch how many rows your queries return and how long they take, without touching application code. Enable it with:

Source code
application.properties
vaadin.observability.database=true

Every DataSource bean is then wrapped so that each JDBC ResultSet reports its row count into the vaadin.db.fetch.rows distribution summary, tagged by the Vaadin route that triggered the fetch. This lets you see which view issues the large reads. Watch the p95/p99 of that summary and alert on it in your backend — for example a Prometheus rule on vaadin_db_fetch_rows — to catch runaway result sets in production.

This is off by default: it reaches outside the Vaadin runtime into the persistence layer and adds a small per-row cost. It covers all JDBC access — Spring Data, JdbcTemplate, and raw JDBC — that flows through a managed DataSource. Row counting is best-effort and attributes to _unknown when no view is active, such as for background tasks.

Locating Slow or Large Queries in a Trace

When tracing is also enabled (vaadin.observability.traces=true, the default), each query additionally opens a vaadin.db.query span. Because it starts on the request-handling thread inside the Vaadin request span, it nests under that request or RPC span automatically. In Jaeger — or any backend fed by your Micrometer tracing bridge — you can open a slow interaction and see the individual queries it ran, each carrying the route and a db.rows attribute. The same observation also yields a vaadin.db.query duration timer: database time per view.

The span doesn’t include the SQL text by default. Set vaadin.observability.database-statement=true to attach the parameterized statement as db.statement. This is useful for pinpointing the offending query, but it’s opt-in because SQL is higher cardinality and can be sensitive.

Extending Built-In Instrumentation

To record your own metrics and spans alongside these, see the Custom Instrumentation page. Custom meters and spans share the same registry and backend, so keep your names and tag cardinality consistent with the conventions above.

4E9CED65-0EA1-4590-956A-6198F0F90482

Updated