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

Prometheus Client Php Laravel Package

promphp/prometheus_client_php

Prometheus client library for PHP with counters, gauges, histograms, and summaries. Supports Redis, Predis, APCu/APCng, or in-memory storage for metric aggregation across workers, with simple APIs to register, update, and expose metrics for scraping.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require promphp/prometheus_client_php
    
  2. Choose a storage adapter (Redis recommended for production):

    // Redis (default)
    $registry = \Prometheus\CollectorRegistry::getDefault();
    
    // In-Memory (for testing)
    $registry = new \Prometheus\CollectorRegistry(new \Prometheus\Storage\InMemory());
    
  3. Instrument a simple metric (e.g., HTTP request counter):

    $counter = $registry->getOrRegisterCounter(
        'http', 'requests_total', 'Total HTTP requests', ['method', 'path']
    );
    $counter->inc(['method' => 'GET', 'path' => '/api/users']);
    
  4. Expose metrics endpoint (e.g., /metrics):

    $renderer = new \Prometheus\RenderTextFormat();
    echo $renderer->render($registry->getMetricFamilySamples());
    

First Use Case: Tracking API Requests

// In your Laravel middleware or controller
$counter = \Prometheus\CollectorRegistry::getDefault()
    ->getOrRegisterCounter(
        'api', 'requests_total', 'Total API requests', ['method', 'endpoint']
    );

// Increment on request
$counter->inc([
    'method' => request()->method(),
    'endpoint' => request()->path()
]);

Implementation Patterns

Core Workflows

1. Metric Registration & Usage

// Register once (e.g., in Service Provider)
$registry = \Prometheus\CollectorRegistry::getDefault();

// Counter for failed jobs
$failedJobs = $registry->getOrRegisterCounter(
    'jobs', 'failed_total', 'Total failed jobs', ['queue', 'job']
);

// Gauge for active workers
$activeWorkers = $registry->getOrRegisterGauge(
    'workers', 'active', 'Number of active workers', ['type']
);

2. Laravel Integration

  • Service Provider Bootstrapping:

    public function boot()
    {
        $this->app->singleton('prometheus.registry', function () {
            return new \Prometheus\CollectorRegistry(
                new \Prometheus\Storage\Redis()
            );
        });
    }
    
  • Middleware for Automatic Metrics:

    public function handle($request, Closure $next)
    {
        $start = microtime(true);
        $response = $next($request);
    
        $duration = microtime(true) - $start;
        $registry = app('prometheus.registry');
    
        $registry->getOrRegisterHistogram(
            'http', 'request_duration_seconds', 'HTTP request latency', ['method', 'path']
        )->observe($duration, [
            'method' => $request->method(),
            'path' => $request->path()
        ]);
    
        return $response;
    }
    

3. Label Strategies

  • Dynamic Labels:

    $counter = $registry->getOrRegisterCounter(
        'db', 'queries_total', 'Total DB queries', ['connection', 'query_type']
    );
    
    // In query builder
    $counter->inc([
        'connection' => DB::connection()->getName(),
        'query_type' => 'select'
    ]);
    
  • Constant Labels:

    $counter = $registry->getOrRegisterCounter(
        'app', 'deployments_total', 'App deployments', ['environment']
    );
    $counter->inc(['environment' => config('app.env')]);
    

4. Batch Processing

// For cron jobs or batch operations
$registry = new \Prometheus\CollectorRegistry(new \Prometheus\Storage\Redis());
$counter = $registry->getOrRegisterCounter(
    'batch', 'processed_items', 'Items processed in batch'
);

// Process items...
foreach ($items as $item) {
    $counter->inc();
    // Process $item
}

5. Custom Collectors

// Extend Collector for custom logic
class DatabaseCollector extends \Prometheus\Collector
{
    public function collect()
    {
        $queries = DB::select('SELECT COUNT(*) FROM queries');
        $this->metrics['queries_total'] = (int) $queries[0]->{'COUNT(*)'};
    }
}

// Register in registry
$registry->registerCollector(new DatabaseCollector());

Advanced Patterns

1. Histogram Buckets

// Exponential buckets for latency metrics
$latency = $registry->getOrRegisterHistogram(
    'http', 'response_time_seconds',
    'HTTP response time in seconds',
    ['endpoint'],
    \Prometheus\Histogram::exponentialBuckets(0.05, 2, 10) // 10 buckets
);

// Observe in middleware
$latency->observe($duration, ['endpoint' => $request->path()]);

2. Summary Quantiles

// Track percentiles for API response times
$summary = $registry->getOrRegisterSummary(
    'api', 'response_time_seconds',
    'API response time summary',
    ['endpoint'],
    60, // max age in seconds
    [0.5, 0.9, 0.95, 0.99] // quantiles
);

// Observe in middleware
$summary->observe($duration, ['endpoint' => $request->path()]);

3. Conditional Metrics

// Track only failed requests
if ($response->isClientError() || $response->isServerError()) {
    $errors->inc([
        'method' => $request->method(),
        'status' => $response->status()
    ]);
}

4. Metric Aggregation

// Track per-user metrics
$userId = auth()->id();
$counter = $registry->getOrRegisterCounter(
    'user', 'actions_total', 'User actions', ['user_id', 'action']
);

// Increment with user context
$counter->inc(['user_id' => $userId, 'action' => 'login']);

5. Health Checks

// Track service health
$health = $registry->getOrRegisterGauge(
    'service', 'health', 'Service health status', ['component']
);

// Update in health check endpoint
$health->set(1, ['component' => 'database']); // 1 = healthy

Gotchas and Tips

Common Pitfalls

1. Storage Adapter Issues

  • Redis Connection Drops:

    • Ensure Redis is running and accessible.
    • Configure timeouts:
      \Prometheus\Storage\Redis::setDefaultOptions([
          'timeout' => 0.5, // Lower for faster failures
          'read_timeout' => 2.0
      ]);
      
    • Use Predis for better connection handling:
      $client = new \Predis\Client(['scheme' => 'tcp', 'host' => 'redis', 'port' => 6379]);
      $registry = new \Prometheus\CollectorRegistry(
          \Prometheus\Storage\Predis::fromExistingConnection($client)
      );
      
  • APCu Memory Limits:

    • APCu may evict metrics if memory is low. Monitor with:
      apcu_cache_info()
      
    • Increase apc.shm_size in php.ini if needed.

2. Label Value Quirks

  • Non-String Labels:
    • All label values must be strings. Convert numeric/boolean values:
      $counter->inc(['status' => (string) $response->status()]);
      
  • Empty Labels:
    • Avoid empty label values (Prometheus may reject them).

3. Metric Naming

  • Reserved Prefixes:
    • Avoid names starting with __ (reserved by Prometheus).
  • Length Limits:
    • Metric names: ≤ 200 chars.
    • Label names: ≤ 100 chars.
    • Label values: ≤ 200 chars.

4. Concurrency Issues

  • Race Conditions:
    • Redis/Predis adapters handle concurrency well.
    • APCu/APCng may have race conditions in high-concurrency scenarios.
    • For critical paths, use Redis or Predis.

5. Floating-Point Precision

  • Gauge/Histogram Values:
    • Prometheus expects floats with ≤ 3 decimal places for precision.
    • Use round($value, 3) if needed.

Debugging Tips

1. Metric Not Found

  • Error: MetricNotFoundException
    • Cause: Trying to access a metric that doesn’t exist.
    • Fix: Use getOrRegister* to auto-create metrics:
      $counter = $registry->getOrRegisterCounter('namespace', 'name', 'desc');
      

2. Redis Serialization Errors

  • Error: RedisException with JSON decode errors.
    • Cause: Corrupted Redis data or schema changes.
    • Fix:
      • Clear Redis:
        redis-cli FLUSHDB
        
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.
croct/coding-standard
croct/plug-php
nqxcode/phpmorphy
boundwize/pyrameter
testo/facade
headercat/phpstan-extension-ide-helper
develia/commons
dmstr/symfony-system-resources-bundle
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
renatomarinho/laravel-page-speed
develia/geo-bundle
austinheap/laravel-database-encryption
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable