Введение: от базового healthcheck к глубокой observability
Базовый мониторинг PHP-приложений, включающий проверку доступности (healthcheck) и загрузку CPU, — это минимум, который необходимо настроить в первую очередь. Однако для продакшн-систем с высокой нагрузкой и сложной бизнес-логикой этого недостаточно. Продвинутый мониторинг переводит фокус с «живо/мертво» на observability (наблюдаемость) и позволяет ответить на вопросы: «Почему упала конверсия?», «Какой именно эндпоинт замедлил работу?», «Сколько пользователей не смогли завершить оплату?».
В этой статье мы рассмотрим архитектуру продвинутого мониторинга PHP-приложений, научимся собирать кастомные метрики (включая бизнес-метрики), настраивать алерты на основе аномалий и интегрировать всё в единую панель Grafana. Все примеры кода написаны на PHP и готовы к внедрению.
1. Архитектура сбора метрик: Prometheus и кастомные экспортеры
Современный стандарт де-факто для сбора метрик — Prometheus с моделью pull. PHP-приложение не обязано напрямую отдавать метрики на порт /metrics. Вместо этого мы используем кастомный экспортер — отдельный скрипт, который опрашивает приложение (через Redis, БД или файл) и формирует ответ в формате Prometheus.
1.1. Установка Prometheus клиента для PHP
Рекомендуемая библиотека — promphp/prometheus_client_php. Установка через Composer:
composer require promphp/prometheus_client_php
1.2. Пример экспортера метрик (metrics.php)
Создадим скрипт, который возвращает метрики в формате Prometheus. Для хранения используем Redis (флаг PERSISTENT для продакшна).
<?php
require 'vendor/autoload.php';
use Prometheus\CollectorRegistry;
use Prometheus\Storage\Redis;
use Prometheus\RenderTextFormat;
// Подключение к Redis
Redis::setDefaultOptions(['host' => '127.0.0.1', 'port' => 6379]);
$registry = new CollectorRegistry(new Redis());
// Регистрируем гистограмму для времени ответа
$histogram = $registry->getOrRegisterHistogram(
'app_http_request_duration_seconds',
'HTTP request duration in seconds',
['method', 'endpoint', 'status']
);
// Регистрируем счётчик бизнес-метрики
$counter = $registry->getOrRegisterCounter(
'app_orders_total',
'Total number of orders processed',
['status'] // success, failed
);
// Симуляция данных (в реальности считываем из БД или логов)
$histogram->observe(0.12, ['GET', '/api/orders', '200']);
$counter->incBy(1, ['success']);
// Отдаём метрики
$renderer = new RenderTextFormat();
header('Content-Type: text/plain');
echo $renderer->render($registry->getMetricFamilySamples());
Затем настраиваем Nginx или Apache, чтобы этот скрипт был доступен по пути /metrics, и добавляем target в Prometheus.
2. Бизнес-метрики: мониторинг того, что действительно важно
Технические метрики (latency, error rate) — основа, но бизнес-метрики дают понимание здоровья продукта. Примеры таких метрик:
- Количество успешных заказов в минуту — падение сигнализирует о проблемах с платёжным шлюзом.
- Среднее время выполнения корзины — рост может указывать на регрессию в коде.
- Процент отказов от регистрации — если резко вырос, возможно, сломалась форма.
2.1. Интеграция бизнес-метрик в код приложения
Используем тот же prometheus_client_php, но оборачиваем вызовы в middleware или сервисный слой. Пример для Laravel:
<?php
namespace App\Http\Middleware;
use Closure;
use Prometheus\CollectorRegistry;
class MetricsMiddleware
{
protected $registry;
public function __construct(CollectorRegistry $registry)
{
$this->registry = $registry;
}
public function handle($request, Closure $next)
{
$start = microtime(true);
$response = $next($request);
$duration = microtime(true) - $start;
// Метрика времени ответа
$histogram = $this->registry->getOrRegisterHistogram(
'app_http_request_duration_seconds',
'HTTP request duration',
['method', 'endpoint', 'status']
);
$histogram->observe($duration, [
$request->method(),
$request->path(),
$response->status()
]);
// Бизнес-метрика: количество заказов
if ($request->path() === 'api/orders' && $response->status() === 201) {
$counter = $this->registry->getOrRegisterCounter(
'app_orders_created_total',
'Total orders created',
['source'] // web, api, mobile
);
$counter->incBy(1, [$request->header('X-Source', 'web')]);
}
return $response;
}
}
Важно: все операции с метриками должны быть асинхронными или буферизированными, чтобы не замедлять запрос пользователя. Для этого используйте Redis Adapter с флагом PERSISTENT — запись в Redis занимает <1 мс.
3. Продвинутые алерты: от порогов к аномалиям
Простые алерты на превышение порога (например, latency > 1s) приводят к ложным срабатываниям. Продвинутый подход включает:
- Базовые линии (baselines) — алерт срабатывает, если метрика отклоняется от исторической нормы на 3 сигмы.
- Мульти-условные алерты — комбинация нескольких метрик (например, высокий error rate + низкая throughput).
- Алерты на отсутствие данных — если метрика перестала поступать, это может быть хуже, чем высокое значение.