Введение: Почему мониторинг критичен для Node.js приложений
Современные веб-приложения на JavaScript (Node.js) работают в условиях высокой нагрузки и распределенных архитектур. Даже идеально написанный код может дать сбой из-за утечек памяти, падения производительности или ошибок в асинхронных операциях. Мониторинг JavaScript приложений позволяет не только обнаружить проблему, но и предотвратить её до того, как она затронет пользователей.
В этой статье мы разберем, какие метрики необходимо отслеживать, как настроить сбор данных с помощью популярных инструментов (Prometheus, Grafana) и как организовать систему алертов для Node.js. Все примеры кода написаны на JavaScript и готовы к использованию.
Ключевые метрики для Node.js приложений
Мониторинг Node.js приложений можно разделить на три уровня: инфраструктурный, прикладной и бизнес-метрики. Рассмотрим каждый из них.
Инфраструктурные метрики
Эти метрики показывают состояние сервера и среды выполнения:
- CPU и Memory (RSS, Heap Total, Heap Used) — утечки памяти и высокая загрузка процессора.
- Event Loop Lag — задержка цикла событий (если >50ms, приложение начинает тормозить).
- Garbage Collection (GC) — частота и длительность сборки мусора.
- File Descriptors — количество открытых файлов и сокетов.
Прикладные метрики
Показывают, как приложение обрабатывает запросы:
- RPS (Requests Per Second) — количество запросов в секунду.
- Latency (p50, p95, p99) — задержка ответа.
- Error Rate — процент ошибок (4xx, 5xx).
- Active Connections — количество активных WebSocket/HTTP соединений.
Бизнес-метрики
Специфичные для вашего приложения:
- Количество зарегистрированных пользователей.
- Скорость обработки платежей.
- Время ответа внешних API.
Сбор метрик с помощью Prometheus и Node.js
Prometheus — стандарт де-факто для сбора метрик в современной инфраструктуре. Для Node.js существует библиотека prom-client, которая позволяет легко экспортировать метрики.
Установка и настройка prom-client
npm install prom-client express
Создадим базовый сервер с метриками:
const express = require('express');
const client = require('prom-client');
const app = express();
// Создаем регистр метрик
const register = new client.Registry();
client.collectDefaultMetrics({ register });
// Создаем кастомную гистограмму для задержек
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status_code'],
buckets: [0.1, 0.5, 1, 2, 5]
});
register.registerMetric(httpRequestDuration);
// Middleware для измерения задержек
app.use((req, res, next) => {
const end = httpRequestDuration.startTimer();
res.on('finish', () => {
end({ method: req.method, route: req.route?.path || 'unknown', status_code: res.statusCode });
});
next();
});
// Эндпоинт для метрик
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType);
res.end(await register.metrics());
});
app.get('/', (req, res) => {
res.send('Hello World');
});
app.listen(3000, () => console.log('Server running on port 3000'));
Сбор метрик Event Loop
Для мониторинга цикла событий используем process.hrtime() или библиотеку event-loop-lag:
const eventLoopLag = new client.Gauge({
name: 'nodejs_event_loop_lag_seconds',
help: 'Event loop lag in seconds'
});
register.registerMetric(eventLoopLag);
setInterval(() => {
const start = process.hrtime.bigint();
setImmediate(() => {
const end = process.hrtime.bigint();
const lag = Number(end - start) / 1e9; // в секундах
eventLoopLag.set(lag);
});
}, 1000);
Настройка алертов в Grafana
Grafana — мощный инструмент для визуализации и алертинга. После того как метрики поступают в Prometheus, настраиваем алерты.
Базовые правила алертов (PromQL)
Примеры правил для файла rules.yml:
groups:
- name: nodejs_alerts
rules:
- alert: HighMemoryUsage
expr: nodejs_heap_used_bytes / nodejs_heap_total_bytes > 0.9
for: 5m
labels:
severity: critical
annotations:
summary: "Heap memory usage > 90%"
description: "Heap usage is {{ $value | humanizePercentage }}"
- alert: HighEventLoopLag
expr: nodejs_event_loop_lag_seconds > 0.05
for: 2m
labels:
severity: warning
annotations:
summary: "Event loop lag > 50ms"
- alert: HighErrorRate
expr: rate(http_requests_total{status_code=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05
for: 1m
labels:
severity: critical
annotations:
summary: "Error rate > 5%"
Настройка алертов в Grafana UI
- Перейдите в раздел Alerting → Alert rules.
- Создайте новое правило, выбрав источник данных Prometheus.
- Укажите условие (например,
MAX() OF query_result > threshold). - Настройте каналы уведомлений: Email, Slack, Telegram или PagerDuty.
- Добавьте описание и severity (critical, warning, info).
Продвинутые техники мониторинга
Мониторинг асинхронных операций
Node.js активно использует промисы и async/await. Важно отслеживать rejected promises:
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason