Продвинутый мониторинг TypeScript приложений: метрики и алерты

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Продвинутый мониторинг 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                

Блоги

Рекомендаций по книгам