PHP Application Monitoring: Metrics and Alerts
Modern PHP applications operate in complex distributed environments where failures and performance degradation can cost businesses millions. Without a monitoring system, you risk learning about a problem only from users. In this article, we will explore how to set up comprehensive monitoring for PHP applications, which metrics to track, and how to configure alerts for rapid response.
Why PHP Monitoring is Critically Important
PHP remains one of the most popular languages for web development (according to W3Techs, over 75% of websites use PHP). However, its interpreted nature and memory management specifics require special attention. Without monitoring, you will not be able to:
- Detect memory leaks before they lead to server crashes
- Identify slow database queries
- Pinpoint inefficient code sections
- Forecast load and scale infrastructure
Effective monitoring consists of three components: metric collection, visualization, and alerting. Let's examine each stage in practice.
Key Metrics for PHP Applications
For comprehensive monitoring, you need to track the following metric groups:
Performance Metrics (APM)
- Response time (p50, p95, p99 percentiles)
- Throughput (RPS – requests per second)
- Script execution time (max_execution_time)
- Error count (5xx, exceptions)
System Metrics
- CPU load and PHP-FPM memory usage
- Number of active PHP-FPM processes
- Disk space usage for logs
- Network traffic and latency
Business Metrics
- Number of successful payments
- Page load speed
- Funnel conversion
Practical Implementation: Collecting Metrics with Prometheus
Let's look at an example of integrating a PHP application with Prometheus – one of the most popular monitoring tools. To work with Prometheus in PHP, use the library promphp/prometheus_client_php.
Installation via Composer:
composer require promphp/prometheus_client_phpExample of registering and using a Counter and a Histogram:
<?phpuse Prometheus\\CollectorRegistry;use Prometheus\\Storage\\InMemory;use Prometheus\\RenderTextFormat;
// Initialize storage (in production use Redis or APCu)$registry = new CollectorRegistry(new InMemory());
// Counter for tracking the number of errors$errorCounter = $registry->registerCounter( 'app_errors_total', 'Total number of application errors', ['type', 'endpoint']);
// Histogram for response time$requestDuration = $registry->registerHistogram( 'http_request_duration_seconds', 'HTTP request duration in seconds', ['method', 'endpoint'], [0.1, 0.5, 1, 2, 5, 10] // buckets);
// Middleware for collecting metricsfunction monitorRequest(callable $handler) { global $requestDuration, $errorCounter; $start = microtime(true); try { $result = $handler(); $duration = microtime(true) - $start; // Record execution time $requestDuration->observe($duration, [ $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'] ]); return $result; } catch (\\Throwable $e) { // Increment error counter $errorCounter->inc([ get_class($e), $_SERVER['REQUEST_URI'] ]); throw $e; }}
// Endpoint for Prometheus (usually /metrics)function metricsEndpoint()