BlogPHP Monitoring Guide
Staff Pick

📡 Monitor your APIs — know when they go down before your users do

Better Stack checks uptime every 30 seconds with instant Slack, email & SMS alerts. Free tier available.

Start Free →

Affiliate link — we may earn a commission at no extra cost to you

PHP Monitoring Guide: Laravel, Metrics, Errors & APM Tools (2026)

PHP powers 77% of the web. Here is a complete guide to monitoring PHP and Laravel applications in 2026 — from basic uptime checks to full-stack observability with Prometheus, Sentry, and APM tracing.

Updated: May 2026·15 min read

Why PHP Monitoring Is Different

PHP applications have unique monitoring challenges compared to languages like Go or Java. The shared-nothing architecture means PHP has no persistent memory between requests — every request spins up a fresh process. There is no long-lived application state to watch. Instead, you need to monitor:

The good news: because PHP is stateless, individual request failures don't cascade. The bad news: detecting slow memory leaks, OPcache thrashing, or FPM pool exhaustion requires explicit instrumentation.

📡
Recommended

Monitor Your PHP & Laravel App

Better Stack monitors your PHP application endpoints, sends alerts on downtime or slowness, and aggregates logs from PHP-FPM and nginx. Works with any PHP stack in minutes.

Try Better Stack Free →

Layer 1: Uptime & HTTP Monitoring

Start with basic external monitoring before building internal metrics. An external uptime monitor tells you when your PHP app is unreachable from users' perspectives — independent of what your internal metrics say.

Health Check Endpoint

Add a /health endpoint that checks critical dependencies:

// routes/web.php (Laravel)
Route::get('/health', function () {
    $checks = [];

    // Database check
    try {
        DB::connection()->getPdo();
        $checks['database'] = 'ok';
    } catch (\Exception $e) {
        $checks['database'] = 'error';
    }

    // Redis check
    try {
        Cache::store('redis')->get('health_check');
        $checks['redis'] = 'ok';
    } catch (\Exception $e) {
        $checks['redis'] = 'error';
    }

    // Queue check (optional)
    $checks['queue'] = Queue::size() < 1000 ? 'ok' : 'degraded';

    $status = in_array('error', $checks) ? 503 : 200;

    return response()->json([
        'status' => $status === 200 ? 'ok' : 'degraded',
        'checks' => $checks,
        'timestamp' => now()->toIso8601String(),
    ], $status);
});

Point your uptime monitor at this endpoint. Configure alerts for any non-200 response or response time >500ms.

Layer 2: PHP-FPM & Server Metrics

PHP-FPM has a built-in status page that exposes pool metrics. Enable it in your FPM pool config:

; /etc/php/8.3/fpm/pool.d/www.conf
pm.status_path = /fpm-status
ping.path = /fpm-ping

; Pool sizing — tune based on your server's RAM
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500  ; Restart workers after N requests to prevent memory leaks

Key PHP-FPM metrics to watch at nginx_host/fpm-status:

MetricWhat to WatchAlert Threshold
active processesRequests being processed right nowAlert if active / max_children > 0.8
max children reachedHow often pool was fully saturatedAlert if incrementing (pool too small)
accepted connTotal requests processed (rate)Alert on sudden drops (FPM crashed)
listen queueRequests waiting for an FPM workerAlert if > 0 for more than 30s
slow requestsRequests exceeding request_slowlog_timeoutAlert if rate increasing

OPcache Monitoring

// Expose OPcache stats as JSON endpoint (protect with auth middleware!)
Route::get('/metrics/opcache', function () {
    $status = opcache_get_status(false);
    return response()->json([
        'hit_rate'     => $status['opcache_statistics']['opcache_hit_rate'],
        'memory_usage' => $status['memory_usage']['used_memory'],
        'cached_files' => $status['opcache_statistics']['num_cached_files'],
        'restarts'     => $status['opcache_statistics']['oom_restarts']
                        + $status['opcache_statistics']['hash_restarts'],
    ]);
})->middleware('auth:sanctum');

OPcache hit rate below 95% indicates memory pressure or too many unique file paths. OPcache restarts (oom_restarts > 0) mean you need to increase opcache.memory_consumption.

📡
Recommended

PHP Log Aggregation Made Simple

Forward PHP error logs, nginx access logs, and Laravel logs to Better Stack Logs. Search across all logs in one place with real-time tail and structured search.

Try Better Stack Free →

Layer 3: Application Metrics with Prometheus

For per-route latency histograms and custom business metrics, use Prometheus instrumentation.

Install Prometheus Client for PHP

composer require promphp/prometheus_client_php

Laravel-Specific: spatie/laravel-prometheus

For Laravel apps, the spatie/laravel-prometheus package is the easiest path:

composer require spatie/laravel-prometheus

# Publish config
php artisan vendor:publish --provider="Spatie\Prometheus\PrometheusServiceProvider"

# This auto-registers /prometheus endpoint
# Add custom gauges in AppServiceProvider:
Prometheus::addGauge('queue_size')
    ->helpText('Current queue depth')
    ->value(fn () => Queue::size());

Prometheus::addGauge('active_users_24h')
    ->helpText('Users active in last 24 hours')
    ->value(fn () => User::where('last_seen_at', '>', now()->subDay())->count());

Middleware for Request Metrics

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

        $route = $request->route()?->getName() ?? 'unknown';
        $status = $response->getStatusCode();
        $method = $request->method();

        // Record request count
        Prometheus::getOrRegisterCounter(
            'http_requests_total',
            'Total HTTP requests',
            ['route', 'method', 'status']
        )->inc([$route, $method, (string) $status]);

        // Record duration histogram
        Prometheus::getOrRegisterHistogram(
            'http_request_duration_seconds',
            'HTTP request duration',
            ['route', 'method'],
            [0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0]
        )->observe($duration, [$route, $method]);

        return $response;
    }
}

Layer 4: Error Tracking

Sentry for PHP/Laravel

Sentry is the standard choice for PHP error tracking. Install and configure in minutes:

composer require sentry/sentry-laravel

# .env
SENTRY_LARAVEL_DSN=https://your-key@sentry.io/your-project

# config/sentry.php — set error sample rates
return [
    'dsn' => env('SENTRY_LARAVEL_DSN'),
    'traces_sample_rate' => 0.1,  // 10% of requests for performance
    'profiles_sample_rate' => 0.1,
];

# bootstrap/app.php (Laravel 11+)
->withExceptions(function (Exceptions $exceptions) {
    $exceptions->report(function (Throwable $e) {
        if (app()->bound('sentry')) {
            \Sentry\captureException($e);
        }
    });
})

Laravel Flare (Laravel-Native Alternative)

Flare integrates deeply with Laravel's Ignition error page for beautiful production error reports:

composer require spatie/laravel-flare

# .env
FLARE_KEY=your-flare-key

# Flare auto-captures: Exceptions, SQL queries on error,
# logs, jobs, and full request context
# No additional configuration required in most Laravel apps

Layer 5: Laravel-Specific Tools

Laravel Telescope (Development & Staging)

Telescope provides an elegant dashboard for debugging in non-production environments:

composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate

# app/Providers/TelescopeServiceProvider.php
Telescope::night();  // Dark mode

# Record only slow queries in production (if you must enable it)
Telescope::filter(function (IncomingEntry $entry) {
    if ($entry->type === EntryType::QUERY) {
        return $entry->content['slow'];  // Only slow queries
    }
    return $this->app->isLocal();
});

Laravel Pulse (Production Monitoring)

Laravel Pulse is the production-ready alternative to Telescope with a much lower overhead:

composer require laravel/pulse
php artisan vendor:publish --provider="Laravel\Pulse\PulseServiceProvider"
php artisan migrate

# routes/web.php — protect the dashboard
Route::middleware(['auth', 'can:viewPulse'])->group(function () {
    Route::get('/pulse', \Laravel\Pulse\Http\Controllers\DashboardController::class);
});

# Pulse tracks: Requests, Slow Requests, Slow DB Queries,
# Queue stats, Cache usage, Exceptions, Server metrics

Laravel Horizon (Queue Monitoring)

composer require laravel/horizon
php artisan horizon:install
php artisan migrate

# Schedule snapshot for historical metrics
// app/Console/Kernel.php (Laravel 10) or routes/console.php (Laravel 11)
Schedule::command('horizon:snapshot')->everyFiveMinutes();

# Key Horizon metrics to alert on:
# - Failed jobs > 0 in last hour → page
# - Queue wait time > 30s → warning
# - Throughput dropping > 50% → warning

Layer 6: Database Query Monitoring

Slow database queries are the #1 source of PHP application performance issues. Laravel makes it easy to detect them:

// AppServiceProvider.php boot() method
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Facades\DB;

// Log slow queries
DB::listen(function (QueryExecuted $query) {
    if ($query->time > 1000) {  // > 1 second
        Log::warning('Slow query detected', [
            'sql'      => $query->sql,
            'bindings' => $query->bindings,
            'time_ms'  => $query->time,
            'url'      => request()->fullUrl(),
        ]);

        // Optionally send to Sentry
        \Sentry\addBreadcrumb(
            category: 'db.query',
            message: 'Slow query: ' . $query->time . 'ms',
            level: 'warning',
        );
    }
});

// Enable query count in staging to catch N+1 problems
if (!app()->isProduction()) {
    DB::enableQueryLog();

    app()->terminating(function () {
        $queryCount = count(DB::getQueryLog());
        if ($queryCount > 50) {
            Log::warning("N+1 suspected: {$queryCount} queries on " . request()->path());
        }
    });
}

Alert Pro

14-day free trial

Stop checking — get alerted instantly

Next time PHP Application goes down, you'll know in under 60 seconds — not when your users start complaining.

  • Email alerts for PHP Application + 9 more APIs
  • $0 due today for trial
  • Cancel anytime — $9/mo after trial

PHP APM Tools Comparison 2026

ToolBest ForPHP SupportPrice
Blackfire.ioPerformance profiling & CI integrationExcellent — PHP-nativeFrom $24/mo
TidewaysProduction PHP profiling & APMExcellent — PHP-focusedFrom $19/mo
Datadog APMEnterprise full-stack observabilityGood auto-instrumentation$31/host/mo+
New RelicMature APM with long historyGood PHP agentFree up to 100GB/mo
Scout APMSimple developer-friendly APMLaravel-native packageFree tier, $19.99/mo
OpenTelemetryOpen-source, any backendGood, improving in 2026Free (self-hosted)
Sentry PerformanceCombined errors + tracesGood, built into SDKFree tier, $26/mo+

Recommendation: For most Laravel apps, start with Scout APM (free tier, Laravel package) for application-level traces and Sentry for error tracking. Add Blackfire.io if you need deep profiling for performance optimization. Graduate to Datadog when you need enterprise-grade observability across multiple services.

OpenTelemetry for PHP (2026)

OpenTelemetry's PHP SDK has matured significantly and is now a viable option for teams wanting vendor-neutral tracing:

composer require open-telemetry/sdk \
  open-telemetry/exporter-otlp \
  open-telemetry/opentelemetry-auto-laravel

# config/otel.php (or .env)
OTEL_PHP_AUTOLOAD_ENABLED=true
OTEL_SERVICE_NAME=my-laravel-app
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=0.1  # 10% sampling

# The laravel instrumentation auto-instruments:
# - HTTP requests
# - Database queries (PDO)
# - Cache operations
# - Queue jobs

Essential PHP Monitoring Alerts

Critical
PHP-FPM Pool Saturation
Condition: active_processes / pm.max_children > 0.85 for 2 min
Increase pm.max_children or scale horizontally
High
High PHP Error Rate
Condition: Error rate > 1% of requests for 5 min
Check Sentry/Flare for exception details, check logs
High
Slow Response Time
Condition: P95 response time > 2s for 5 min
Check slow query log, Blackfire profile, DB connection pool
Warning
OPcache Miss Rate
Condition: OPcache hit rate < 95% sustained
Increase opcache.memory_consumption in php.ini
High
Queue Depth Growing
Condition: Queue depth increasing for 10+ min without processing
Check Horizon dashboard — workers may have crashed
Critical
Failed Jobs Spike
Condition: Failed job count > 0 in last 5 min
Review failed job reason in Horizon or queue:failed
Critical
Database Connection Pool Exhaustion
Condition: PDO exceptions with "too many connections" in logs
Check DB::getConnections(), increase max_connections, add PgBouncer/ProxySQL

Frequently Asked Questions

How do I add Prometheus metrics to a PHP application?

Use the promphp/prometheus_client_php library. Install via Composer: composer require promphp/prometheus_client_php. Create a CollectorRegistry, register counters/gauges/histograms, and expose them on a /metrics endpoint using TextRenderer::renderMetrics(). For Laravel, the spatie/laravel-prometheus package wraps this with automatic route and middleware registration. Key metrics to track: request count (Counter with route and method labels), request duration (Histogram with latency buckets), queue depth (Gauge), cache hit rate (Counter).

What is Laravel Telescope and should I use it in production?

Laravel Telescope is an elegant debug assistant that records requests, exceptions, database queries, queue jobs, mail, notifications, cache operations, and scheduled tasks. It is excellent in development and staging. For production: use it only if your database can handle the write load (it logs every request). Enable the slowLog option to only record slow operations. Use telescope:prune in your scheduler to prevent database bloat. Consider Pulse (Laravel's newer lightweight dashboard) for production monitoring as it is designed for lower overhead.

How do I track PHP errors in production?

The best options for PHP error tracking are: (1) Sentry — install sentry/sentry-laravel, configure DSN, automatic exception capture with stack traces and user context. (2) Flare — Laravel-native, integrates with Ignition for beautiful exception reports. (3) Bugsnag — good for multi-language teams. For Laravel, configure the report() callback in bootstrap/app.php to send exceptions to your provider. Set thresholds (e.g., only report errors, not warnings) to avoid alert fatigue.

What PHP APM tools are available?

Top PHP APM tools in 2026: (1) Datadog APM — excellent PHP tracing, auto-instrumentation for Laravel, high cost. (2) New Relic — mature PHP agent with detailed transaction tracing. (3) Blackfire.io — PHP-specific profiler, excellent for performance optimization, not full APM. (4) Tideways — PHP-focused APM with good Laravel support. (5) OpenTelemetry PHP SDK — open-source, export to any backend (Jaeger, Tempo). (6) Scout APM — simple, developer-friendly with a generous free tier. For most Laravel apps, Scout APM or OpenTelemetry are the best value.

How do I monitor Laravel queues?

Monitor Laravel queue health with: (1) Laravel Horizon — built-in dashboard for Redis queues with metrics on throughput, wait time, failed jobs. Add horizon:snapshot to your scheduler for metrics history. (2) Prometheus metrics via spatie/laravel-queue-monitor — exposes queue size, failed job count as Prometheus gauges. (3) Failed job alerting — use queue:failed notifications in Laravel, or a scheduler job that runs php artisan queue:failed | wc -l and alerts when > 0. Critical queue metrics: queue depth (alert if > N), failed job rate, job processing time (alert on P95 spikes).

📡
Recommended

Add Production Monitoring to Your PHP App

Better Stack monitors your PHP endpoints, aggregates your logs, and sends on-call alerts when things break. Works with any PHP framework — Laravel, Symfony, WordPress, or plain PHP.

Try Better Stack Free →

Related Guides

🛠 Tools We Use & Recommend

Tested across our own infrastructure monitoring 200+ APIs daily

Better StackBest for API Teams

Uptime Monitoring & Incident Management

Used by 100,000+ websites

Monitors your APIs every 30 seconds. Instant alerts via Slack, email, SMS, and phone calls when something goes down.

We use Better Stack to monitor every API on this site. It caught 23 outages last month before users reported them.

Free tier · Paid from $24/moStart Free Monitoring
1PasswordBest for Credential Security

Secrets Management & Developer Security

Trusted by 150,000+ businesses

Manage API keys, database passwords, and service tokens with CLI integration and automatic rotation.

After covering dozens of outages caused by leaked credentials, we recommend every team use a secrets manager.

OpteryBest for Privacy

Automated Personal Data Removal

Removes data from 350+ brokers

Removes your personal data from 350+ data broker sites. Protects against phishing and social engineering attacks.

Service outages sometimes involve data breaches. Optery keeps your personal info off the sites attackers use first.

From $9.99/moFree Privacy Scan
ElevenLabsBest for AI Voice

AI Voice & Audio Generation

Used by 1M+ developers

Text-to-speech, voice cloning, and audio AI for developers. Build voice features into your apps with a simple API.

The best AI voice API we've tested — natural-sounding speech with low latency. Essential for any app adding voice features.

Free tier · Paid from $5/moTry ElevenLabs Free
SEMrushBest for SEO

SEO & Site Performance Monitoring

Used by 10M+ marketers

Track your site health, uptime, search rankings, and competitor movements from one dashboard.

We use SEMrush to track how our API status pages rank and catch site health issues early.

From $129.95/moTry SEMrush Free
View full comparison & more tools →Affiliate links — we earn a commission at no extra cost to you