spatie/laravel-prometheus
Export Laravel app metrics to Prometheus via a /prometheus endpoint. Register custom gauges/counters with simple callbacks, use built-in queue and Horizon metrics, and optionally secure the endpoint. Ideal for scraping by Prometheus and charting in Grafana.
Installation:
composer require spatie/laravel-prometheus
Publish the config file:
php artisan vendor:publish --provider="Spatie\Prometheus\PrometheusServiceProvider"
Configuration:
Edit config/prometheus.php to define:
host (default: 127.0.0.1)port (default: 9256)metrics (enabled/disabled metrics like laravel, queue, cache, etc.)First Use Case: Start the Prometheus server:
php artisan prometheus:server
Access metrics at http://localhost:9256/metrics. Verify Laravel-specific metrics (e.g., laravel_request_duration_seconds) appear in the output.
config/prometheus.php (toggle metrics, adjust endpoints)./metrics (validate data exposure).Default Metrics: Automatically exposes:
laravel_routes_count).Custom Metrics:
Use the PrometheusRegistrar facade to define custom metrics:
use Spatie\Prometheus\Facades\PrometheusRegistrar;
PrometheusRegistrar::gauge('my_app.custom_metric', 'Custom metric description');
PrometheusRegistrar::set('my_app.custom_metric', 42);
Register custom metrics in a service provider’s boot() method.
Conditional Metrics:
Disable metrics in config/prometheus.php for performance-sensitive environments:
'metrics' => [
'laravel' => env('APP_ENV') !== 'production',
'queue' => true,
],
Integration with Monitoring Tools:
/metrics endpoint.Dynamic Metrics: Track dynamic values (e.g., user-specific metrics) using labels:
PrometheusRegistrar::gauge('user_activity', 'User activity count', ['user_id']);
PrometheusRegistrar::set('user_activity', ['user_id' => 123], 10);
Middleware for Request Metrics: Extend request tracking with middleware:
public function handle($request, Closure $next) {
$start = microtime(true);
$response = $next($request);
$duration = microtime(true) - $start;
PrometheusRegistrar::histogram('custom_request_duration_seconds')
->labels(['route' => $request->route()->getName()])
->observe($duration);
return $response;
}
Health Checks:
Expose a /health endpoint alongside /metrics to validate Prometheus connectivity:
Route::get('/health', function () {
return response()->json(['status' => 'ok']);
});
Environment-Specific Config:
Use environment variables to toggle metrics in .env:
PROMETHEUS_ENABLED=true
PROMETHEUS_METRICS="laravel,queue"
Then reference in config/prometheus.php:
'enabled' => env('PROMETHEUS_ENABLED', true),
'metrics' => explode(',', env('PROMETHEUS_METRICS', 'laravel,queue,cache')),
Port Conflicts:
9256 may clash with other services. Change in config/prometheus.php:
'port' => env('PROMETHEUS_PORT', 9257),
sudo ufw allow 9257
Performance Overhead:
htop or docker stats).Metric Naming Collisions:
laravel_ or prometheus_ to prevent conflicts with built-in metrics.myapp_custom_metric).Prometheus Scraping Issues:
/metrics endpoint (check CORS, auth, or network policies).curl http://localhost:9256/metrics
Log Metric Updates:
Enable debug logging in config/prometheus.php:
'debug' => env('APP_DEBUG', false),
Check storage/logs/laravel.log for metric-related entries.
Validate Metric Exposure:
Use curl to inspect raw metrics:
curl -v http://localhost:9256/metrics | grep "laravel_"
Prometheus Configuration:
Validate prometheus.yml targets:
scrape_configs:
- job_name: 'laravel'
static_configs:
- targets: ['laravel-app:9256']
Restart Prometheus after changes:
prometheus --config.file=prometheus.yml
Custom Metric Types:
Extend beyond gauges/histograms by implementing Spatie\Prometheus\Metric\MetricInterface:
class CustomCounter implements MetricInterface {
public function collect(): string { /* ... */ }
}
Register via PrometheusRegistrar::registerMetric().
Dynamic Metric Labels: Use closures for dynamic labels:
PrometheusRegistrar::gauge('dynamic_metric', function () {
return ['user_id' => auth()->id()];
});
Prometheus Server Hooks: Override the server boot process in a service provider:
public function boot() {
$this->app->make(Spatie\Prometheus\PrometheusServiceProvider::class)
->registerServer(function ($server) {
$server->addCollector(new CustomCollector());
});
}
Metric Aggregation:
Use Prometheus’s built-in functions (sum, avg) to aggregate custom metrics in queries:
sum(laravel_request_duration_seconds_bucket{le="0.5"}) by (route)
Environment Variables:
Prefix config keys with PROMETHEUS_ for clarity:
PROMETHEUS_HOST=0.0.0.0
PROMETHEUS_PORT=9256
Access in config:
'host' => env('PROMETHEUS_HOST', '127.0.0.1'),
Docker Integration:
Expose the port in docker-compose.yml:
services:
laravel:
ports:
- "9256:9256"
Use links or Docker networks for Prometheus-Laravel communication.
Queue Worker Metrics:
Ensure queue workers are running with the same Laravel environment (e.g., same .env) to expose consistent metrics.
Caching Metrics:
Disable caching for /metrics in routes/web.php:
Route::get('/metrics', function () {
return Spatie\Prometheus\Facades\PrometheusRegistrar::metrics();
})->middleware('throttle:60,1'); // Limit scraping rate
How can I help you explore Laravel packages today?