Чем парсить логи в ubuntu

Обновлено: 01.07.2024

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

Кому интересно, добро пожаловать под кат)

Необходимы базовые знания bash, docker-compose, Elasticsearch и Kibana.

Обзор используемого стека

Тестовое приложение будем запускать с помощью docker-compose.

Для организации логгирования воспользуемся следующими технологиями:

kibana - предоставляет интерфейс пользователю, для визуализации данных хранимых в elasticsearch

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

Подготовка тестового приложения

Для примера организуем логгирование веб-сервера Nginx.

Подготовка Nginx

Создадим директорию с проектом и добавим в нее docker-compose.yml, в котором будем задавать конфигурацию запуска контейнеров приложения.

Определим формат логов Nginx. Для этого создадим директорию nginx c файлом nginx.conf. В нем переопределим стандартный формат логов:

Добавим сервис web в docker-compose.yml:

Подготовка fluent-bit

Для начала организуем самый простой вариант логгирования. Создадим директорию fluent-bit c конфигурационным файлом fluent-bit.conf. Про формат и схему конфигурационного файла можно прочитать здесь.

Добавим в docker-compose.yml сервис fluent-bit:

Добавим настройки логгирования для сервиса web:

Запустим тестовое приложение:

временной метки, добавляемой fluent-bit;

мета данных, добавляемых драйвером fluentd.

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

Кратко о маршрутизации лог-сообщиний в fluent-bit

Выглядит все следующим образом:

Отделение логов запросов от логов ошибок

На текущий момент логи посылаемые Nginx можно разделить на две категории:

логи с предупреждениями, ошибками;

Добавим новый фильтр rewrite_tag. Ниже приведена его конфигурация.

Обновим конфигурационный файл fluent-bit.conf. Подключим к нему файл с конфигурацией парсера и добавим фильтр parser.

Теперь необходимо добавить файл parsers.conf в контейнер, сделаем это путем добавления еще одного volume к сервису fluent-bit:

Добавим в docker-compose.yml сервисы elasticsearch и kibana.

На текущем этапе структура проекта выглядит следующим образом:

Финальную версию проекта можно найти в репозитории.

Результаты

Так уж сложилось, что по долгу работы мне приходится много времени уделять логам. Это и участие в выработке правил и политик сбора/хранения/использования логов, это и разбор разных инцидентов и обнаружение аномалий. За сутки наши программы, сервисы и серверы генерируют ОЧЕНЬ большое количество логов. И потребность копания в логах растёт постоянно.
Мне довелось поработать с коммерческими лог-менеджмент продуктами типа ArcSight, RSA Envision, Q1 Labs. У этих продуктов есть как плюсы, так и минусы. Но в статье речь пойдёт не о них.
Речь будет о Logstash.

Что же такое Logstash? Зачем он нужен? Что он умеет?

Logstash — это орудие для сбора, фильтрации и нормализации логов. Оно является бесплатным и open source приложением. Тип лицензии Apache 2.0.

Первой моё знакомство с LS (Logstash) произошло более года назад, и с того времени я очень плотно на него подсел. Мне нравится его идея и возможности. Для меня Logstash — это подобие мясорубки. Неважно что заходит в неё, но после не сложных манипуляций, на выходе всегда красиво и понятно оформленная информация.

Формат конфигурационного файла Logstash'а прост и понятен. Он состоит из трёх частей:

1. INPUT

Данный метод является входной точкой для логов. В нём определяет по каким каналам будут логи попадать в Logstash.
В этой статье я попытаюсь вас ознакомит с основными типами, которые я использую — это file, tcp и udp.

Пример конфигурации, для работы с локальными лог-файлами:


Построчное описание настроек:
тип/описание лога. При использовании нескольких входных блоков, удобно их разделять для последующих действий в filter или output.

указывается путь к лог-файлам, которые подлежат обработке. Путь должен быть абсолютным (/path/to/logs/), а не относительным (../../some/other/path/).

исключает из обработки файлы с соответствующими расширениями.

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

время (в секундах) через которое будет обновлён список обрабатываемых файлов указанных в path.

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


Построчное описание настроек:
тип/описание лога.

время (в секундах), по истечении которого не активное tcp соединение будет закрыто. Значение -1 — соединение всегда будет открыто.

в этом случае Logstash становится сервером, и начинает слушать на 192.168.3.12:3337. При установке mode => «client» Logstash будет присоединятся к удалённому ip:port для забора логов.

2. FILTER

В данном блоке настраиваются основные манипуляции с логами. Это может быть и разбивка по key=value, и удаление ненужных параметров, и замена имеющихся значений, и использование geoip или DNS запросов для ип-адресов или названий хостов.

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

Пример конфигурационного файла для основной нормализации логов:


Построчное описание настроек:
тип/описание лога. Здесь надо указать тот тип (type), который прописан в блоке input для которого будет происходить обработка.

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

указывается шаблон разборки логов. Шаблон можно использовать либо в конфигурационном файле, либо из файла шаблонов. Что бы не путаться, я для каждого формата логов создаю отдельный шаблонный файл.

С помощью grok фильтра можно структурировать большую часть логов — syslog, apache, nginx, mysql итд, записанных в определённом формате.
Logstash имеет более 120 шаблонов готовых регулярных выражений (regex). Так что написание фильтров для обработки большинства логов не должно вызвать особого страха или недопонимания.

Формат шаблонов относительно простой — NAME PATTERN, то есть построчно указывается имя шаблона и ему соответствующее регулярное выражение. Пример:

Можно использовать любой ранее созданный шаблон:

Шаблоны можно так же и комбинировать:


Допустим формат логов у нас следующий:
55.3.244.1 GET /index.html 15824 0.043

Среди готовых шаблонов, к счастью уже имеются некоторые регулярные выражения и не надо придумывать колёсное транспортное средство, приводимое в движение мускульной силой человека через ножные педали или через ручные рычаги (это я про велосипед если что).
С данным примером лога достаточно pattern записать в виде "% % % % % ", в этом случае все логи с данным форматом будут уже иметь некую логическую структуру.
После обработки наша строка будет выглядеть следующим образом:

client: 55.3.244.1
method: GET
request: /index.html
bytes: 15824
duration: 0.043

Со списком готовых grok-шаблонов можно познакомиться здесь.

Пример конфигурационного файла для изменения/удаления записей из логов:

Построчное описание настроек:
тип/описание лога. Указывается тип (type) логов с которыми будет происходить обработка.

удаление всех данных имеющих название поля client. Возможно указание нескольких названий полей.

переименование название поля HOSTORIP в client_ip.

замена всех "/" на "_" в поле messages.

добавление нового поля «sample1» со значением «from %». Допускается использование названий переменных.

Пример конфигурационого файла:

Построчное описание настроек:
тип/описание лога. Указывается тип (type) логов с которыми будет происходить обработка.

временная метка события. Важная настройка для дальнейшей возможности сортировки или выборки логов. Если в логах время указано в unix timestamp (squid), то следует использовать match => [ «timestamp», «UNIX» ]

Пример конфигурационного файла для обработки логов в формате key=value:

Построчное описание настроек:
тип/описание лога. Указывается тип (type) логов с которыми будет происходить обработка.

использовать символы "=" и ":" для разделения ключа-значения.

название поля в котором искать 'ключ=значение'. По умолчанию разбивка будет происходить для всей строки лога.

использовать символы "\t?&" для разделения ключей. \t — знак табулятора

Пример конфигурационного файла для «склеивания» многострочных логов (например Java stack trace):

Построчное описание настроек:
тип/описание лога. Указывается тип (type) логов с которыми будет происходить обработка.

при соответствии шаблону «pattern» строка принадлежит предыдущей (previous) строке.

3. OUTPUT

Пример конфигурационного файла для вывода логов в standard output:

Пример конфигурационого файла для записи логов в файл:

Пример конфигурационного файла для записи логов в базу Elasticsearch:

название кластера указанного в cluster.name в настроечном файле Elasticsearch.

указывает какую базу Elasticsearch использовать внутреннюю или стороннюю.

транспортный port Elasticsearch.

IP адрес Elasticsearch

название индекса куда будут записываться логи.

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

если у вас хватило сил дочитать до этих строк, значит вы можете сами определить смысл этих 3х настроек :)

тема письма уведомления. Можно использовать переменные. Например % — название условия совпадения из настройки «match».

способ отсылки письма. Возможен один вариант из двух — smtp или sendmail.

стандартные настройки почтовых параметров.

«response errors» — название алерта (записывается в переменную %). «response,501,,or,response,301» — критерии срабатывания алертов. В данном примере если поле response содержит значение 501 или 301, то алерт считается сработавшим. Во второй строке используется логика AND, т.е. оба условия должны быть выполнены.

4. Итого

Создаём файл habr.conf:


Запускаем Logstash:
java -jar logstash-1.1.9-monolithic.jar agent -f ./habr.conf

В новом терминальном окне пишем:
echo "Logs are cool!" | nc localhost 11111

Смотрим результат в окне где запущен Logstash. Если там появилось секретное послание, значит всё работает.


Мануал

Если вы хотите оптимизировать свой веб-сервер, необходимо понимать access логи Nginx.

Оно также играет свою роль в обнаружении дефектов в веб-разработке.

Журналы доступа Nginx содержат подробную информацию о запросах пользователей.

Для анализа и мониторинга вашего веб-сервера необходимо разбирать логи Nginx.

Как разобрать access логи Nginx

Как пользователь Linux, вы можете использовать два метода для парсинга доступа к Nginx.

Вы можете либо использовать команды Linux, либо воспользоваться инструментом анализатора журналов.

Выполнение команд Linux спарсит логи Nginx для указанной функции, в то время как при парсинге с помощью любого инструмента анализатора вы можете получить полный отчет.

В этой статье будут продемонстрированы оба метода разбора логов доступа Nginx.

Как спарсить журнал доступа Nginx для получения списка IP-адресов

В этом разделе будет показано, как получить IP-адреса клиентов с помощью команды Linux.

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

Как спарсить логи доступа Nginx для получения списка доступа к файлам

Как спарсить логи доступа Nginx для подсчета количества запросов в секунду

Вы можете выполнить эту операцию, выполнив простую команду Linux, а именно:


В результате выполнения приведенной выше команды все запросы будут отсортированы, и для каждого из них будет проставлена временная метка. Здесь первое число представляет собой количество запросов: Этот код указывает на событие, которое должно произойти. Вы можете проанализировать журналы доступа Nginx для получения кодов ответа. Для этого в терминале Linux выполните приведенные ниже команды:


Как спарсить логи доступа Nginx с помощью онлайн-анализаторов

Неважно, используете ли вы Nginx в качестве сервера статического контента, балансировщика нагрузки или веб-сервера, вы наверняка захотите просмотреть журналы доступа, чтобы понять, насколько хорошо он работает.

Существует несколько вариантов инструментов Nginx, например Goaccess, Visitors, ELK Stack.

Вы можете выбрать инструмент анализатора в соответствии с вашими требованиями.

Однако для демонстрации процедуры разбора журналов доступа Nginx с помощью онлайн-анализатора мы выбрали Goaccess.

Чтобы использовать Goaccess для разбора журналов доступа Nginx, необходимо сначала установить его в вашей системе:

fluentd

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

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

В течение последних нескольких лет появились интересные программные инструменты позволяющие решать описанные выше проблемы. Всё большую популярность обретают решения, позволяющие хранить и обрабатывать логи онлайн: Splunk,Loggly, Papertrail, Logentries и другие. В числе несомненных плюсов этих сервисов следует назвать удобный интерфейс и низкую стоимость использования (да и в рамках базовых бесплатных тарифов они предоставляют весьма неплохие возможности). Но по при работе с большими количествами логов они зачастую не справляются с возлагаемыми на них задачами. Кроме того, их использование для работы с большими количествами информации нередко оказывается невыгодным с чисто финансовой точки зрения.

Гораздо более предпочтительным вариантом является развёртывание самостоятельного решения. Мы задумались над этим вопросом, когда перед нами встала необходимось собирать и анализировать логи облачного хранилища.

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

Общая информация

Fluend был разработан Садаюки Фурухаси, сооснователем компании Treasure Data(она является одним из спонсоров проекта), в 2011 году. Он написан на Ruby. Fluentd активно развивается и совершенствуется (см. репозиторий на GitHub, где обновления стабильно появляются раз в несколько дней).

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

Fluentd

В качестве основных преимуществ Fluentd можно выделить следующие:

  • Низкие требования к системным ресурсам. Для нормальной работы Fluentd вполне достаточно 30 — 40 Мб оперативной памяти; скорость обработки при этом составляет 13 000 событий в секунду.
  • Использование унифицированного формата логгирования. Данные, полученные из разных источников, Fluentd переводит в формат JSON. Это помогает решить проблему сбора логов из различных систем и открывает широкие возможности для интеграции с другими программными решениями.
  • Удобная архитектура. Архитектура Fluentd позволяет расширять имеющийся набор функций с помощью многочисленных плагинов (на сегодняшний день их создано более 300). С помощью плагинов можно подключать новые источники данных и выводить данные в различных форматах.
  • Возможность интеграции с различными языками программирования. Fluentd может принимать логи из приложений на Python, Ruby, PHP, Perl, Node.JS, Java, Scala.

Fluentd распространяется бесплатно под лицензией Apache 2.0. Проект достаточно подробно документирован; на официальном сайте и в блоге опубликовано немало полезных обучающих материалов.

Установка

В рамках этой статьи мы описываем процедуру установки для ОС Ubuntu 14.04. С инструкциями по установке для других операционных систем можно ознакомиться здесь.

Установка и первоначальная настройка Fluentd осуществляются с помощью специального скрипта. Выполним команды:

По завершении установки запустим Fluentd:

Конфигурирование

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

Fluentd

Настройки fluentd (какие данные и откуда брать, каким критериям они должны соответствовать, куда их переправлять) прописываются в конфигурационном файле /etc/td-agent/td-agent.conf, который строится из следующих блоков:

  • source — содержит информацию об источнике данных;
  • match — содержит информацию о том, куда нужно передавать полученные данные;
  • include — содержит информацию о типах файлов;
  • system — содержит настройки системы.

Рассмотрим структуру и содержание этих блоков более подробно.

Source: откуда брать данные

Match: что делать с данными

В секции Match указывается, по каком признаку будут отбираться события для последующей обработки. Для этого используются специализированные плагины.

К стандартным плагинам вывода относятся match и forward:


В приведённом фрагменте указано, что все события, отмеченные тэгами myapp и access, нужно сохранять в файле, путь к которому указывается в директиве path. Обратим внимание на то, что события, которые помимо тэгов myapp и access отмечены ещё и другими тэгами, в файл отправлены не будут.
Кратко рассмотрим особенности синтаксиса директивы match:

  • символ * означает соответствие любой части тэга (если указать <match a.*>, то a.b будет соответствовать заданному условию, а a.b.c — нет);
  • ** означает соответствие любому тэгу (если указать <match **>, то заданному условию будут соответствовать и a, и a.b., и a.b.c);
  • означает соответствие по крайней мере одному из тэгов, указанных в фигурных скобках (если указать <match >, то а и b будут соответствовать заданному условию, а с — нет);
  • фигурные скобки можно использоовать в сочетании с символами * и **, например: <match . c.*> или <match .c>*;
  • <match a b> означает соответствие тэгам a и b одновременно;
  • <match a.** b.*> означает соответствие тэгам a, a.b и a.b.c (первая часть) и b.d (вторая часть).

Fluentd проверяет события на соответствие тэгам в том порядке, в котором блоки match следуют друг за другом в конфигурационном файле. Сначала указываются соответствия частного характера, а затем — более общие соответствия. Если это правило нарушено, Fluentd корректно работать не будет. Так, фрагмент вида

содержит ошибку: сначала в нём указаны предельно общие совпадения (<match **> означает, что в файл нужно записывать события, отмеченные любым тэгом), а затем — частные. Допущенная ошибка приведёт к тому, что события с тэгами myapp и access записываться вообще не будут. Чтобы все работало так, как надо, фрагмент должен выглядеть так:

Include: объединяем конфигурационные файлы

Директивы можно импортировать из одного конфигурационного файла в другой и объединять. Эта операция осуществляется в блоке include:

В этой директиве можно указывать путь к одному или нескольким файлам с указанием маски или URL:

System: устанавливаем дополнительные настройки

В блоке System можно установить дополнительные настройки, например, задать уровень логгирования (подробнее см. здесь), включить ии отключить опцию удаления повторяющихся записей из логов и т.п.

Поддерживаемые типы данных

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

  • string — строка;
  • integer — целое число;
  • float — число с плавающей точкой;
  • size — число байт; возможны следующие варианты записи:
    • <целое число>k — размер в килобайтах;
    • <целое число>g — размер в гигабайтах;
    • <целое число>t — размер терабайтах;
    • если никакой единицы измерения не указано, то значение в поле size будет воспринято как число байт.
    • <целое число>s — время в секундах;
    • <целое число>m — время в минутах;
    • <целое число>h — время в часах;
    • <целое число>d — время в днях;
    • если никакой единицы измерения не указано, что значение в поле time будет воспринято как количество секунд.

    Плагины Fluentd: расширяем возможности

    В Fluentd используется 5 типов плагинов: плагины вывода, плагины ввода, плагины буферизации, плагины форм и плагины парсинга.

    Плагины ввода

    Плагины вывода

    Плагины вывода делятся на три группы:

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

    К плагинам без буферизации относятся:

    • out_copy — копирует события в указанное место (или несколько мест);
    • out_null — этот плагин просто выбрасывает пакеты;
    • out_roundrobin — записывает события в различные локации вывода, которые выбираются методом кругового перебора;
    • out_stdout — моментально записывает события в стандартный вывод (или в файл лога, если он запущен в режиме демона).
    • out_exec_filter — запускает внешнюю программу и считывает событие из её вывода;
    • out_forward — передаёт события на другие узлы fluentd;
    • out_mongo (или out_mongo_replset) — передаёт записи в БД MongoDB.

    Плагины буферизации

    • buf_memory — изменяет объём памяти, используемой для хранения буферизованных данных (подробнее см. в официальной документации);
    • buf_file — даёт возможность хранить содержимое буфера в файле на жёстком диске.

    Плагины форматирования

    С помощью плагинов форматирования можно изменять формат данных, полученных из логов. К стандартным плагинам этой группы относятся:

    • out_file — позволяет кастомизировать данные, представленные в виде «время — тэг — запись в формате json»;
    • json — убирает из записи в формате json поле «время» или «тэг»;
    • ltsv — преобразует запись в формат LTSV;
    • single_value — выводит значение одного поля вместо целой записи;
    • csv — выводит запись в формате CSV/TSV.

    Более подробно о плагинах форматирования можно прочитать здесь.

    Плагины парсинга

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

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

    Общие параметры для всех плагинов

    Для всех плагинов указываются также следующие параметры:

    • type — тип;
    • id — идентификационный номер;
    • log_level — уровень логгирования (см. выше).

    На официальном сайте fluentd выложены готовые конфигурационные файлы, адаптированные под различные сценарии использования (см. здесь).

    Вывод данных и интеграция с другими решениями

    Собранные с помощью Fluentd могут быть переданы для хранения и дальнейшей обработки в базы данных (MySQL, PostgreSQL, CouchBase, CouchDB, MongoDB, OpenTSDB, InfluxDB) распределенные файловые системы (HDFS — см. также статью об интеграции Fluentd c Hadoop) облачные сервисы (AWS, Google BigQuery), поисковые инструменты (Elasticsearch, Splunk, Loggly).
    Для обеспечения возможности поиска и визуализации данных довольно часто используется комбинация Fluentd+Elasticsearc+Kibana (подробную инструкцию по установке и настройке см., например, здесь).

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

    Заключение

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

    С проблемой сбора и анализа логов, наверное, сталкивались многие из вас. Было бы интересно узнать, какими инструментами вы пользуетесь для её решения и почему вы выбрали именно их. А если вы используете Fluentd — поделитесь опытом в комментариях.
    Если вы по тем или иным причинам не может оставлять комментарии здесь — добро пожаловать в наш блог.

    Читайте также: