МАТЕРИАЛЫ КУРСА
СИИ • НАВИГАЦИЯ

Наблюдаемость: метрики, логи, трейсы

Три столпа, стек Prometheus + Loki + Grafana, что мерить в AI-продукте и как связать три источника

Наблюдаемость: метрики, логи, трейсы

Мониторинг отвечает на вопрос «работает ли?», наблюдаемость — на вопрос «почему сломалось?», причём для поломки, которую вы не предвидели. Разница практическая: первое — это график с зелёной галочкой, второе — возможность за десять минут дойти от «пользователь жалуется» до конкретной строчки и конкретного запроса.

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

Три столпа и вопросы, на которые они отвечают

СтолпЧто этоВопросИнструмент
МетрикиЧисла во времени, дёшево хранитьЧто и когда пошло не так?Prometheus
ЛогиСобытия с контекстом, дорожеЧто именно произошло в этот момент?Loki
ТрейсыПуть одного запроса по системеГде потерялось время и на каком шаге упало?Tempo, Langfuse

Порядок расследования всегда один: метрика показывает аномалию, трейс находит шаг, лог объясняет причину. Стек нужен целиком именно потому, что каждый следующий шаг без предыдущего означает «искать вручную».

  • Prometheus ходит по /metrics ваших сервисов и складывает ряды. Формат простой текстовый, клиентские библиотеки есть везде.
  • Loki хранит логи не как полнотекстовый индекс, а по меткам (service, env, level) — поэтому дёшево и хорошо ложится на один сервер.
  • Grafana — одно окно: дашборды поверх обеих баз и алерты.

Что мерить в AI-продукте

Обычные четыре сигнала (нагрузка, задержка, ошибки, насыщение) остаются, но добавляются свои — иначе продукт «работает», а денег нет:

  • Стоимость. Токены и рубли на запрос, на пользователя, в сутки. Метрика, которая раньше всех показывает, что промпт распух.
  • Задержка отдельно для вызовов модели. Общий p95 API маскирует то, что модель отвечает по восемь секунд.
  • Доля деградаций. Как часто сработал фолбэк, ретрай, кэш вместо живого ответа — это альтернативы из ваших UC, ставшие метрикой.
  • Качество. Доля ответов, не прошедших проверку формата или валидацию; оценки из evals по свежему трафику.

Полезное правило: если в UC написано «система деградирует на архив» — это счётчик. Не измеряете деградации — не узнаете, что продукт наполовину живёт на фолбэках.

Связка: один запрос — одна история

Три столпа сходятся только при общем идентификаторе. trace_id рождается на входе в систему, кладётся в лог каждой записи, в спан трейса и в атрибуты трейса LLM. Тогда из графика в Grafana можно провалиться в конкретный запрос, а из него — в логи именно этого запроса.

Без этого получается три отдельных инструмента и ручное сопоставление по времени — то, ради чего наблюдаемость и заводили, не работает.

Минимум для лабы 3–4:

# compose.yml — стек рядом с продуктом
services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
  loki:
    image: grafana/loki:latest
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
    volumes:
      - grafana:/var/lib/grafana

volumes:
  grafana:

Дашборды и источники данных тоже as-code: JSON дашборда и provisioning-файлы лежат в monitoring/ в репозитории. Дашборд, собранный кликами и живущий только в одном браузере, — это не артефакт, его нельзя ни сдать, ни восстановить.

Алерты

Алерт имеет смысл, только если на него кто-то реагирует ночью или его не должно быть. Для проекта курса хватает трёх:

  1. Сервис не отвечает (health-чек падает N минут).
  2. Доля ошибок выше порога за окно.
  3. Стоимость за сутки превысила бюджет.

Всё остальное смотрится глазами на дашборде: когда алертов много, команда перестаёт на них реагировать.

Дальше — Langfuse: третий столп для той части системы, где обычные трейсы бесполезны.