Monitoring PHP Applications: Advanced Metrics and Alerts

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Basic Monitoring Is Not Enough?

Basic monitoring of PHP applications (alive/dead check and CPU load) stops working under high loads. When your application processes thousands of requests per second, standard metrics do not show bottlenecks: slow database queries, memory leaks in long-running processes, or sudden latency spikes.

In this article, we will cover the advanced level of monitoring: collecting business metrics, real-time profiling, configuring alerts based on percentiles, and integration with modern observability stacks (Prometheus + Grafana). You will learn to implement tooling that allows you not just to see that the application has "crashed," but to predict problems before they occur.



1. Advanced Metrics: From HTTP Codes to Business Indicators

Standard counters (number of requests, 200/500 statuses) are the bare minimum. For in-depth analysis, you need to collect:

  • Latency: p50, p95, p99 response time. Anomalies in p99 indicate "outliers" in operation.
  • Memory consumption: not only the peak value but also the growth rate within a single request.
  • External call execution time: Redis, MySQL, RabbitMQ — each service should have its own metric.
  • Business metrics: number of completed orders, validation errors, queue speed.

Example of collecting metrics using promphp/prometheus_client_php:

use Prometheus\\CollectorRegistry;use Prometheus\\RenderTextFormat;use Prometheus\\Storage\\InMemory;

$registry = new CollectorRegistry(new InMemory());

// Histogram for request execution time$histogram = $registry->registerHistogram( 'app', 'request_duration_seconds', 'HTTP request duration', ['method', 'endpoint'], [0.1, 0.5, 1.0, 2.0, 5.0]);

// Counter for business events$counter = $registry->registerCounter( 'business', 'orders_total', 'Total orders created', ['status'] // success/failed);

// In middleware, measure the time$start = microtime(true);// ... execute request ...$duration = microtime(true) - $start;$histogram->observe($duration, ['GET', '/api/orders']);


2. Health Checks and Deep Probing: Checking Dependencies

A simple ping endpoint does not check the availability of the database, cache, or queues. Create a comprehensive health check that simulates real requests:

// health.php$checks = [    'database' => function () {        $db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');        $db->query('SELECT 1');        return true;    },    'redis' => function () {        $redis = new Redis();        $redis->connect('127.0.0.1', 6379);        $redis->ping();        return true;    },    'queue' => function () {        // Check that RabbitMQ is not overloaded        $channel = new AMQPChannel(new AMQPConnection());        $queue = new AMQPQueue($channel);        return $queue->declareQueue() !== false;    }];

$results = [];$healthy = true;foreach ($checks as $name => $check) { try { $check(); $results[$name] = 'ok'; } catch (\\Throwable $e) { $results[$name] = 'failed: ' . $e->getMessage(); $healthy = false; }}

header('Content-Type: application/json');http_response_code($healthy ? 200 : 503);echo json_encode(['status' => $healthy ? 'healthy' : 'unhealthy', 'checks' => $results]);

Such an endpoint can be connected to Kubernetes liveness/readiness probes or to external monitoring (e.g., UptimeRobot), which will check not only availability but also the operability of all dependencies.



3. Alerts Based on Percentiles and Anomalies

Alerts on "average response time" often miss

Blogs

Book Recommendations