Что логировать в проде
Хороший лог инференса — это то, что позволит расследовать инцидент через месяц.
Логирование инференса — сохранение по каждому предсказанию входа, выхода, версии модели и контекста, чтобы обеспечить мониторинг дрейфа, отладку и аудит.
Зачем логировать больше обычного
В обычном сервисе логируют ошибки и запросы. В 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 маскируется.