Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Prometheus Laravel Package

spatie/laravel-prometheus

Export Laravel app metrics to Prometheus via a /prometheus endpoint. Register custom gauges and counters in code, with built-in metrics for queues and Horizon. Includes optional security so your metrics aren’t publicly exposed; pair with Grafana for dashboards.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-prometheus
    

    Publish the config file:

    php artisan vendor:publish --provider="Spatie\Prometheus\PrometheusServiceProvider"
    
  2. Register Middleware (if needed): Add Spatie\Prometheus\Middleware\PrometheusMiddleware to your app/Http/Kernel.php under $middleware or $middlewareGroups['web'].

  3. Basic Metric Exposure: Add a route in routes/web.php:

    use Spatie\Prometheus\Facades\Prometheus;
    
    Prometheus::addGauge('user.count')
        ->value(fn() => \App\Models\User::count());
    
    Route::get('/prometheus', [\Spatie\Prometheus\Http\Controllers\PrometheusController::class, 'metrics']);
    
  4. Prometheus Configuration: Configure your Prometheus server (prometheus.yml) to scrape your Laravel app:

    scrape_configs:
      - job_name: 'laravel_app'
        scrape_interval: 15s
        static_configs:
          - targets: ['your-app-url:8000']
    

First Use Case: Monitoring API Requests

Track HTTP request counts and durations:

Prometheus::addCounter('http.requests.total')
    ->labels(['method', 'endpoint'])
    ->increment();

Prometheus::addHistogram('http.request.duration.seconds')
    ->labels(['endpoint'])
    ->observe($durationInSeconds);

Implementation Patterns

Core Workflows

1. Metric Types and Usage

  • Gauges: Track real-time values (e.g., active users, cache size).
    Prometheus::addGauge('cache.size')
        ->value(fn() => Cache::getStore()->getSize());
    
  • Counters: Increment-only metrics (e.g., API calls, errors).
    Prometheus::addCounter('api.errors')
        ->increment();
    
  • Histograms: Measure distributions (e.g., request latency).
    Prometheus::addHistogram('request.latency')
        ->observe($executionTime);
    
  • Summaries: Track percentiles (e.g., response times).
    Prometheus::addSummary('response.time')
        ->observe($responseTime);
    

2. Labels for Context

Add dimensions to metrics for granularity:

Prometheus::addCounter('database.queries')
    ->labels(['connection' => 'mysql', 'type' => 'select'])
    ->increment();

3. Conditional Metrics

Use the Conditionable trait for dynamic metrics:

Prometheus::addGauge('active.users')
    ->when(fn() => auth()->check(), fn() => auth()->user()->active ? 1 : 0);

4. Queue Monitoring

Leverage built-in collectors for Laravel Queues/Horizon:

// Auto-registered via config (enabled by default)
Prometheus::collectors()->addQueueCollectors();

5. Middleware Integration

Track requests globally:

// app/Http/Middleware/TrackRequests.php
public function handle($request, Closure $next) {
    $start = microtime(true);
    $response = $next($request);
    $duration = microtime(true) - $start;

    Prometheus::addHistogram('http.request.duration')
        ->labels(['method' => $request->method(), 'path' => $request->path()])
        ->observe($duration);

    return $response;
}

Advanced Patterns

1. Custom Collectors

Extend functionality by creating custom collectors:

use Spatie\Prometheus\Collectors\Collector;

class DatabaseCollector extends Collector {
    public function collect(): array {
        $queries = DB::getQueryLog();
        return [
            'db_queries_total' => count($queries),
            'db_queries_duration_seconds_sum' => array_sum(array_column($queries, 'time')),
        ];
    }
}

// Register in a service provider:
Prometheus::collectors()->add(new DatabaseCollector());

2. Dynamic Metric Registration

Register metrics dynamically (e.g., per-model):

// app/Providers/AppServiceProvider.php
public function boot() {
    foreach (Model::allModels() as $model) {
        Prometheus::addGauge("models.{$model}.count")
            ->value(fn() => $model::count());
    }
}

3. Rate Limiting Metrics

Track rate limits:

Prometheus::addCounter('rate.limit.hits')
    ->labels(['endpoint' => 'api/auth'])
    ->increment();

Prometheus::addCounter('rate.limit.rejected')
    ->labels(['endpoint' => 'api/auth'])
    ->when(fn() => $this->isRateLimited(), fn() => 1);

4. Health Checks

Expose health metrics:

Prometheus::addGauge('system.health')
    ->value(fn() => app()->isDownForMaintenance() ? 0 : 1);

5. Integration with Laravel Events

React to events and update metrics:

// app/Providers/EventServiceProvider.php
protected $listen = [
    'eloquent.created' => [function ($model) {
        Prometheus::addCounter('models.created')
            ->labels(['model' => class_basename($model)])
            ->increment();
    }],
];

Gotchas and Tips

Common Pitfalls

  1. Metric Naming Collisions:

    • Use consistent naming conventions (e.g., namespace_metric_type_metric_name).
    • Avoid spaces or special characters; use underscores (_) or dots (.).
  2. Performance Overhead:

    • Issue: Frequent database queries in metric values can slow down the /prometheus endpoint.
    • Fix: Cache values or use lightweight queries:
      Prometheus::addGauge('user.count')
          ->value(fn() => Cache::remember('user_count', 60, fn() => User::count()));
      
  3. Label Cardinality Explosion:

    • Issue: Too many unique label combinations can bloat Prometheus.
    • Fix: Limit labels to essential dimensions (e.g., avoid per-user labels unless necessary).
  4. Middleware Misconfiguration:

    • Issue: Forgetting to add PrometheusMiddleware can expose metrics without security.
    • Fix: Always register middleware in app/Http/Kernel.php:
      protected $middleware = [
          // ...
          \Spatie\Prometheus\Middleware\PrometheusMiddleware::class,
      ];
      
  5. Queue Collector Conflicts:

    • Issue: Running multiple queue workers with the same collector can cause race conditions.
    • Fix: Disable duplicate collectors in config:
      'collectors' => [
          'queue' => [
              'enabled' => env('QUEUE_COLLECTOR_ENABLED', false),
          ],
      ],
      
  6. Prometheus Scrape Timeouts:

    • Issue: Slow metric collection can cause Prometheus to time out.
    • Fix: Optimize collectors or increase scrape timeout in Prometheus config:
      scrape_configs:
        - scrape_timeout: 30s
      

Debugging Tips

  1. Inspect Metrics Locally: Visit /prometheus in your browser to see raw metrics before configuring Prometheus.

  2. Check Collector Registration: Debug collectors with:

    dd(\Spatie\Prometheus\Facades\Prometheus::collectors()->all());
    
  3. Log Metric Updates: Enable debug logging in config/prometheus.php:

    'debug' => env('PROMETHEUS_DEBUG', false),
    
  4. Validate Prometheus Configuration: Use promtool check config prometheus.yml to validate your Prometheus config.

  5. Monitor Scraping: Check Prometheus targets page (http://prometheus-server:9090/targets) for failed scrapes.


Configuration Quirks

  1. Security:

    • Default: The /prometheus endpoint is public. Always secure it:
      // config/prometheus.php
      'middleware' => ['throttle:60,1'],
      
    • For private networks, use IP whitelisting:
      'middleware' => ['Spatie\Prometheus\Middleware\TrustProxies'],
      
  2. Collector Registry Wiping:

    • Config: Control whether the registry is wiped on each request:
      'wipe_collector_registry' => env('PROMETHEUS_WIPE_REGISTRY', true),
      
    • Set to false if you want metrics to persist across requests (e.g., for counters).
  3. Custom Endpoint Path: Change the default /prometheus path:

    'route' => [
        'path' => 'metrics',
        'middleware' => [],
    ],
    
  4. Prometheus Client Configuration: Customize the Prometheus client (e.g., namespace):

    'client
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony