Современный Stack Мониторинга

Prometheus и Grafana формируют индустриальный стандарт open-source стека мониторинга. Prometheus собирает и хранит временные ряды метрик, в то время как Grafana визуализирует их через настраиваемые дашборды. Для QA-инженеров этот стек предоставляет инсайты в реальном времени о производительности приложений, состоянии инфраструктуры и метриках пользовательского опыта.

Почему Prometheus + Grafana?

  • Pull-Based Модель - Prometheus собирает метрики с целей, не нужен push со стороны клиента
  • Мощный Язык Запросов (PromQL) - Гибкие запросы и агрегация метрик
  • Service Discovery - Автоматическое обнаружение целей в динамических окружениях (Kubernetes, AWS, etc.)
  • Алертинг - Встроенный alert manager с маршрутизацией и заглушением
  • Open Source - Без vendor lock-in, большая поддержка сообщества
  • Визуализация Grafana - Богатые дашборды с поддержкой множества источников данных

Архитектура Prometheus

Основные Компоненты

# Обзор архитектуры Prometheus
components:
  prometheus_server:
    - scrapes_metrics: true
    - stores_timeseries: true
    - evaluates_rules: true

  exporters:
    - node_exporter: "Системные метрики (CPU, память, диск)"
    - blackbox_exporter: "Проверка endpoints (HTTP, DNS, TCP)"
    - custom_exporters: "Специфичные метрики приложения"

  pushgateway:
    - for_batch_jobs: true
    - short_lived_processes: true

  alertmanager:
    - handles_alerts: true
    - routes_notifications: true
    - silences_alerts: true

  service_discovery:
    - kubernetes: true
    - consul: true
    - ec2: true
    - dns: true

Установка Prometheus

# Установка Docker
docker run -d \
  --name prometheus \
  -p 9090:9090 \
  -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus

# Установка Kubernetes (используя Helm)
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/prometheus

# Файл конфигурации: prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['localhost:9100']

  - job_name: 'application'
    static_configs:
      - targets: ['app:8080']
    metrics_path: '/metrics'

Инструментирование Приложений

Приложение Node.js

// app.js
const express = require('express');
const promClient = require('prom-client');

const app = express();
const register = promClient.register;

// Включить метрики по умолчанию (CPU, память, event loop lag)
promClient.collectDefaultMetrics({ register });

// Кастомные метрики
const httpRequestDuration = new promClient.Histogram({
  name: 'http_request_duration_seconds',
  help: 'Длительность HTTP запросов в секундах',
  labelNames: ['method', 'route', 'status_code'],
  buckets: [0.1, 0.3, 0.5, 0.7, 1, 3, 5, 7, 10]
});

const httpRequestTotal = new promClient.Counter({
  name: 'http_requests_total',
  help: 'Общее количество HTTP запросов',
  labelNames: ['method', 'route', 'status_code']
});

const activeConnections = new promClient.Gauge({
  name: 'active_connections',
  help: 'Количество активных соединений'
});

// Middleware для отслеживания метрик
app.use((req, res, next) => {
  const start = Date.now();
  activeConnections.inc();

  res.on('finish', () => {
    const duration = (Date.now() - start) / 1000;

    httpRequestDuration
      .labels(req.method, req.route?.path || req.path, res.statusCode)
      .observe(duration);

    httpRequestTotal
      .labels(req.method, req.route?.path || req.path, res.statusCode)
      .inc();

    activeConnections.dec();
  });

  next();
});

// Endpoint метрик
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', register.contentType);
  res.end(await register.metrics());
});

// Бизнес-логика
app.get('/api/users', async (req, res) => {
  // Ваша логика здесь
  res.json({ users: [] });
});

app.listen(3000, () => {
  console.log('Сервер работает на порту 3000');
  console.log('Метрики доступны на http://localhost:3000/metrics');
});

PromQL: Язык Запросов

Базовые Запросы

# Мгновенный вектор - текущее значение
http_requests_total

# Фильтрация по labels
http_requests_total{method="GET", status_code="200"}

# Диапазонный вектор - значения за период времени
http_requests_total[5m]

# Скорость увеличения (в секунду)
rate(http_requests_total[5m])

# Увеличение за период времени
increase(http_requests_total[1h])

Продвинутый PromQL

# Скорость запросов по endpoint
sum(rate(http_requests_total[5m])) by (route)

# Процент ошибок
(
  sum(rate(http_requests_total{status_code=~"5.."}[5m]))
  / sum(rate(http_requests_total[5m]))
) * 100

# Задержка P95
histogram_quantile(0.95,
  rate(http_request_duration_seconds_bucket[5m])
)

# Процент доступности
(
  sum(up{job="application"})
  / count(up{job="application"})
) * 100

# Скорость роста использования памяти
deriv(node_memory_MemAvailable_bytes[1h])

Дашборды Grafana

Установка Grafana

# Установка Docker
docker run -d \
  --name=grafana \
  -p 3000:3000 \
  grafana/grafana

# Добавить data source Prometheus
# Перейти на: http://localhost:3000 (admin/admin)
# Configuration → Data Sources → Add Prometheus
# URL: http://prometheus:9090

Создание Дашборда Производительности

{
  "dashboard": {
    "title": "Производительность Приложения",
    "panels": [
      {
        "title": "Скорость Запросов",
        "targets": [
          {
            "expr": "sum(rate(http_requests_total[5m])) by (route)",
            "legendFormat": "{{route}}"
          }
        ],
        "type": "graph"
      },
      {
        "title": "Частота Ошибок",
        "targets": [
          {
            "expr": "(sum(rate(http_requests_total{status_code=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))) * 100",
            "legendFormat": "Ошибки %"
          }
        ],
        "type": "graph"
      }
    ]
  }
}

Алертинг с Prometheus & Grafana

Правила Алертов Prometheus

# alerts.yml
groups:
  - name: performance_alerts
    interval: 30s
    rules:
      - alert: ВысокаяЧастотаОшибок
        expr: |
          (sum(rate(http_requests_total{status_code=~"5.."}[5m]))
          / sum(rate(http_requests_total[5m]))) * 100 > 5
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Обнаружена высокая частота ошибок"
          description: "Частота ошибок {{ $value }}% (порог: 5%)"

      - alert: ВысокаяЗадержка
        expr: |
          histogram_quantile(0.95,
            rate(http_request_duration_seconds_bucket[5m])
          ) > 2
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Высокая задержка на {{ $labels.route }}"
          description: "Задержка P95 составляет {{ $value }}s"

Лучшие Практики Мониторинга

Четыре Золотых Сигнала

# 1. ЗАДЕРЖКА - Длительность запроса
histogram_quantile(0.99,
  sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
)

# 2. ТРАФИК - Частота запросов
sum(rate(http_requests_total[5m]))

# 3. ОШИБКИ - Частота ошибок
sum(rate(http_requests_total{status_code=~"5.."}[5m]))

# 4. НАСЫЩЕНИЕ - Использование ресурсов
avg(rate(node_cpu_seconds_total{mode!="idle"}[5m])) * 100

Заключение

Prometheus и Grafana предоставляют мощный, гибкий стек мониторинга для QA-инженеров. От инструментирования приложений до создания проницательных дашбордов и настройки интеллектуальных алертов, этот стек обеспечивает проактивный мониторинг производительности и быстрое обнаружение проблем.

Ключевые Выводы:

  • Инструментируйте приложения с кастомными метриками
  • Освойте PromQL для мощных запросов
  • Создавайте действенные дашборды с Grafana
  • Настраивайте алерты на основе SLOs/SLIs
  • Следуйте методологиям мониторинга: RED, USE, Четыре Золотых Сигнала
  • Интегрируйте мониторинг в workflows нагрузочного тестирования

Эффективный мониторинг — это не просто сбор метрик, это превращение данных в действенные инсайты.