Введение: Почему базового мониторинга недостаточно?
Базовый мониторинг PHP приложений (проверка "жив/мертв" и загрузка CPU) перестает работать на высоких нагрузках. Когда ваше приложение обрабатывает тысячи запросов в секунду, стандартные метрики не показывают узкие места: медленные запросы к БД, утечки памяти в долгих процессах или внезапные пики задержек (latency).
В этой статье мы рассмотрим продвинутый уровень мониторинга: сбор бизнес-метрик, профилирование в реальном времени, настройку алертов на основе перцентилей и интеграцию с современными стеками observability (Prometheus + Grafana). Вы научитесь внедрять инструментарий, который позволит не просто видеть, что приложение "упало", но и предсказывать проблемы до их возникновения.
1. Продвинутые метрики: от HTTP-кодов к бизнес-показателям
Стандартные счетчики (количество запросов, 200/500 статусы) — это минимум. Для глубокого анализа нужно собирать:
- Latency (задержка): p50, p95, p99 время ответа. Аномалии в p99 указывают на "выбросы" в работе.
- Потребление памяти: не только пиковое значение, но и скорость роста в рамках одного запроса.
- Время выполнения внешних вызовов: Redis, MySQL, RabbitMQ — каждый сервис должен иметь свою метрику.
- Бизнес-метрики: количество оформленных заказов, ошибок валидации, скорость очередей.
Пример сбора метрик с использованием promphp/prometheus_client_php:
use Prometheus\CollectorRegistry;
use Prometheus\RenderTextFormat;
use Prometheus\Storage\InMemory;
$registry = new CollectorRegistry(new InMemory());
// Гистограмма для времени выполнения запроса
$histogram = $registry->registerHistogram(
'app', 'request_duration_seconds', 'HTTP request duration',
['method', 'endpoint'],
[0.1, 0.5, 1.0, 2.0, 5.0]
);
// Счетчик бизнес-событий
$counter = $registry->registerCounter(
'business', 'orders_total', 'Total orders created',
['status'] // success/failed
);
// В middleware замеряем время
$start = microtime(true);
// ... выполнение запроса ...
$duration = microtime(true) - $start;
$histogram->observe($duration, ['GET', '/api/orders']);
2. Health Checks и Deep Probing: проверка зависимостей
Простой ping-эндпоинт не проверяет доступность базы данных, кэша или очередей. Создайте комплексный health check, который имитирует реальные запросы:
// 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 () {
// Проверяем, что RabbitMQ не переполнен
$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]);
Такой эндпоинт можно подключить к Kubernetes liveness/readiness probes или к внешнему мониторингу (например, UptimeRobot), который будет проверять не только доступность, но и работоспособность всех зависимостей.
3. Алерты на основе перцентилей и аномалий
Алерты на "среднее время ответа" часто пропускают проблемы. Если среднее = 200ms, но каждый 100-й запрос выполняется 10 секунд, среднее все еще будет низким. Используйте перцентили (p99) и базовые линии (baselines).
Пример правил для Prometheus Alertmanager:
groups:
- name: php_app
rules:
- alert: HighLatencyP99
expr: histogram_quantile(0.99, rate(app_request_duration_seconds_bucket[5m])) > 2
for: 5m
labels:
severity: critical
annotations:
summary: "P99 latency over 2s for {{ $labels.endpoint }}"
- alert: HighErrorRate
expr: rate(app_http_requests_total{status=~"5.."}[5m]) / rate(app_http_requests_total[5m]) > 0.05
for: 2m
labels:
severity: warning
annotations:
summary: "Error rate above 5%"
- alert: MemoryLeakDetected
expr: process_resident_memory_bytes / 1024 / 1024 > 512
for: 10m
labels:
severity: warning
annotations:
summary: "Memory usage > 512MB on {{ $labels.instance }}"
Для бизнес-метрик настройте алерты на "внезапное падение" — например, если количество заказов упало на 50% за час (используйте predict_linear или пороговые значения).
4. Интеграция с Grafana: визуализация и дашборды
Данные бесполезны без визуализации. Создайте дашборд в Grafana, который покажет:
- Тепловую карту (heatmap) задержек по эндпоинтам.
- График перцентилей p50, p95, p99 на одном полотне.
- Скорость ошибок в разрезе статусов (4xx, 5xx).
- Топ медленных запросов — таблица с сортировкой по p99.
Пример запроса для получения p99 в Grafana (PromQL):
histogram_quantile(0.99,
sum(rate(app_request_duration_seconds_bucket[