Короткий ответ
Структурированный лог записывается в виде набора полей с именами (обычно JSON: level, msg, service, trace_id и т.д.), а не произвольной строки текста; это позволяет системе агрегации логов искать, фильтровать и строить метрики по конкретным полям, а не парсить текст регулярными выражениями.
Как это работает подробнее
вместо строки "2024-05-01 10:02:11 ERROR checkout: payment failed for order a1b2" структурированный логгер пишет {"ts":"...","level":"error","service":"checkout","msg":"payment failed","order_id":"a1b2"}. Система агрегации (Elasticsearch, Loki с label-ами) может индексировать каждое поле отдельно и строить быстрые запросы по ним.
Пример кода
example.txt
# Plain text — сложно парсить программно
2024-05-01 10:02:11 ERROR checkout: payment failed for order a1b2, gateway timeout after 4200ms
# Структурированный JSON — легко искать по полям
{"ts":"2024-05-01T10:02:11Z","level":"error","service":"checkout","order_id":"a1b2","gateway_latency_ms":4200,"msg":"payment gateway timeout"}Что использовать на практике
- Практика. структурированные логи особенно важны в микросервисной архитектуре, где нужно быстро отфильтровать логи по
service,trace_idилиorder_idсреди миллионов строк от десятков сервисов; для нового проекта разумно сразу выбирать JSON-логирование через стандартную библиотеку логирования языка (например,logrus/zapдля Go,structlogдля Python), а не писать свободный текст. - Практика. В системе типа Loki запрос
{service="checkout"} | json | gateway_latency_ms > 3000сработает только на структурированном варианте лога, позволяя быстро найти все медленные платежи без regex по свободному тексту.
Подводные камни
- Частые ошибки. смешивать в одном сервисе разные форматы логов (часть JSON, часть plain text), из-за чего парсер в системе агрегации не может единообразно индексировать поля; включать в поля лога чувствительные данные (пароли, токены, полные номера карт) просто потому, что "так удобнее искать"; делать поля с нестабильным набором ключей, усложняя построение дашбордов на их основе.