Помню день, когда наша производственная система вышла из строя в 2 часа ночи. Наш генеральный директор спросил: «Что случилось?», и у меня было три варианта: посмотреть на панели управления, которые не показывали ничего полезного, порыться в терабайтах логов с помощью grep или помолиться. Спойлер: я помолился. И тогда я понял, что мы всё делали неправильно.

Сейчас, спустя некоторое время, наблюдаемость стала Святым Граалем современной инженерии. Но вот грязный секрет, о котором вам не расскажут вендоры: вам не нужен годовой контракт на шестизначную сумму с SaaS-платформой, чтобы обеспечить достойную наблюдаемость. Вам нужны понимание, стратегия и немного усердной работы.

Эта статья — моё личное путешествие по построению прагматичной наблюдаемости при ограниченном бюджете. Независимо от того, являетесь ли вы стартапом, сжигающим венчурный капитал, или устоявшейся компанией, уставшей от усталости SaaS-подписок, это руководство покажет вам, как реализовать три столпа наблюдаемости — метрики, логи и трейсы — не продавая своего первенца.

Почему наблюдаемость важна (и почему традиционный мониторинг не работает)

Прежде чем мы углубимся в детали, давайте определимся, чем наблюдаемость отличается от традиционного мониторинга. Традиционный мониторинг — это как термостат: он показывает текущую температуру, не больше. Наблюдаемость — это как врач, который может задать вам вопросы и диагностировать проблему.

Метрики — это жизненные показатели вашего приложения. Использование ЦП, частота запросов, количество ошибок — это числовые измерения, агрегированные во времени. Они эффективны и идеально подходят для информационных панелей и оповещений.

Логи — это неизменяемые записи с меткой времени, показывающие, что на самом деле произошло. Они предоставляют детальный контекст об определённой ошибке или операции, сообщая вам подробности о том, что пошло не так в определённый момент.

Трейсы представляют собой полное, сквозное путешествие одного запроса по мере его распространения через ваши микросервисы. Они отвечают на важнейший вопрос о том, где возникла проблема в вашем сложном рабочем процессе.

Магия происходит, когда вы объединяете эти три сигнала. Специалист по надёжности системы может начать с оповещения о метрике высокого уровня, углубиться в конкретное сообщение об ошибке в логе и точно увидеть, какой нисходящий вызов службы failed. Это и есть наблюдаемость.

Проверка реальности бюджета

Давайте будем честными: платформы наблюдаемости для предприятий стоят дорого. Мы говорим о 10 000–100 000 долларов и более ежегодно в зависимости от объёма данных. Для многих организаций, особенно стартапов, это непозволительная роскошь.

Хорошая новость? Экосистема с открытым исходным кодом значительно продвинулась вперёд. Вы можете построить производственную стек наблюдаемости, используя:

  • Prometheus для метрик (бесплатно, проверен в боях);
  • Loki или ELK Stack для логов (бесплатно/дёшево);
  • Jaeger или Zipkin для распределённого трейсинга (бесплатно);
  • OpenTelemetry в качестве стандарта инструментирования (бесплатно).

Ваши единственные реальные затраты — это инфраструктура (которая у вас всё равно будет) и эксплуатационные усилия (которые научат вас большему, чем любое аутсорсинг-решение).

Понимание метрик: фундамент

Метрики — это ваш обзор на высоком уровне. Это агрегированные числа с тегами — например, «количество HTTP-запросов в секунду» или «использование пула соединений с базой данных».

Почему метрики важны

Метрики отлично подходят для:

  • Обнаружения базовых аномалий («наш уровень ошибок только что подскочил на 10%»);
  • Создания информационных панелей для руководителей («вот наш показатель времени безотказной работы за этот квартал»);
  • Настройки оповещений («уведомляй меня, когда этот порог будет превышен»);
  • Эффективного хранения (метрика занимает килобайты, а не гигабайты).

Практическая реализация с Prometheus

Prometheus — это стандарт де-факто для сбора метрик. Вот минимальная настройка:

# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
scrape_configs:
  - job_name: 'my-app'
    static_configs:
      - targets: ['localhost:8080']
  - job_name: 'node-exporter'
    static_configs:
      - targets: ['localhost:9100']

На стороне вашего приложения экспортируйте метрики, используя библиотеку, совместимую с вашим языком. Вот пример на Go с использованием клиента Prometheus:

package main
import (
    "net/http"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
    requestCounter = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Общее количество HTTP-запросов",
        },
        []string{"method", "endpoint", "status"},
    )
    requestDuration = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Name:    "http_request_duration_seconds",
            Help:    "Задержка HTTP-запроса",
            Buckets: prometheus.DefBuckets,
        },
        []string{"method", "endpoint"},
    )
)
func init() {
    prometheus.MustRegister(requestCounter)
    prometheus.MustRegister(requestDuration)
}
func main() {
    http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        // Ваша бизнес-логика здесь
        w.WriteHeader(http.StatusOK)
        w.Write([]byte(`{"status": "ok"}`))
        // Запись метрик
        requestCounter.WithLabelValues(
            r.Method,
            "/api/users",
            "200",
        ).Inc()
        requestDuration.WithLabelValues(
            r.Method,
            "/api/users",
        ).Observe(time.Since(start).Seconds())
    })
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8080", nil)
}

Ключевые метрики для отслеживания

Каждое приложение должно предоставлять эти базовые метрики:

  • Частота запросов: количество запросов в секунду (с разбивкой по конечной точке и методу);
  • Уровень ошибок: процент неудачных запросов;
  • Задержка: p50, p95, p99 время ответа;
  • Использование ресурсов: ЦП, память, дисковый ввод-вывод;
  • Бизнес-метрики: регистрация пользователей, завершённые транзакции, выручка.

Запрос метрик с PromQL

Prometheus использует PromQL для запросов. Некоторые основные запросы:

# Частота запросов за последние 5 минут
rate(http_requests_total[5m])
# 95-й процентиль задержки
histogram_quantile(0.95, http_request_duration_seconds)
# Уровень ошибок
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m])
# Использование памяти в МБ
node_memory_MemAvailable_bytes / 1024 / 1024

Понимание логов: подробная история

Пока метрики дают вам заголовок, логи дают вам полный отчёт расследования. Это текстовые записи, которые фиксируют, что произошло, почему это произошло и весь контекст.

Иерархия логов

Уровни логов существуют не просто так:

  • DEBUG: Информация для разработки, подробный вывод;
  • INFO: Нормальные операции, ключевые события;
  • WARNING: Что-то неожиданное произошло, но мы восстановились;
  • ERROR: Что-то failed, возможно, потребуется вмешательство вручную;
  • CRITICAL: Система в плохом состоянии, требуется немедленное действие.

Структурированный логирование: игра меняется

Разница между хорошим и плохим логированием заключается в структуре. Сравните эти примеры:

Плохой: "Ошибка обработки запроса"
Хороший: {"timestamp": "2026-02-14T14:30:45Z", "level": "error", "service": "payment-service", "user_id": "usr_123", "error": "insufficient_funds", "amount": 99.99, "request_id": "req_456"}

Структурированное логирование (в формате JSON) позволяет вам без усилий искать, фильтровать и сопоставлять логи. Вот пример на Python:

import logging
import json
from pythonjsonlogger import jsonlogger
# Настройка JSON-логирования
logHandler = logging.StreamHandler()
formatter = jsonlogger.JsonFormatter()
logHandler.setFormatter(formatter)
logger = logging.getLogger()
logger.addHandler(logHandler)
logger.setLevel(logging.INFO)
# Использование
logger.info("payment_processed", extra={
    "user