Настройка парсинга и обогащения логов (Logstash/Fluentd)

Когда сервисы пишут события в разных форматах, команда теряет часы на поиск причины сбоя. Мы настраиваем разбор и обогащение логов под ключ: приводим данные к единому виду и добавляем к ним контекст. Время расследования сокращается в разы, а дежурный видит полную картину.
Часто задаваемые вопросы

Парсинг логов: где ломается разбор и что теряет команда

Конвейер сбора логов выглядит ровно до того момента, когда очередной сервис меняет формат вывода. Агент читает файл, буфер сглаживает пики, парсер раскладывает строку по полям, индекс получает структуру — и именно на этом участке начинается расхождение между тем, что команда ожидает увидеть, и тем, что реально лежит в хранилище.

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

Дальше вступает цена. Битые строки логов занимают объём, но не отвечают на вопросы: по ним нельзя отфильтровать по коду ответа, длительности или идентификатору запроса — только искать подстроку вручную. Структурирование логов, которого не случилось, оборачивается потерей контекста инцидента: записи из нескольких сервисов приходится сводить по времени и надеяться, что метки совпадут. Отладка маски занимает минуты, а разбор аварии без структуры — часы.

Ниже разбираем, как это закрывается: где чинить разбор, как удерживать многолинейные записи целиком и какие проверки ставить на сам конвейер, чтобы неразобранное событие было видно сразу, а не в момент отказа.

Эффект от разбора и обогащения: что меняется в работе

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

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

Обогащение событий добавляет к записи то, чего нет в самой строке: узел и версию релиза, зону доступности, владельца сервиса. Конфигурация парсеров и фильтров лежит рядом с описанием источника и версионируется вместе с ним — в Elastic это делается теми же декларативными правилами, что и в альтернативных сборщиках. Тогда причина инцидента находится фильтром по атрибутам, а не по памяти о том, кто как пишет логи.

На эксплуатации эффект виден в измеримых величинах: доля распознанных строк доходит до 98-99%, путь от сигнала мониторинга до понятной причины сокращается с часов до минут, а объём хранимого перестаёт расти, потому что мусорные строки отсекаются на входе. Отдельно закрываются классы отказов самих логов — нераспознанный шаблон, отставание доставки и разрыв между источником и приёмником становятся видимыми метриками, а не сюрпризом в момент разбора.

Парсинг логов: разбор на узле или централизованный конвейер

Разбор логов можно разместить в трёх точках: на самом узле до отправки, в централизованном конвейере потоковой обработки событий или позже — по уже сохранённым сырым данным. Точка разбора определяет, где тратится процессор, какой объём уходит по сети и как быстро новые поля становятся доступны для поиска, оповещений и корреляции.

Варианты редко конкурируют напрямую: рабочие схемы комбинируют разбор на узле для горячих полей и централизованный разбор для тяжёлых шаблонов. Границы применимости каждого:

Вариант Когда подходит Ограничения
Разбор на узле Однотипные сервисы, стабильный формат, узкий канал связи Тратит процессор и память боевого хоста; шаблоны надо синхронизировать по всем узлам; ошибку видно только на реальном трафике
Централизованный разбор Много разнородных источников, общее обогащение и маршрутизация Конвейер становится точкой отказа: при всплеске растёт задержка и появляются потери; сырьё всё равно идёт по сети
Потоковая обработка событий Поля нужны сразу — для оповещений, метрик, корреляции Жёсткие требования к схеме и буферизации; обогащение на лету дороже хранения сырых данных
Отложенный разбор Архив, расследования, редко читаемые логи Поля появляются с задержкой, оповещения на них не построить, разбор по запросу замедляет ответ

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

Как мы внедряем разбор и обогащение событий: этапы

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

  1. Инвентаризация источников логов. Обходим приложения, сервисы, балансировщики, планировщики задач и базы: формат записи (структурированный или свободный текст), часовой пояс, суточный объём, наличие идентификатора запроса. Результат — реестр источников с ответственным за каждый.
  2. Схема разбора. Для каждого типа события описываем набор полей, а регулярные выражения оставляем только там, где структуру не отдаёт сам источник. Схему проверяем на выборке реальных записей, включая многострочные трассировки ошибок.
  3. Правила обогащения. Дописываем то, чего нет в источнике: привязку к сервису и команде-владельцу, расшифровку кодов ошибок, разметку окружения, приведение уровней важности к общему словарю. Обогащение делаем в коллекторе, а не в системе хранения — правила живут в одном месте.
  4. Проверка на потоке. Новую схему включаем параллельно с текущей и сравниваем поля и долю разобранных событий на живом трафике. Если доля неразобранных записей выше порога, правило уходит на доработку, а не в основную ветку.
  5. Защита от всплесков и потерь. Задаём размер очереди, поведение при переполнении и контроль задержки доставки. Потери и повторы считаем отдельными метриками — конвейер не должен терять события молча.
  6. Передача конвейера. Конфигурации, тесты и описание полей кладём в систему контроля версий, изменения проходят проверку. Команде отдаём регламент: как подключить новый источник, как изменить правило, кто дежурит и что смотреть при расхождении.

Конфигурации, схемы и регламенты: что остаётся команде

Мы передаём не набор разовых правок, а рабочий контур сбора, который команда сопровождает сама. Всё, что описывает поведение конвейера, лежит в системе контроля версий и согласуется как обычный код: история изменений восстановима, откат к предыдущей версии занимает минуты.

  • Конфигурация конвейера — описание приёма, разбора и маршрутизации событий отдельными файлами, с шаблонами под каждый тип источника и набором контрольных сообщений для проверки правок.
  • Схема потоков событий — откуда приходят данные, через какие звенья проходят, где оседают и что происходит при недоступности любого из них; точки отказа отмечены явно.
  • Шаблоны разбора — правила под каждый формат источника: структурированный JSON, системный журнал, свободный текст. Отдельно описано поведение при появлении незнакомых полей, чтобы новый формат не ломал разбор целиком.
  • Политики доступа к событиям — роли и зоны видимости: какие потоки доступны какой команде, сколько они хранятся и в каком порядке выдаётся доступ новому участнику.
  • Правила маскирования чувствительных полей — что заменяется или хешируется на входе, до попадания в хранилище: учётные данные, идентификаторы пользователей, персональные данные.
  • Регламент изменений — кто предлагает правку, кто проверяет, как она обкатывается на тестовом контуре, при каких условиях откатывается и кто отвечает при инциденте.
  • Набор проверок и метрик — контрольные события, прогоняемые через конвейер после каждого изменения, и оповещения о потере событий или росте очереди.

После передачи разбираем с командой реальные инциденты: где смотреть, что править и как убедиться, что правка не сломала разбор. Дальше контур живёт без нас — подключаемся точечно, когда меняется источник или растёт поток.

Кейс: разбор и обогащение событий в высоконагруженном сервисе

Высоконагруженный сервис писал события в хранилище сырым текстом: одна строка смешивала уровень важности, идентификатор запроса, код ответа и пользовательские данные. Разбор выполнялся уже в момент поиска, шаблонами регулярных выражений, которые ломались на каждом нестандартном сообщении.

Что было до изменений

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

Что изменили

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

Метрика До После
Доля неразобранных событий 34% 1,2%
Поиск причины инцидента ~40 минут 4 минуты
Объём хранилища на тот же поток рос линейно втрое меньше
Глубина разбора инцидента выборочно весь поток

Остаток неразобранных событий теперь предсказуем: новые форматы сообщений ловит проверка на этапе сборки, а не дежурный во время отказа.

Что делать, если сервисы пишут события в несогласованных форматах

Разнородные форматы логов — норма для зрелого продукта: один сервис пишет структурированный JSON, другой — плоский текст с парами ключ-значение, третий — многострочные трассировки ошибок. Переписывать их ради единообразия никто не станет, поэтому приведение к единой схеме делают на слое сбора: Fluentd или Logstash разбирает событие на входе, в хранилище уходит уже нормализованная запись.

Первый шаг — зафиксировать обязательный минимум полей: время, имя сервиса, уровень, идентификатор запроса; остальное остаётся расширяемой частью. За основу имён берём семантические соглашения OpenTelemetry — тогда выгрузку читает любой инженер, а не только автор сервиса.

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

Схему версионируем: номер версии проставляется в само событие при разборе, и потребители какое-то время читают обе версии параллельно. Это снимает главный риск — переход без остановки сервисов и без одновременной правки всех панелей и правил оповещения.

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

Технические сомнения: производительность, потери и дубли

За этими сомнениями стоит один риск: сбор логов перестаёт быть вспомогательным и начинает влиять на сервисы или на бюджет хранения. Ниже — как каждый сценарий закрывается в конфигурации агента и приёмника.

Агент на каждом узле не замедлит сами сервисы?

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

Что станет с событиями, если узел или приёмник упадёт?

Доставка с подтверждением и повторами: недоотправленное лежит в локальном буфере. После перезапуска агент дочитывает файл с последней подтверждённой позиции.

Повторы не дадут дублей в отчётах?

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

Как сбор переживает резкий всплеск нагрузки?

Очередь на диске сглаживает всплеск: события ждут, а не теряются. Задаём лимиты по объёму и времени ожидания, чтобы очередь не выела диск.

Объём хранения не вырастет быстрее, чем польза?

Парсинг на стороне агента отбрасывает лишние поля до записи, а lifecycle-правила держат горячие данные отдельно от тёплых и чистят старое. Шумные источники переводим на выборочный сбор — реестр перестаёт расти линейно.

Обсудим задачу: разбор под ваш поток событий и состав данных

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

  • 5–10 примеров сырых событий из каждого источника — как есть, вместе с многострочными записями и явно нестандартными строками: по ним подбираются шаблоны разбора и проверяется их устойчивость.
  • Схема конвейера на сегодня: откуда берутся события, где стоит сборщик (Logstash или Fluentd), есть ли промежуточный буфер и кто читает результат — хранилище, мониторинг или аналитика.
  • Перечень полей, которые нужны в разобранном и обогащённом виде, и правила связывания: по адресу, идентификатору запроса, справочникам соответствия, гео- и сервисным атрибутам.
  • Профиль нагрузки: средняя и пиковая частота событий, суточный рост, требуемая глубина хранения и допустимое время задержки до появления записи в хранилище.
  • Требования к чувствительным данным: что маскировать на входе, что вырезать полностью, сколько хранить в открытом виде и кто имеет доступ.
  • Доступы для пилотного сегмента: чтение одного-двух источников и площадка, где развернём контур, не затрагивая рабочий поток.
  • Жёсткие ограничения: окна обслуживания, требования к откату, контуры, куда данные не должны уходить.

После разбора вернёмся со схемой конвейера, порядком этапов плана внедрения и оценкой работ, разбитой по этапам. Пилотный сегмент запускаем на одном-двух источниках — качество разбора проверяется на живой нагрузке до раскатки на весь поток. Опишите задачу — пришлём оценку и план.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка логотипа компании B2B Advance
    Разработка логотипа компании B2B Advance
    816
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1142