prismamedia/metrics
Prismamedia Metrics is a Laravel package for capturing and querying application metrics. Define named metrics, record values from your app, and retrieve aggregated time-series data through a simple, Eloquent-friendly API—no external monitoring service required.
prismamedia/metrics is a framework-agnostic PHP metrics abstraction: you call a small interface (counters, gauges, timings) and swap the backend adapter underneath without touching call sites. v2.1.0 is an infrastructure release — it adds Symfony 7 compatibility and expands the PHP test matrix. That matters directly for Laravel developers: Laravel 11 ships on Symfony 7 components, so v2.1.0 is the first release you can install cleanly in a modern Laravel app without constraint conflicts.
Minimal steps:
composer require prismamedia/metrics:^2.1 — pin the minor, since ^2.0 will not guarantee the relaxed Symfony constraint.symfony/* conflict, re-run composer update prismamedia/metrics --with-dependencies and confirm with composer why-not prismamedia/metrics 2.1.0.AppServiceProvider::register() as a singleton and inject the interface, not the concrete client.First use case: instrument a single controller and a single queued job. Add a counter for requests by status code and a timing around the handler, then look at the numbers in your backend before instrumenting anything else. Metrics you don't read are just latency.
Service container wiring. The package predates Laravel and has no Laravel service provider, so you own the binding. Build the client from config('metrics.*') in a dedicated MetricsServiceProvider, bind it as a singleton, and bind the interface to it so tests can swap the implementation. Register it late enough that config is available, but early enough that middleware and jobs resolve it.
Environment-driven adapter selection. Use the Null adapter (or an in-memory fake) for local and testing, and the real backend only in staging/production. This keeps dev machines from emitting garbage into shared dashboards and keeps your test suite from opening sockets.
Middleware for request-level metrics. A single terminable middleware covers most of your needs: start a timer in handle(), and in terminate() emit the duration plus a counter tagged by HTTP status. Use terminate() rather than the end of handle() so the measurement includes response delivery and doesn't sit on the critical path.
Queue instrumentation via events. Rather than editing every job, listen to JobProcessing/JobProcessed/JobFailed and derive counters and timings from the event payload. Key by job class name, never by job ID or payload hash — that's how you blow up cardinality in one deploy.
Timer discipline. Wrap external calls (HTTP, Redis, third-party APIs) in try/finally so failures still record a duration, and tag failures with an explicit outcome dimension rather than letting them look like slow successes. If the package's timer returns a duration, normalise units at the call site — mixing milliseconds and seconds across a codebase is the most common source of "the graph is wrong" bug reports.
Decorator for testability. Wrap the package client in a thin App\Metrics\Metrics class exposing only the methods you use. That gives you one place to enforce naming conventions, add default tags, swallow adapter exceptions, and swap to an in-memory recorder in tests without the package's own fakes.
symfony/* at 6.x.Metrics::increment() in Blade or quick scripts; resolve the interface out of the container so the decorator and test swaps keep working.php artisan config:cache bakes it in — changing METRICS_* env values requires a re-cache in deployed environments.How can I help you explore Laravel packages today?