Skip to content

Cache observer

Cache event capture, the raw report, exports, deletion, and settings are provided by the native_observability_cache_observer submodule. It is part of the RAW install tier; enable it with drush no:preset:raw, or directly with drush en native_observability_cache_observer -y.

Cache tab of the dashboard, showing cache health and efficiency
The Cache tab reads the records this module writes: backend per cache layer, activity trend, and an efficiency score broken down by cacheable responses, HTTP cache activity, invalidation pressure and dynamic cache effectiveness.

Routes

Route Path Permission
native_observability_cache_observer.report /admin/reports/native-observability/cache-observer access native observability cache observer
native_observability_cache_observer.view /admin/reports/native-observability/cache-observer/{id} access native observability cache observer
native_observability_cache_observer.export /admin/reports/native-observability/cache-observer/{id}/export access native observability cache observer
native_observability_cache_observer.export_filtered /admin/reports/native-observability/cache-observer/export/filtered access native observability cache observer
native_observability_cache_observer.delete_selected /admin/reports/native-observability/cache-observer/delete-selected administer native observability cache observer
native_observability_cache_observer.delete_scope /admin/reports/native-observability/cache-observer/delete-scope administer native observability cache observer
native_observability_cache_observer.delete_all /admin/reports/native-observability/cache-observer/delete-all administer native observability cache observer
native_observability_cache_observer.delete_filtered /admin/reports/native-observability/cache-observer/delete-filtered administer native observability cache observer
native_observability_cache_observer.settings /admin/config/development/native-observability/settings/cache-observer administer native observability cache observer

Report

Open /admin/reports/native-observability/cache-observer. CacheObserverListController::list() renders a filterable, paginated table (event/layer, status, method, route/path, request ID, cacheability summary, created date) sourced from CacheObserverStorage. Filters read from the query string: search, event_type, status, method (the filtered export and deletion forms additionally support cache_layer, route_name, path, request_id, has_request_id, and uncacheable_only).

CacheObserverEnvironmentInspector checks the environment and the report shows a warning banner when it finds Twig debug enabled, the page_cache or dynamic_page_cache module disabled, or the page or dynamic_page_cache cache bin served by the null backend. A bin is not checked again when its module is already reported as disabled. In any of these conditions, cache headers, page cache hits, dynamic cache hits, and other observer signals may be partial or missing.

Each row links to the single event view. The row's request_id is shown as plain text; to find the correlated trace, open /admin/reports/native-observability/trace/request/{request_id} (route native_observability.trace_view_by_request_id).

A row recorded for an Internal Page Cache HIT is the one case where that trace is expected to be absent. A hit is served by the page cache middleware before the HTTP kernel runs, so no trace row is ever written for it. The observer still assigns the request a correlation ID and records it, both on the row and on the X-Native-Observability-Request-Id response header, so a hit remains identifiable and countable. That ID resolves to this cache event and to nothing in native_observability_trace, which is the accurate answer for a request Drupal never handled.

The MCP tools cache_explain_misses and cache_events_list classify an uncacheable event by reason: poor cacheability, no cacheability, request policy, response policy or other. An event whose request ended with HTTP 400 or more is reported as error_response, because an error response is never cacheable in the dynamic page cache and says nothing about the route. cache_explain_misses also counts them apart, as error_responses with a 4xx and a 5xx count.

Cache Observer does not need Spans. Without the Spans module the request spans cannot carry the cache summary, and everything else works the same. Requests matching an exclusion rule are not recorded, an Internal Page Cache HIT included.

Single event view

Follow a row's ID link, or open /admin/reports/native-observability/cache-observer/{id} directly, for full details on one captured cache event.

Exports

Single event

/admin/reports/native-observability/cache-observer/{id}/export downloads the raw stored record as cache_observer_event_<id>.json.

Filtered set

/admin/reports/native-observability/cache-observer/export/filtered downloads up to 5000 rows matching the current filter set as cache_observer_filtered_export.json. The payload includes a meta block (export timestamp, row count, applied filters) alongside the rows array.

Deletion scopes

The submodule exposes four distinct deletion actions. They are not interchangeable: each targets a different subset of stored records.

Scope Route What it deletes
Selected delete_selected Only the record IDs passed in the ids query parameter (comma-separated), populated by row selection in the report UI.
Scope (table) delete_scope Every record in one partition, chosen by the scope query parameter: route_bound (events captured inside a resolved Drupal route) or orphan (rows with no resolved route, which today are only page cache HITs recorded by the middleware; invalidations outside a kernel request, such as drush or cron run from the CLI, are not recorded because they carry no request id). The other partition is left untouched.
All delete_all Every stored cache observer record, regardless of filters or partition.
Filtered delete_filtered Only the records matching the filter set currently applied on the report page (up to 5000 rows per submission).
flowchart TD
    A[Cache observer records] --> B[Selected: chosen row IDs only]
    A --> C["Scope: route_bound partition"]
    A --> D["Scope: orphan partition (no resolved route)"]
    A --> E[Filtered: rows matching current filters]
    A --> F[All: every record]

All four deletion forms are confirmation forms and note explicitly that they remove stored observability records only; none of them clears Drupal's runtime caches.

Settings

/admin/config/development/native-observability/settings/cache-observer configures capture behavior and retention. See Cache observer settings for the full list of keys and their default values.