Продвинутый мониторинг TypeScript приложений: метрики и алерты
В современной разработке мониторинг вышел за рамки простой проверки "жив ли сервер". Для TypeScript-приложений, работающих в сложных распределенных средах, требуется продвинутая система наблюдаемости. Недостаточно просто логировать ошибки — необходимо собирать кастомные метрики производительности, настраивать интеллектуальные алерты и строить дашборды для предиктивного анализа. В этой статье мы рассмотрим, как реализовать профессиональный мониторинг TypeScript-приложений с использованием современных инструментов и лучших практик.
1. Сбор кастомных метрик производительности
Базовые метрики (CPU, память) часто не дают полной картины. Для TypeScript-приложений критически важны бизнес-метрики и метрики времени выполнения. Рассмотрим настройку сбора кастомных метрик с помощью библиотеки prom-client (клиент Prometheus для Node.js).
Типы кастомных метрик
- Counter (счетчик) — для подсчета событий (запросы, ошибки).
- Gauge (датчик) — для значений, которые могут расти и уменьшаться (количество активных соединений).
- Histogram (гистограмма) — для распределения значений (время ответа).
- Summary (сводка) — для квантилей времени выполнения.
Пример: Регистрация кастомных метрик в TypeScript
import client from 'prom-client';
import express, { Request, Response } from 'express';
// Создаем регистр метрик
const register = new client.Registry();
client.collectDefaultMetrics({ register });
// Кастомный счетчик ошибок
const errorCounter = new client.Counter({
name: 'app_errors_total',
help: 'Total number of application errors',
labelNames: ['type', 'code'],
registers: [register],
});
// Гистограмма времени ответа
const httpRequestDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status'],
buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5],
registers: [register],
});
// Gauge активных пользователей
const activeUsers = new client.Gauge({
name: 'active_users_count',
help: 'Number of currently active users',
labelNames: ['user_type'],
registers: [register],
});
const app = express();
// Middleware для замера времени запросов
app.use((req: Request, res: Response, next) => {
const end = httpRequestDuration.startTimer();
res.on('finish', () => {
end({ method: req.method, route: req.path, status: res.statusCode });
});
next();
});
// Эндпоинт для метрик
app.get('/metrics', async (req: Request, res: Response) => {
res.set('Content-Type', register.contentType);
res.end(await register.metrics());
});
// Симуляция ошибки
app.get('/error', (req: Request, res: Response) => {
errorCounter.inc({ type: 'validation', code: '400' });
res.status(400).send('Bad Request');
});
app.listen(3000, () => console.log('Server on port 3000'));
2. Интеграция с Prometheus и Grafana
Собранные метрики необходимо экспортировать и визуализировать. Prometheus будет опрашивать наш эндпоинт /metrics, а Grafana отобразит данные на дашбордах.
Конфигурация Prometheus для TypeScript-приложения
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'typescript-app'
static_configs:
- targets: ['localhost:3000']
metrics_path: '/metrics'
# Добавляем метки окружения
relabel_configs:
- source_labels: [__address__]
target_label: instance
regex: '([^:]+):.*'
replacement: '${1}'
Продвинутые запросы PromQL для анализа
rate(app_errors_total[5m])— частота ошибок за 5 минут.histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))— 95-й перцентиль времени ответа.avg(rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m]))— среднее время ответа.
3. Настройка интеллектуальных алертов
Алерты должны быть умными, чтобы минимизировать ложные срабатывания. Используем Alertmanager для управления оповещениями.
Правила алертов (rules.yml)
groups:
- name: typescript-app-alerts
rules:
# Высокая частота ошибок
- alert: HighErrorRate
expr: |
rate(app_errors_total[5m]) > 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.instance }}"
description: "Error rate is {{ $value | humanize }} per second"
# Медленные ответы (p95 > 1s)
- alert: SlowResponses
expr: |
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
for: 5m
labels:
severity: warning
annotations:
summary: "Slow responses detected"
description: "95th percentile is {{ $value }}s"
# Резкое падение активных пользователей
- alert: ActiveUsersDrop
expr: |
active_users_count < 10
for: 1m
labels:
severity: info
annotations:
summary: "Low active users count"
Конфигурация Alertmanager для отправки в Telegram:
# alertmanager.yml
receivers:
- name: 'telegram'
telegram_configs:
- bot_token: 'YOUR_BOT_TOKEN'
chat_id: -1001234567890
parse_mode: 'HTML'
route:
receiver: 'telegram'
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
4. Продвинутые техники: трейсинг и логирование
Для полной картины наблюдаемости (Observability) стоит объединить метрики с трейсингом и структурированным логированием.
Структурированное логирование с корреляцией
import pino from 'pino';
import { v4 as uuidv4 } from 'uuid';
const logger = pino({
level: 'info',
formatters: {
level