Что логировать в проде

Хороший лог инференса — это то, что позволит расследовать инцидент через месяц.

Логирование инференса — сохранение по каждому предсказанию входа, выхода, версии модели и контекста, чтобы обеспечить мониторинг дрейфа, отладку и аудит.

Зачем логировать больше обычного

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

Разберём каждую цель. Отладка: пользователь жалуется «модель выдала ерунду на моём запросе» — без сохранённого входа вы не воспроизведёте случай и будете гадать. С логом вы берёте ровно те признаки, что видела модель, прогоняете локально и находите причину (битый вход? редкий кейс? баг препроцессинга?). Аудит: в регулируемых отраслях (кредиты, страхование, медицина) нужно уметь объяснить любое решение модели задним числом — «почему этому клиенту отказали 3 марта». Лог предсказаний с входами и версией модели — это юридически значимая запись. Мониторинг: дрейф и качество считаются не из воздуха, а из накопленных логов — это их единственный источник данных.

Именно поэтому в ML логируют то, что в обычном бэкенде сочли бы избыточным: полный вход и выход каждого предсказания, а не только факт «запрос обработан за 18 мс». Для ML-системы эти данные — не шум, а топливо для замыкания цикла обратной связи.

Минимальный набор полей

ПолеЗачем
request_idсвязать предсказание с пришедшей позже меткой
timestampвременные окна для дрейфа и анализа
входные признакирасчёт дрейфа, воспроизведение бага
предсказание (и вероятность)аудит решений, расчёт качества
model_versionпривязать просадку к конкретной версии
latency_msоперационный мониторинг

Структурированный лог

Лог должен быть машиночитаемым (JSON), а не строкой для человека — по нему будут считать метрики.

{
  "request_id": "req-8f3a",
  "timestamp": "2026-06-22T10:15:03Z",
  "model_version": "fraud-detector:v7",
  "features": {"age": 34, "income": 52000, "orders_30d": 3},
  "prediction": {"label": 1, "probability": 0.83},
  "latency_ms": 18
}

Как лог замыкается на качество

Поле request_id — мостик к будущему. Когда через дни придёт настоящая метка («платёж действительно был мошенническим»), её джойнят с логом по request_id и считают, угадала ли модель. Без этого ключа предсказание и метку не связать, и качество не измерить.

лог(request_id, prediction) ----+
                                 |--- join по request_id ---> качество
метка(request_id, truth) -------+

Чего НЕ логировать

  • Персональные данные в открытом виде. Логировать признаки нужно с оглядкой на приватность: маскировать/хешировать чувствительные поля (152-ФЗ, GDPR).
  • Лишний объём. Логировать всё подряд дорого; сэмплируйте, если поток огромен, но сохраняя репрезентативность для дрейфа.

Как работает под капотом

Сервис пишет структурированную запись в поток логов (stdout → агент → хранилище, или сразу в Kafka). Оттуда данные текут в два места: в систему метрик (агрегаты латентности, частоты ошибок) и в хранилище для офлайн-анализа (расчёт дрейфа по окнам, джойн с метками для качества). Версия модели в каждой записи позволяет разбивать все метрики по версиям — критично при канареечном деплое, когда в проде одновременно две версии.

Частые ошибки

  • Не логировать входные признаки. Тогда дрейф не посчитать и баг не воспроизвести.
  • Забыть request_id. Без него предсказание не связать с будущей меткой — качество измерить нельзя.
  • Не писать версию модели. При двух версиях в проде непонятно, кто виноват в просадке.
  • Логировать PII в открытую. Нарушение приватности и закона.

Итог

  • Лог инференса — сырьё для дрейфа, качества и аудита: вход, выход, версия модели, время, request_id, латентность.
  • request_id связывает предсказание с запаздывающей меткой — без него качество не посчитать.
  • Логи структурированы (JSON), версия модели в каждой записи, PII маскируется.
Проверьте себя
1. Зачем в логе инференса нужен request_id?
AДля красоты
BЧтобы позже связать предсказание с пришедшей меткой и посчитать качество
CЧтобы ускорить сервис
DЭто требование JSON
2. Почему в каждой записи лога важна версия модели?
AЧтобы лог был длиннее
BЧтобы разбивать метрики по версиям, особенно при двух версиях в проде (канарейка)
CВерсия не нужна
DЧтобы шифровать данные
3. Зачем логировать входные признаки, а не только предсказание?
AЧтобы занять место
BБез них нельзя посчитать дрейф данных и воспроизвести баг
CПризнаки не важны
DТак требует Kubernetes