Типичные ошибки логирования

Соберём в один чек-лист грабли, на которые наступают почти все, кто строит логирование на ELK.

Антипаттерны логирования — типовые ошибки конфигурации и культуры логов, которые приводят к падению кластера, потере данных или росту счетов.

Зачем отдельный урок про ошибки

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

Ошибка 1: взрыв полей (mapping explosion)

Самая опасная. Если в логи попадают динамические ключи{"user_42_clicks": 3}, {"error_in_method_calculatePrice": true} — Elasticsearch заводит новое поле в маппинге под каждый уникальный ключ. Маппинг разрастается до тысяч полей, потребление памяти кластера взлетает, и в какой-то момент он падает. Лечение: фиксированный набор ключей, динамические значения класть в значения, а не в имена полей.

  ПЛОХО (имя поля динамическое):
  { "user_42_action": "login" }   --> новое поле на каждого юзера

  ХОРОШО (значения в значениях):
  { "user_id": 42, "action": "login" }  --> два стабильных поля

Ошибка 2: нет ротации / нет ILM

Логи растут вечно. Без ILM с фазой delete (или хотя бы внешней очистки) индексы заполняют диск под ноль, и кластер встаёт. Это не «может быть», а вопрос времени. Лечение из раздела 7: ILM с rollover и delete, заданные с самого старта.

Ошибка 3: логировать слишком много

DEBUG в проде, health-check'и каждую секунду, дублирование одного события в нескольких местах — всё это раздувает объём и счёт, зашумляет поиск. Полезного сигнала тонет в шуме. Лечение: разумные уровни логирования, drop для health-check'ов, семплирование частых событий (раздел 5).

Ошибка 4: логи без структуры и стандарта

Каждый сервис логирует в своём формате, со своими именами полей и часовыми поясами. Дашборд «ошибки по сервисам» приходится подгонять под каждый, корреляция мучительна. Лечение: структурированные JSON-логи по единому стандарту (ECS), сквозной trace_id (разделы 5 и 8).

Ошибка 5: типы полей

Числа как строки (status = "500"), идентификаторы как text вместо keyword — и числовые сравнения с агрегациями ломаются. Лечение: явный маппинг в index template, приведение типов на обработке (:int в grok, convert в mutate).

Как работает под капотом: почему именно эти ошибки фатальны

Объединяет их одно: они бьют по кластеру в целом, а не по отдельному запросу. Взрыв полей раздувает cluster state — структуру, которую каждый узел держит в памяти и синхронизирует; отсутствие ротации убивает общий ресурс — диск; переизбыток логов перегружает индексацию для всех. Поэтому они валят систему целиком, а не «чуть тормозят». Отсюда вывод: дисциплина логирования — это не эстетика, а условие стабильности.

Чек-лист здорового логирования

ДелатьНе делать
фиксированный набор полейдинамические ключи в именах полей
ILM с delete с первого дняхранить логи вечно
структурный JSON по ECSкаждый сервис в своём формате
drop шума, разумные уровниDEBUG и health-check в прод-индекс
явный маппинг типовполагаться на динамический маппинг
сквозной trace_idлоги без корреляции

Откуда берутся эти ошибки

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

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

Итоги

  • Взрыв полей (динамические ключи) — самая частая причина падения кластера логов; держите набор полей фиксированным.
  • Без ILM/ротации диск однажды кончится — настраивайте удаление с первого дня.
  • Переизбыток логов и отсутствие единого структурного стандарта зашумляют систему и ломают корреляцию.
  • Эти ошибки бьют по кластеру целиком — дисциплина логирования есть условие стабильности, а не вкусовщина.
Проверьте себя
1. Что такое взрыв полей (mapping explosion) и почему он опасен?
AСлишком длинные сообщения логов
BДинамические ключи в именах полей заставляют ES создавать новое поле под каждый уникальный ключ, раздувая маппинг и память кластера вплоть до падения
CСлишком много индексов
DОшибка в grok-шаблоне
2. Почему отсутствие ILM/ротации логов — вопрос времени, а не вероятности?
AЛоги портятся со временем
BЛоги растут непрерывно, и без удаления старого диск рано или поздно заполняется под ноль, останавливая кластер
CElasticsearch требует ротации по лицензии
DKibana перестаёт работать через месяц
3. Что объединяет самые фатальные ошибки логирования (взрыв полей, нет ротации, переизбыток логов)?
AОни замедляют только один запрос
BОни бьют по кластеру в целом — cluster state, общий диск, индексация для всех — поэтому валят систему целиком
CИх легко заметить сразу
DОни касаются только Kibana