Перейти к содержимому

Monitoring Stack 2025: Prometheus + Grafana + Loki на минималках

Константин Потапов
18 мин

Как настроить полноценный мониторинг за вечер без DevOps-команды. Метрики, логи, алерты и дашборды для проектов на одном сервере или небольшом кластере.

Monitoring Stack 2025: Prometheus + Grafana + Loki на минималках

"У нас упал прод в 3 ночи. Мы узнали об этом в 9 утра из письма клиента."

Знакомая ситуация? У меня таких историй десятки. В 2023-м я консультировал стартап на $2M ARR — у них не было ни единого алерта. Мониторинг = SSH на сервер и tail -f в логах. Когда база встала из-за переполнения диска, они потеряли 6 часов работы и $15k выручки.

Спойлер: настроить нормальный мониторинг можно за один вечер. Без Kubernetes, без DataDog за $3000/месяц, без dedicated DevOps-команды.

В этой статье — минималистичный стек для реальных проектов: Prometheus для метрик, Grafana для визуализации, Loki для логов. Всё это поднимается на одном сервере, работает годами и спасает вашу жопу в 3 ночи.

Почему мониторинг — это не роскошь

Три реальных кейса из моей практики:

Кейс 1: Fintech-стартап (2024) Клиентская база росла, API тормозил всё сильнее. Команда знала, что "что-то не так", но не знала, что именно. Поставили Prometheus за вечер — оказалось, что одна точка делала 300+ SQL-запросов на один HTTP-запрос. Пофиксили N+1, response time с 2.5s упал до 120ms. ROI мониторинга окупился за неделю.

Кейс 2: E-commerce на Django (2025) Продакшен "тупил" раз в 2-3 дня, но без паттерна. SSH + htop ничего не показывал. Добавили Grafana с метриками памяти — обнаружили, что Celery worker жрал 16GB RAM и OOM-killer убивал его. Виновник — утечка памяти в обработке картинок. Фикс занял 2 часа, простои прекратились.

Кейс 3: SaaS для B2B (2023) Клиенты жаловались на "странные тормоза". Метрики показали spike в латентности каждые 6 часов. Loki помог найти паттерн: backup-скрипт на том же сервере выполнял pg_dump без nice, CPU утилизация летела в 100%, приложение задыхалось. Решение — перенести бэкапы на отдельную машину.

90% production-проблем невидимы без мониторинга. Вы не узнаете о них, пока не получите angry email от клиента или пока не потеряете деньги.

Что такое observability простыми словами

Observability (наблюдаемость) — способность понять, что происходит внутри системы, глядя на её внешние сигналы.

Три столпа наблюдаемости:

  1. Метрики (Metrics) — числовые показатели: CPU, память, RPS, latency, error rate
  2. Логи (Logs) — события: "пользователь зарегистрировался", "ошибка в базе", "начали деплой"
  3. Трейсы (Traces) — путь запроса через систему (в этой статье не покрываем, это для микросервисов)

Метафора: представьте автомобиль.

  • Метрики — спидометр, тахометр, температура двигателя
  • Логи — бортовой компьютер с записью "двигатель перегрелся в 14:35"
  • Трейсы — видео регистратор, показывающий весь маршрут

Без мониторинга вы ведёте машину с завязанными глазами и узнаёте о поломке, когда она уже встала.

Выбор стека: почему Prometheus + Grafana + Loki

Есть десятки инструментов мониторинга. Я перепробовал Zabbix, Nagios, ELK Stack, Datadog, New Relic. Для 90% проектов выбор очевиден: Prometheus + Grafana + Loki.

Почему этот стек:

  • Open source и бесплатный — никаких лицензий, vendor lock-in или счетов на $5k/месяц
  • Production-grade — используется в крупнейших компаниях (Google, Uber, GitLab)
  • Lightweight — работает на одном сервере с 2GB RAM
  • Интеграции из коробки — exporters для всего: PostgreSQL, Redis, Nginx, Node.js
  • Active development — обновления каждый месяц, огромное комьюнити
  • Простота — поднимается за час, не требует PhD в DevOps

Сравнение с альтернативами:

КритерийPrometheus StackELK StackDatadog/New RelicZabbix
Стоимость✅ Бесплатно✅ Бесплатно❌ $100-5000/мес✅ Бесплатно
Простота setup✅ 1-2 часа⚠️ 4-8 часов✅ 30 минут⚠️ 2-4 часа
Ресурсы (RAM)✅ 1-2GB❌ 8-16GB☁️ SaaS⚠️ 2-4GB
Метрики✅ Отлично⚠️ Не фокус✅ Отлично✅ Хорошо
Логи✅ Loki✅ Отлично (ES)✅ Отлично⚠️ Базово
Алерты✅ Alertmanager⚠️ Сложно✅ Отлично✅ Хорошо
Дашборды✅ Grafana⚠️ Kibana✅ Красиво⚠️ Kibana
Community & Экосистема✅ Огромное✅ Большое⚠️ Vendor-lock⚠️ Устарело

Мой выбор:

  • Для стартапов и малых проектов (до 10 серверов) — Prometheus Stack
  • Для enterprise с compliance — ELK Stack (требует Elasticsearch для аудита)
  • Для корпораций с деньгами — Datadog/New Relic (если бюджет есть и лень возиться)
  • Для legacy-систем — Zabbix (если он уже стоит, не трогайте)
PrometheusGrafanaLokiDockerNode Exporter

Архитектура стека на минималках

Вот что мы будем запускать:

┌─────────────────────────────────────────────────┐
│  Ваш сервер (2-4GB RAM)                         │
├─────────────────────────────────────────────────┤
│                                                 │
│  ┌─────────────────┐  ┌──────────────┐          │
│  │ Ваше приложение │  │ PostgreSQL   │          │
│  │ (FastAPI/Django)│  │ / Redis      │          │
│  └────┬────────────┘  └────┬─────────┘          │
│       │                    │                    │
│       │ metrics            │ metrics            │
│       │ + logs             │ (exporter)         │
│       ▼                    ▼                    │
│  ┌─────────────────────────────────┐            │
│  │ Prometheus                      │            │
│  │ (собирает метрики каждые 15s)   │            │
│  └───────────┬─────────────────────┘            │
│              │                                  │
│              │ query                            │
│              ▼                                  │
│  ┌─────────────────────────────────┐            │
│  │ Grafana                         │            │
│  │ (визуализация + алерты)         │            │
│  └───────────┬─────────────────────┘            │
│              │ query                            │
│  ┌───────────▼─────────────────────┐            │
│  │ Loki                            │            │
│  │ (хранит логи)                   │            │
│  └─────────────────────────────────┘            │
│                                                 │
└─────────────────────────────────────────────────┘

Компоненты:

  1. Prometheus — time-series база данных для метрик. Ходит по HTTP к вашему приложению и exporters, забирает метрики каждые 15-30 секунд.
  2. Grafana — веб-интерфейс для дашбордов и алертов. Подключается к Prometheus и Loki, рисует графики.
  3. Loki — лог-агрегатор. Ваше приложение шлёт логи, Loki их индексирует, Grafana показывает.
  4. Exporters — приложения, которые экспортируют метрики в формате Prometheus:
    • node_exporter — метрики сервера (CPU, RAM, disk, network)
    • postgres_exporter — метрики PostgreSQL
    • redis_exporter — метрики Redis
    • nginx_exporter — метрики Nginx

Требования к серверу:

  • Минимум: 2GB RAM, 2 CPU cores, 20GB disk
  • Рекомендуется: 4GB RAM, 2 CPU cores, 50GB disk
  • OS: Ubuntu 22.04/24.04, Debian 12, или любой Linux с Docker

Этот стек я запускал даже на VPS за $5/месяц (Hetzner CX21). Для малых проектов хватает за глаза.

Практика: поднимаем стек за час

Переходим к делу. Предполагаю, что у вас есть сервер на Ubuntu/Debian с Docker.

Шаг 1: Создаём docker-compose.yml

Создайте директорию для мониторинга:

mkdir -p /opt/monitoring
cd /opt/monitoring

Создайте docker-compose.yml:

services:
  # Prometheus — собирает метрики
  prometheus:
    image: prom/prometheus:v3.0.0
    container_name: prometheus
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus"
      - "--storage.tsdb.retention.time=30d" # Храним метрики 30 дней
      - "--web.enable-lifecycle" # API для hot-reload конфига
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./prometheus/alerts.yml:/etc/prometheus/alerts.yml
      - prometheus_data:/prometheus
    restart: unless-stopped
    networks:
      - monitoring
 
  # Grafana — визуализация
  grafana:
    image: grafana/grafana:11.4.0
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=your_secure_password # ПОМЕНЯЙТЕ!
      - GF_INSTALL_PLUGINS=grafana-piechart-panel
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    restart: unless-stopped
    networks:
      - monitoring
 
  # Loki — логи
  loki:
    image: grafana/loki:3.3.2
    container_name: loki
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - loki_data:/loki
    restart: unless-stopped
    networks:
      - monitoring
 
  # Node Exporter — метрики сервера
  node_exporter:
    image: prom/node-exporter:v1.8.2
    container_name: node_exporter
    command:
      - "--path.rootfs=/host"
    ports:
      - "9100:9100"
    volumes:
      - /:/host:ro,rslave
    restart: unless-stopped
    networks:
      - monitoring
 
volumes:
  prometheus_data:
  grafana_data:
  loki_data:
 
networks:
  monitoring:
    driver: bridge

Шаг 2: Конфигурация Prometheus

Создайте prometheus/prometheus.yml:

global:
  scrape_interval: 15s # Собираем метрики каждые 15 секунд
  evaluation_interval: 15s # Проверяем правила алертов каждые 15 секунд
 
# Алерты (создадим позже)
rule_files:
  - "/etc/prometheus/alerts.yml"
 
# Откуда собираем метрики
scrape_configs:
  # Сам Prometheus
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]
 
  # Метрики сервера (CPU, RAM, Disk)
  - job_name: "node"
    static_configs:
      - targets: ["node_exporter:9100"]
 
  # Ваше приложение (FastAPI, Django, etc.)
  # Раскомментируйте и укажите адрес вашего приложения
  # - job_name: 'app'
  #   static_configs:
  #     - targets: ['app:8000']
 
  # PostgreSQL (если используете postgres_exporter)
  # - job_name: 'postgres'
  #   static_configs:
  #     - targets: ['postgres_exporter:9187']
 
  # Redis (если используете redis_exporter)
  # - job_name: 'redis'
  #   static_configs:
  #     - targets: ['redis_exporter:9121']

Создайте пустой файл алертов prometheus/alerts.yml (заполним позже):

groups:
  - name: basic_alerts
    interval: 30s
    rules: []

Шаг 3: Запускаем стек

docker compose up -d

Проверяем, что всё запустилось:

docker compose ps

Должны увидеть 4 контейнера в статусе Up:

  • prometheus
  • grafana
  • loki
  • node_exporter

Проверяем доступность:

Поздравляю! Базовый стек запущен. Теперь настраиваем дашборды и алерты.

Шаг 4: Настройка Grafana

  1. Откройте Grafana: http://your-server-ip:3000
  2. Войдите (admin / ваш пароль из docker-compose)
  3. Добавьте Data Source:
    • ConnectionsAdd data sourcePrometheus
    • URL: http://prometheus:9090
    • Save & Test — должна быть галочка "Data source is working"
  4. Повторите для Loki:
    • Add data sourceLoki
    • URL: http://loki:3100
    • Save & Test

Шаг 5: Импорт готового дашборда

Не нужно рисовать дашборд с нуля — используйте готовый.

  1. В Grafana: DashboardsImport
  2. Введите ID дашборда: 1860 (Node Exporter Full)
  3. Нажмите Load
  4. Выберите Prometheus data source
  5. Import

Вуаля! У вас появился дашборд с метриками сервера: CPU, RAM, Disk I/O, Network.

Другие полезные дашборды:

  • PostgreSQL: ID 9628
  • Redis: ID 11835
  • Nginx: ID 12708
  • Docker: ID 893

Добавляем метрики из вашего приложения

Теперь самое важное — метрики из вашего приложения.

Python (FastAPI / Django)

Установите библиотеку:

pip install prometheus-client

FastAPI:

from fastapi import FastAPI
from prometheus_client import Counter, Histogram, make_asgi_app
 
app = FastAPI()
 
# Метрики
REQUEST_COUNT = Counter(
    'app_requests_total',
    'Total HTTP requests',
    ['method', 'endpoint', 'status']
)
 
REQUEST_DURATION = Histogram(
    'app_request_duration_seconds',
    'HTTP request duration',
    ['method', 'endpoint']
)
 
@app.middleware("http")
async def prometheus_middleware(request, call_next):
    method = request.method
    endpoint = request.url.path
 
    with REQUEST_DURATION.labels(method, endpoint).time():
        response = await call_next(request)
 
    REQUEST_COUNT.labels(method, endpoint, response.status_code).inc()
    return response
 
# Endpoint для Prometheus
metrics_app = make_asgi_app()
app.mount("/metrics", metrics_app)

Теперь метрики доступны на http://your-app:8000/metrics.

Django (с django-prometheus):

pip install django-prometheus
# settings.py
INSTALLED_APPS = [
    'django_prometheus',
    # ...
]
 
MIDDLEWARE = [
    'django_prometheus.middleware.PrometheusBeforeMiddleware',
    # ... остальные middleware
    'django_prometheus.middleware.PrometheusAfterMiddleware',
]
 
# urls.py
urlpatterns = [
    path('', include('django_prometheus.urls')),
    # ...
]

Метрики на http://your-app:8000/metrics.

Node.js (Express)

npm install prom-client
const express = require("express");
const client = require("prom-client");
 
const app = express();
 
// Создаём registry
const register = new client.Registry();
 
// Собираем дефолтные метрики (CPU, memory, event loop)
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"],
  registers: [register],
});
 
// Middleware для метрик
app.use((req, res, next) => {
  const start = Date.now();
  res.on("finish", () => {
    const duration = (Date.now() - start) / 1000;
    httpRequestDuration
      .labels(req.method, req.route?.path || req.path, res.statusCode)
      .observe(duration);
  });
  next();
});
 
// Endpoint для Prometheus
app.get("/metrics", async (req, res) => {
  res.set("Content-Type", register.contentType);
  res.end(await register.metrics());
});
 
app.listen(3000);

Добавляем приложение в Prometheus

Отредактируйте prometheus/prometheus.yml:

scrape_configs:
  # ... existing jobs
 
  - job_name: "myapp"
    static_configs:
      - targets: ["host.docker.internal:8000"] # Ваше приложение

Если приложение в Docker Compose, используйте имя сервиса:

- job_name: "myapp"
  static_configs:
    - targets: ["myapp:8000"]

Перезапустите Prometheus:

docker compose restart prometheus

Проверьте в Prometheus UI: StatusTargets — ваше приложение должно быть в статусе UP.

Настройка логов с Loki

Loki собирает логи из вашего приложения.

Вариант 1: Promtail (рекомендуется)

Promtail — агент для сбора логов и отправки в Loki.

Добавьте в docker-compose.yml:

promtail:
  image: grafana/promtail:3.3.2
  container_name: promtail
  volumes:
    - /var/log:/var/log:ro # Логи системы
    - ./promtail/config.yml:/etc/promtail/config.yml
    - ./logs:/app/logs:ro # Логи вашего приложения
  command: -config.file=/etc/promtail/config.yml
  restart: unless-stopped
  networks:
    - monitoring

Создайте promtail/config.yml:

server:
  http_listen_port: 9080
  grpc_listen_port: 0
 
positions:
  filename: /tmp/positions.yaml
 
clients:
  - url: http://loki:3100/loki/api/v1/push
 
scrape_configs:
  # Логи вашего приложения
  - job_name: app
    static_configs:
      - targets:
          - localhost
        labels:
          job: app
          __path__: /app/logs/*.log
 
  # Системные логи (опционально)
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: syslog
          __path__: /var/log/syslog

Перезапустите стек:

docker compose up -d

Вариант 2: Логирование напрямую из приложения

Python (python-logging-loki):

pip install python-logging-loki
import logging
from logging_loki import LokiHandler
 
logger = logging.getLogger("my-app")
logger.setLevel(logging.INFO)
 
loki_handler = LokiHandler(
    url="http://loki:3100/loki/api/v1/push",
    tags={"application": "my-app", "environment": "production"},
    version="1",
)
 
logger.addHandler(loki_handler)
 
logger.info("Application started")
logger.error("Something went wrong", extra={"user_id": 123})

Просмотр логов в Grafana

  1. Откройте Grafana
  2. Explore → выберите Loki data source
  3. Запрос: {job="app"}
  4. Нажмите Run query

Вы увидите логи вашего приложения в реальном времени.

Полезные запросы Loki (LogQL):

# Все логи приложения
{job="app"}
 
# Только ошибки
{job="app"} |= "ERROR"
 
# Логи конкретного пользователя
{job="app"} | json | user_id="123"
 
# Rate ошибок за последние 5 минут
rate({job="app"} |= "ERROR" [5m])

Алерты: чтобы не проспать падение прода

Алерты — самая важная часть мониторинга. Настроим alerting в 3 шага.

Шаг 1: Добавляем правила алертов

Отредактируйте prometheus/alerts.yml:

groups:
  - name: critical_alerts
    interval: 30s
    rules:
      # Сервер недоступен
      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Instance {{ $labels.instance }} is down"
          description: "{{ $labels.job }} has been down for more than 1 minute."
 
      # CPU больше 80%
      - alert: HighCPU
        expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High CPU usage on {{ $labels.instance }}"
          description: "CPU usage is above 80% for 5 minutes (current: {{ $value }}%)"
 
      # RAM больше 90%
      - alert: HighMemory
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "High memory usage on {{ $labels.instance }}"
          description: "Memory usage is above 90% (current: {{ $value }}%)"
 
      # Диск больше 85%
      - alert: DiskSpaceLow
        expr: (1 - (node_filesystem_avail_bytes{fstype!~"tmpfs|fuse.lxcfs"} / node_filesystem_size_bytes)) * 100 > 85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Low disk space on {{ $labels.instance }}"
          description: "Disk {{ $labels.mountpoint }} is {{ $value }}% full"
 
      # Высокий error rate (>5% запросов с ошибками)
      - alert: HighErrorRate
        expr: rate(app_requests_total{status=~"5.."}[5m]) / rate(app_requests_total[5m]) > 0.05
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "High error rate in {{ $labels.job }}"
          description: "Error rate is {{ $value | humanizePercentage }} for 5 minutes"
 
      # Медленные запросы (p95 latency > 1s)
      - alert: SlowRequests
        expr: histogram_quantile(0.95, rate(app_request_duration_seconds_bucket[5m])) > 1
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Slow requests in {{ $labels.job }}"
          description: "95th percentile latency is {{ $value }}s"

Перезагрузите конфиг Prometheus:

curl -X POST http://localhost:9090/-/reload

Проверьте алерты: http://your-server-ip:9090/alerts

Шаг 2: Настройка Alertmanager (уведомления)

Alertmanager отправляет уведомления в Telegram, Slack, email и т.д.

Добавьте в docker-compose.yml:

alertmanager:
  image: prom/alertmanager:v0.27.0
  container_name: alertmanager
  ports:
    - "9093:9093"
  volumes:
    - ./alertmanager/config.yml:/etc/alertmanager/config.yml
    - alertmanager_data:/alertmanager
  command:
    - "--config.file=/etc/alertmanager/config.yml"
  restart: unless-stopped
  networks:
    - monitoring
 
volumes:
  # ... existing volumes
  alertmanager_data:

Отредактируйте prometheus/prometheus.yml:

# Добавьте в начало файла
alerting:
  alertmanagers:
    - static_configs:
        - targets: ["alertmanager:9093"]

Создайте alertmanager/config.yml:

global:
  resolve_timeout: 5m
 
route:
  group_by: ["alertname", "cluster"]
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 12h
  receiver: "telegram"
 
receivers:
  # Telegram (рекомендуется)
  - name: "telegram"
    telegram_configs:
      - bot_token: "YOUR_BOT_TOKEN" # Получите у @BotFather
        chat_id: YOUR_CHAT_ID # Ваш chat_id
        parse_mode: "HTML"
        message: |
          <b>{{ .Status | toUpper }}</b>
          {{ range .Alerts }}
          <b>Alert:</b> {{ .Labels.alertname }}
          <b>Severity:</b> {{ .Labels.severity }}
          <b>Summary:</b> {{ .Annotations.summary }}
          <b>Description:</b> {{ .Annotations.description }}
          {{ end }}
 
  # Slack (альтернатива)
  # - name: 'slack'
  #   slack_configs:
  #     - api_url: 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL'
  #       channel: '#alerts'
  #       title: 'Alert: {{ .GroupLabels.alertname }}'
  #       text: '{{ range .Alerts }}{{ .Annotations.description }}{{ end }}'
 
  # Email (альтернатива)
  # - name: 'email'
  #   email_configs:
  #     - to: 'your-email@example.com'
  #       from: 'alerts@yourapp.com'
  #       smarthost: 'smtp.gmail.com:587'
  #       auth_username: 'your-email@gmail.com'
  #       auth_password: 'your-app-password'

Перезапустите стек:

docker compose up -d

Как получить Telegram bot token и chat_id:

  1. Создайте бота: напишите @BotFather → /newbot → следуйте инструкциям → получите bot_token
  2. Узнайте chat_id: напишите боту /start, затем откройте https://api.telegram.org/bot<bot_token>/getUpdates → найдите "chat":{"id":123456789}

Шаг 3: Тестируем алерты

Создадим искусственную нагрузку для теста:

# Загружаем CPU
yes > /dev/null &
yes > /dev/null &
yes > /dev/null &
yes > /dev/null &
 
# Через 5 минут должен сработать алерт HighCPU
# Проверьте: http://your-server-ip:9090/alerts
 
# Остановите нагрузку:
killall yes

Вы должны получить уведомление в Telegram в течение 5-6 минут.

Алерты работают! Теперь вы узнаете о проблемах раньше, чем клиенты.

Дашборды для реальной жизни

Готовые дашборды — это хорошо, но для production нужны кастомные.

Дашборд "Application Health"

Создайте новый дашборд в Grafana:

Панели:

  1. RPS (Requests Per Second)

    • Query: rate(app_requests_total[1m])
    • Визуализация: Graph
  2. Error Rate (%)

    • Query: (rate(app_requests_total{status=~"5.."}[5m]) / rate(app_requests_total[5m])) * 100
    • Визуализация: Graph
    • Threshold: warning при 1%, critical при 5%
  3. Latency (p50, p95, p99)

    • Query:
      histogram_quantile(0.50, rate(app_request_duration_seconds_bucket[5m]))  # p50
      histogram_quantile(0.95, rate(app_request_duration_seconds_bucket[5m]))  # p95
      histogram_quantile(0.99, rate(app_request_duration_seconds_bucket[5m]))  # p99
    • Визуализация: Graph
  4. Active Users (если есть метрика)

    • Query: active_users_gauge
    • Визуализация: Stat
  5. Top 5 Slowest Endpoints

    • Query: topk(5, histogram_quantile(0.95, rate(app_request_duration_seconds_bucket[5m])))
    • Визуализация: Table

Дашборд "Infrastructure"

  1. CPU Usage

    • Query: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
  2. Memory Usage

    • Query: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
  3. Disk I/O

    • Query: rate(node_disk_read_bytes_total[5m]) и rate(node_disk_written_bytes_total[5m])
  4. Network Traffic

    • Query: rate(node_network_receive_bytes_total[5m]) и rate(node_network_transmit_bytes_total[5m])

Troubleshooting: как расследовать проблемы

Вы получили алерт в 3 ночи. Что делать?

Сценарий 1: HighCPU alert

  1. Grafana → дашборд Infrastructure → смотрим CPU график
  2. Correlate: смотрим RPS в это же время — если spike в трафике, виноват код
  3. Logs in Loki: {job="app"} | json | line_format "{{.endpoint}} {{.duration}}" — ищем медленные эндпоинты
  4. Prometheus: topk(5, rate(app_request_duration_seconds_sum[5m])) — топ медленных запросов
  5. Fix: оптимизируем код или масштабируем

Сценарий 2: HighMemory alert

  1. Grafana → Infrastructure → Memory Usage
  2. Prometheus: process_resident_memory_bytes — смотрим потребление памяти приложением
  3. Logs: {job="app"} |= "OutOfMemory" или |= "MemoryError"
  4. Hypothesis: утечка памяти? Проверяем код
  5. Temporary fix: docker compose restart app
  6. Long-term fix: профилируем код (memory_profiler, py-spy)

Сценарий 3: HighErrorRate alert

  1. Grafana → Application Health → Error Rate график
  2. Prometheus: rate(app_requests_total{status=~"5.."}[5m]) — какие эндпоинты?
  3. Loki: {job="app"} |= "ERROR" or "Exception" — читаем стектрейсы
  4. Root cause: база недоступна? API упал? Timeout?
  5. Fix: в зависимости от причины

Сценарий 4: SlowRequests alert

  1. Prometheus: histogram_quantile(0.95, rate(app_request_duration_seconds_bucket[5m])) by endpoint
  2. Loki: находим конкретные медленные запросы с параметрами
  3. Database: проверяем pg_stat_statements — может быть, slow query?
  4. Fix: добавляем индексы, кешируем, оптимизируем

Pro tip: создайте Runbook для каждого алерта. Документ с шагами расследования и типичными решениями. Сохранит часы времени в 3 ночи.

Best Practices: что я усвоил за годы

1. Retention Policy

По умолчанию Prometheus хранит метрики 15 дней. Это мало. Установите 30-90 дней:

command:
  - "--storage.tsdb.retention.time=90d"

Для Loki:

# loki-config.yaml
limits_config:
  retention_period: 30d

2. Не мониторьте всё подряд

Метрики стоят памяти и диска. Мониторьте только то, что помогает принимать решения:

  • Мониторить: RPS, error rate, latency, CPU, RAM, disk
  • Не мониторить: количество кликов на каждую кнопку (это для аналитики, не observability)

3. Гигиена оповещений

  • Группируйте алерты: не шлите 50 уведомлений за минуту, группируйте по 1 каждые 5 минут
  • Severity levels: critical → звонок, warning → Telegram, info → только логи
  • Mute when deploying: во время деплоя отключайте алерты, иначе false positives

4. Backup конфигов

Храните конфиги в Git:

git init
git add docker-compose.yml prometheus/ grafana/ alertmanager/
git commit -m "Initial monitoring setup"
git remote add origin git@github.com:yourname/monitoring-config.git
git push

5. Security

  • Не открывайте порты наружу: используйте Nginx reverse proxy с auth
  • Смените дефолтный пароль Grafana
  • Ограничьте доступ к Prometheus: он может показать чувствительные данные

Продвинутые фишки

Remote Write (долгосрочное хранение)

Prometheus хранит метрики локально. Для долгосрочного хранения (годы) используйте remote write в:

  • Thanos — open source, S3-backed storage
  • Cortex — мультитенантный Prometheus
  • Grafana Cloud — managed (бесплатно до 10k series)

ServiceMonitor (для Kubernetes)

Если у вас Kubernetes, используйте Prometheus Operator + ServiceMonitor:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app: myapp
  endpoints:
    - port: metrics
      interval: 30s

Distributed Tracing (Tempo)

Для микросервисов добавьте Grafana Tempo:

tempo:
  image: grafana/tempo:latest
  command: ["-config.file=/etc/tempo.yaml"]
  volumes:
    - ./tempo.yaml:/etc/tempo.yaml
  ports:
    - "3200:3200" # Tempo UI
    - "4317:4317" # OTLP gRPC

Интегрируйте с OpenTelemetry SDK в приложении.

Стоимость владения

Реальные цифры из моей практики:

Стоимость self-hosted стека (в месяц):

  • VPS 4GB RAM (Hetzner CX31): $7
  • Хранилище 50GB (если нужно больше): $5
  • Время на setup: 4-8 часов (один раз)
  • Время на поддержку: 1-2 часа в месяц

Итого: $12-15/месяц + 2 часа времени

Стоимость SaaS-альтернатив:

  • Datadog: $100-500/месяц (зависит от объёма)
  • New Relic: $99-749/месяц
  • Grafana Cloud: $0-299/месяц (free tier до 10k series)

ROI: за 3 месяца экономия $300-1500. За год — $1200-6000.

Но главная экономия — не потерянная выручка из-за простоев. Один даунтайм на час может стоить $1000-10000 в зависимости от проекта.

Мониторинг окупается после первого инцидента, который вы предотвратили. У меня это была первая неделя.

Выводы

Что мы сделали:

  • Подняли Prometheus + Grafana + Loki за час
  • Настроили метрики приложения и инфраструктуры
  • Создали алерты с уведомлениями в Telegram
  • Построили дашборды для мониторинга и troubleshooting
  • Научились расследовать проблемы

Что дальше:

  1. Добавьте метрики из всех критичных компонентов: база данных, кеш, очереди, внешние API
  2. Настройте алерты под ваш SLA: если у вас 99.9% uptime, downtime > 43 минуты в месяц — критичен
  3. Создайте runbook для каждого алерта: документ "что делать, если..."
  4. Обучите команду: все должны уметь читать метрики и логи
  5. Автоматизируйте: добавьте мониторинг в CI/CD, чтобы метрики появлялись автоматически

Главный урок:

Мониторинг — это не опция, а необходимость. Чем раньше вы его настроите, тем больше нервов, денег и клиентов сохраните.

Не ждите, пока production упадёт в 3 ночи. Настройте мониторинг прямо сейчас.


P.S. У вас вопросы по настройке мониторинга для вашего проекта? Пишите в комментарии или на email — помогу разобраться.