cboxdk / laravel-telemetry
Collector-free telemetry for Laravel: Prometheus metrics, OTLP traces and events. No C extension, no protobuf, no sidecar — metrics that actually work under FPM.
Requires
- php: ^8.3|^8.4|^8.5
- illuminate/contracts: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- cboxdk/system-metrics: ^3.0
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
Suggests
- ext-apcu: Required when using the apcu metric store.
- ext-redis: Recommended when using the redis metric store (phpredis).
- cboxdk/system-metrics: Host CPU/memory/load metrics via the built-in provider AND real per-request/per-job process footprint (peak RSS, CPU utilization) on spans.
This package is auto-updated.
Last update: 2026-07-03 10:40:28 UTC
README
Collector-free telemetry for Laravel: Prometheus metrics, OTLP traces and events. No C extension, no protobuf, no sidecar — metrics that actually work under FPM.
Telemetry::counter('orders.created')->inc(); Telemetry::gauge('queue.depth', fn () => Queue::size()); Telemetry::histogram('checkout.duration', unit: 'ms')->record($ms); Telemetry::span('import.customers', function () { // traced work — exceptions recorded, duration measured }); Telemetry::event('autoscale.decision', ['workers' => 7]);
Why
PHP is shared-nothing: in-process metric state dies with the request, which is why the official OTel SDK's metrics don't work under FPM without a collector. This package aggregates metrics in Redis (or APCu) instead — web workers, queue workers and nodes all write to the same series. Prometheus scrapes a route; traces and events go straight to any OTLP backend as spec-stable HTTP JSON.
- ✅ Pure Composer package — deploys anywhere Laravel runs
- ✅ Prometheus scrape endpoint(s) with IP allowlisting and metric filters
- ✅ Real OTLP (
/v1/traces,/v1/metrics,/v1/logs) without the SDK - ✅
telemetrylog channel: Laravel logs become trace-correlated OTLP log records (severity-mapped, feedback-loop safe) - ✅ Auto-instrumentation: requests, queue jobs (full W3C trace propagation
into workers), DB queries, commands — plus
Http::withTraceparent()for outbound calls - ✅
Telemetry::fake()with assertions for counters, gauges, histograms, spans and events - ✅ Provider contract so packages publish telemetry without coupling
- ✅ Host CPU/memory/load via
cboxdk/system-metrics— just install it - ✅ Zero cost when disabled; telemetry never throws into your app
- ✅ Resource attribution: peak memory + CPU per request/job/task, per-span
CPU & memory deltas, real RSS via
cboxdk/system-metrics - ✅ Ships 13 Grafana dashboards (
telemetry:dashboards) — an APM-style suite (requests, jobs, queries, cache, exceptions, system, users …) — service-scoped, LGTM-ready - ✅ AI-ready: ships Laravel Boost
guidelines,
llms.txtand an agent guide — your AI assistant follows the conventions out of the box
Installation
composer require cboxdk/laravel-telemetry
TELEMETRY_STORE=redis # redis | apcu | array TELEMETRY_EXPORTERS=otlp # optional; Prometheus endpoint is on by default TELEMETRY_OTLP_ENDPOINT=https://otlp.example.com:4318
Scrape GET /telemetry/metrics, and for OTLP metrics schedule the flush:
Schedule::command('telemetry:flush')->everyMinute()->onOneServer();
Documentation
Full documentation lives in docs/:
- Getting started — quickstart, testing, API reference, AI assistants
- Core concepts — metrics, traces, events, logs, naming
- Cookbook — multi-tenant SaaS, queue monitoring, external services
- Configuration reference
- Extension points — custom exporters
- Production — OTLP, the recommended Grafana stack, performance, security
Design decisions (and the prior-art survey behind them) are recorded in
docs/adr/.
Publishing telemetry from your package
if (class_exists(\Cbox\Telemetry\Facades\Telemetry::class)) { Telemetry::provider(new QueueMetricsProvider); }
Telemetry never knows about your package — your package publishes telemetry if telemetry exists. See providers.
Development
composer check # pint --test, phpstan (level 8), pest
License
MIT. See LICENSE.md.