Введение: Почему продвинутый мониторинг — необходимость для Node.js
В современной веб-разработке мониторинг вышел за рамки простого логирования ошибок. Для критически важных Node.js приложений — от микросервисов до высоконагруженных API — требуется проактивный сбор метрик, интеллектуальные алерты и визуализация данных. На продвинутом уровне мы говорим не просто о "приложение живо", а о его производительности, узких местах и предсказании сбоев.
В этой статье мы разберём, как построить полноценную систему мониторинга для JavaScript (Node.js) приложения: от сбора кастомных метрик до настройки алертов через Prometheus и Grafana. Вы узнаете, как использовать встроенные возможности Node.js и современные библиотеки для проактивного отслеживания состояния сервиса.
1. Сбор продвинутых метрик: от Event Loop до пользовательских счётчиков
Базовая метрика — это время ответа сервера. Продвинутая — это задержка Event Loop, количество активных дескрипторов и частота сборки мусора. Рассмотрим, как собирать эти данные с помощью process и библиотеки prom-client (клиент для Prometheus).
1.1. Метрики Event Loop и системные ресурсы
Node.js однопоточен, поэтому задержка Event Loop критична. Измеряем её через process.hrtime() и экспортируем как гистограмму.
const client = require('prom-client');
const eventLoopDelay = new client.Histogram({
name: 'nodejs_event_loop_delay_seconds',
help: 'Задержка Event Loop в секундах',
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1]
});
function measureEventLoop() {
const start = process.hrtime.bigint();
setImmediate(() => {
const duration = Number(process.hrtime.bigint() - start) / 1e9;
eventLoopDelay.observe(duration);
});
}
setInterval(measureEventLoop, 5000);
1.2. Пользовательские метрики бизнес-логики
Помимо системных метрик, отслеживайте бизнес-показатели: количество обработанных заказов, ошибки валидации, время выполнения внешних запросов.
const orderCounter = new client.Counter({
name: 'app_orders_total',
help: 'Общее количество обработанных заказов',
labelNames: ['status'] // success, failed
});
// Пример использования в обработчике
app.post('/api/order', async (req, res) => {
try {
await processOrder(req.body);
orderCounter.inc({ status: 'success' });
res.send('OK');
} catch (err) {
orderCounter.inc({ status: 'failed' });
res.status(500).send('Error');
}
});
2. Экспорт метрик и интеграция с Prometheus
Чтобы Prometheus мог собирать метрики, нужно создать эндпоинт /metrics. Используем стандартный регистр prom-client.
2.1. Создание эндпоинта для сбора
const express = require('express');
const app = express();
const client = require('prom-client');
// Собираем стандартные метрики Node.js
client.collectDefaultMetrics({ timeout: 5000 });
app.get('/metrics', async (req, res) => {
res.set('Content-Type', client.register.contentType);
res.end(await client.register.metrics());
});
app.listen(3000, () => console.log('Metrics server on :3000'));
2.2. Конфигурация Prometheus
В файле prometheus.yml добавьте цель для вашего приложения:
scrape_configs:
- job_name: 'nodejs-app'
static_configs:
- targets: ['localhost:3000']
После перезапуска Prometheus метрики будут собираться каждые 15 секунд по умолчанию.
3. Настройка алертов: от простых порогов до анализа аномалий
Алерты — это реакция на выход метрик за пределы нормы. На продвинутом уровне мы используем PromQL для сложных условий и настраиваем правила в Alertmanager.
3.1. Базовые правила алертов
Создайте файл alerts.yml:
groups:
- name: nodejs_alerts
rules:
- alert: HighEventLoopLatency
expr: nodejs_event_loop_delay_seconds{quantile="0.99"} > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "Высокая задержка Event Loop ({{ $value }}s)"
- alert: HighErrorRate
expr: rate(app_orders_total{status="failed"}[5m]) / rate(app_orders_total[5m]) > 0.05
for: 2m
labels:
severity: warning
annotations:
summary: "Уровень ошибок выше 5%"
3.2. Продвинутые алерты: предсказание сбоев
Используйте функцию predict_linear для прогнозирования исчерпания ресурсов:
- alert: DiskFullIn4Hours
expr: predict_linear(node_filesystem_free_bytes{mountpoint="/"}[1h], 4*3600) < 0
for: 10m
labels:
severity: critical
annotations:
summary: "Диск заполнится через 4 часа"
4. Визуализация в Grafana и Health Check API
Grafana позволяет строить дашборды в реальном времени. Но для быстрой диагностики полезен эндпоинт /health.
4.1. Кастомный Health Check
const checkDatabase = async () => {
// Логика проверки БД
return { status: 'ok', latency: 5 };
};
app.get('/health', async (req, res) => {
const dbHealth = await checkDatabase();
const memoryUsage = process.memoryUsage();
const healthData = {
status: 'healthy',
uptime: process.uptime(),
memory: {
heapUsed: Math.round(memoryUsage.heapUsed / 1024 / 1024) + 'MB',
heapTotal: Math.round(memoryUsage.heapTotal / 1024 / 1024) + 'MB'
},
database: dbHealth
};
const isHealthy = dbHealth.status === 'ok';
res.status(isHealthy ? 200 : 503).json(healthData);
});
4.2. Пример дашборда в Grafana
Подключите Prometheus как источник данных и создайте панели:
- За