content_telemetry
Content Telemetry & Performance Insights (CTPI) gives you always-on,
request-level performance telemetry for your Drupal site — with no external services,
no JavaScript trackers, no PII, and no ongoing costs. All data stays inside your
database.
What it does
CTPI instruments every page request at the PHP level. It records render time, DB time,
cache-hit ratio, and entity metadata, then aggregates that data hourly and daily via
Drupal cron. From those aggregates it derives deterministic, rule-based performance
insights and surfaces them in a purpose-built admin UI.
Reports and UI
-
Dashboard (
admin/reports/content-telemetry) — site-wide
health score (0–100), per-entity health badges, trend pill indicators
(↑ Rising / ↑ Critical / → Stable), and an insight panel. -
Per-node performance tab (
/node/{id}/performance) —
24-hour sparkline chart, health score badge, metric tiles (avg render, max render,
avg DB time, cache-hit ratio), and a full insight panel per node. -
Route performance report — all tracked routes with mini sparklines,
status badges, avg/max render times, and drilldown links. -
Route drilldown — full 24-hour sparkline, baseline comparison, and
insights for a single route. -
Views performance report — all tracked Views displays with render
metrics and edit links. -
View drilldown — block-level breakdown showing each block's share of
the view's render time. -
Block performance report — all tracked blocks with human-readable
names, type labels, CRC32 IDs, and render metrics. -
View performance tab (Structure → Views) — sparkline and render stats
inline in the Views admin UI. -
Block performance tab (Structure → Block layout) — per-block
performance metrics. -
Settings form (
admin/config/system/content-telemetry) —
configure sampling rate, force-sample toggle, render budget, and all insight-rule
thresholds.
Insight engine
Six deterministic rules fire when data thresholds are crossed (all thresholds are
configurable):
- PerformanceBudgetRule — avg render ≥ configured budget (warn); ≥ 2× budget (critical)
- HighDbRatioRule — DB time as a % of total render exceeds threshold
- LowCacheHitRule — cache-hit ratio below threshold
- RegressionRule — 24h avg render has increased vs. 7-day baseline by more than the configured %
- HeavyBlockDominanceRule — a single block accounts for more than 30% of page render time
- GlobalSlowBlockRule — a block is slow (avg > 500 ms) across 3 or more routes
Each insight carries a severity (warn or poor) and contributes to a
health score. The score deducts 15 points per warn and 30 points per poor, clamped at 0.
Labels: Good (80–100) · Needs attention (50–79) ·
Critical (0–49).
JSON Insight API
Two JSON endpoints are available to authenticated users with the
view content telemetry permission:
GET /api/content-telemetry/insights/{entity_type}/{entity_id}GET /api/content-telemetry/insights/dashboard
Responses carry Cache-Control: no-store, private and include
health_score, health_label, insight_count, and
a full insights array. Useful for monitoring scripts and CI health checks.
Data model
- Three database tables: raw hourly samples, hourly aggregates, daily aggregates.
- All reporting reads from aggregate tables — never from the raw table.
- Raw data retention: 14 days.
- Aggregation runs via Drupal cron (hourly rollup, daily rollup).
- Insert-only raw table — no locks, no runtime aggregation.
Requirements
- Drupal 10 or 11
- PHP 8.1+
- Core modules: Node, Views, System
Installation
composer require drupal/content_telemetry drush en content_telemetry -y drush updb -y drush cr
Set sampling rate to 100% and enable force sample at
admin/config/system/content-telemetry for local testing. In production,
leave the default 5% sampling rate to minimise overhead.
Code quality
120 tests / 285 assertions · PHPStan Level 6 · PHPCS Drupal +
DrupalPractice · GitLab CI pipeline on every push · strict types throughout ·
zero deprecation warnings.