Request Audit
This module collects and logs request timing data to help diagnose performance issues. It can log this data to Drupal's watchdog system or to database tables. The module also provides a reporting interface with charts and a list of the slowest URLs.
request_audit)
Allow collect telemetry data from requests.
Overview
request_audit instruments incoming requests in Drupal and records latency telemetry. It can log request timing data either to Watchdog or to database tables for reporting and chart visualization.
The module provides:
- An admin settings form to enable/disable telemetry and select logging destination.
- A charts page that renders latency over time buckets (via Chart.js).
- An AJAX endpoint that returns bucketed latency series data.
- A table of URLs below the chart, filtered by the current query and time range.
- A “Top 10 slow URLs” section computed from recent aggregated buckets.
- Zoom support in the chart, with automatic refresh of both the graph and the URL table.
Requirements
- Drupal 10 (and core versions compatible with what’s declared in
composer.json) - PHP requirements are inherited from Drupal.
- A database supported by Drupal’s database layer.
- Chart.js and its plugins available through the configured library paths.
Dependencies
In composer.json the module requires:
drupal/core(^10.6 || ^11 || ^12)npm-asset/chart.js(^4.4)npm-asset/chartjs-plugin-zoom(^2.2)npm-asset/chartjs-adapter-date-fns(^3.0)
Installation
Install via Composer (recommended for contributed modules):
-
From your Drupal root, require the module package:
composer require drupal/request_audit -
Enable the module:
- Via UI: Extend
- Or with Drush:
drush en request_audit
Run database updates if needed:
drush updb
When enabled, the module’s request_audit.install will create these tables if they do not exist:
request_audit_relrequest_audit_latency_agg
Configuration
Go to:
- Configuration → System → Request audit settings
- Route:
/admin/config/system/settings(request_audit.settings)
- Route:
Settings:
- Log activity (
active) - Database
- Log database activity (
database_log) - Log queries list (
save_queries)
- Log database activity (
- Log destination (
log_to)watchdog: logs the payload to Drupal loggerdatabase: stores request timing + aggregated latency in DB
Admin permission
All admin routes require:
administer site configuration
Charts / Reporting
Go to:
- Reports → Request Audit Charts
- Route:
/admin/reports/request-audit-charts(request_audit.request_audit_charts)
- Route:
The page includes:
- A URL pattern control (glob-like, e.g.
/pay2/*) - A time window selector
- An auto-refreshing Chart.js chart
- A zoomable chart with drag-zoom and pan support
- A table of URLs for the current filter/range
- A “Top 10 slow URLs” section (based on average latency in recent buckets)
Chart series
The chart currently displays these series derived from the visible bucket values:
- Avg latency (ms): the average latency of the buckets shown in the chart. This is the main blue line.
- p25–p75: the middle 50% of the bucket values. It shows the typical spread of the data.
- Median: the middle value of the bucket distribution. It is more robust than the average when there are spikes.
- Mean: arithmetic average of the displayed bucket values. It is sensitive to large outliers.
- p95: the value below which 95% of the bucket values fall. Useful to detect slow tail latency.
- p99: the value below which 99% of the bucket values fall. Useful to detect severe tail latency and rare spikes.
URL table behavior
The table below the chart is updated automatically:
- on initial page load
- when the filter pattern changes
- when the time window changes
- when the user zooms into a range of the chart
- when the user resets zoom
The table shows, for each URL:
- position in the result set
- URL path
- number of requests
- average latency
- minimum latency
- maximum latency
AJAX endpoint (data provider)
The chart fetches data from:
/admin/reports/request-audit-charts/block(request_audit.request_audit_charts_block)
Query parameters:
path(optional): exact path matchpattern(optional): glob-like pattern (e.g./pay2/*)windowMinutes(optional, default:180)bucketMinutes(optional, default:5)start(optional): explicit ISO 8601 UTC start of rangeend(optional): explicit ISO 8601 UTC end of range
If both start and end are provided, the chart and the URL table use that explicit range.
This is what makes the zoomed view update correctly.
Response format
The AJAX endpoint returns JSON with:
buckets: bucketed latency data for the chartpath: the active path/pattern labelurls: the list of URLs that match the current filter and time rangerange: the normalized start/end range used by the server
Data Model
request_audit_rel (per-request)
Created by request_audit.install and filled when logging to database is enabled.
Stores:
request_id,path,method- timing breakdown in milliseconds:
total_ms,routing_ms,controller_ms,render_ms,untracked_ms
- DB timing breakdown:
db_total_ms,db_select_ms,db_write_ms
timestamp
request_audit_latency_agg (aggregated)
Stores aggregated latency per:
pathbucket_start/bucket_end(UTC buckets)
Fields include:
request_countsum_latency_msavg_latency_mserrors
Bucketing is done in the event subscriber with 5-minute UTC buckets.
Architecture Notes
Core logic lives in:
Drupal\request_audit\EventSubscriber\RequestTimingSubscriber
It subscribes to Kernel events:
REQUESTCONTROLLERVIEWRESPONSETERMINATE
Key behaviors:
- Generates a request id from
X-Request-Idor viarandom_bytes(). - When enabled and
database_logis checked, starts Drupal DB query logging usingDatabase::startLog(). - On terminate:
- analyzes logged queries
- stores per-request data into
request_audit_rel - updates aggregated bucket rows in
request_audit_latency_agg
The chart UI JS lives in:
js/request_audit_charts.js
It is declared in:
request_audit.libraries.yml
and includes:
- Chart.js
- Chart.js zoom plugin
- Chart.js date adapter
Frontend behavior
The chart page uses a Drupal behavior that:
- initializes the chart only once
- creates the canvas dynamically if needed
- supports auto-refresh every configured interval
- stores the current zoom range in the URL query string
- reloads the chart and the URL table after zooming
- allows zoom reset with a dedicated button
URL synchronization
The current state is written to the browser URL using query parameters:
patternwindowMinutesbucketMinutesstartend
This allows reloading the page while preserving the selected range.
Uninstallation
On module uninstall, request_audit_uninstall() drops:
request_audit_relrequest_audit_latency_agg
Maintainers
Current maintainers for Drupal 10:
- Pedro Peláez (psf_) - https://www.drupal.org/u/psf_