** multiline – для многострочных логов с разделителями.
Пример, можно лог в формате "дата тип число" разложить на составляющие, например "01.01.2021 INFO 1" разложить в хэш "message":
filter {
grok {
type => "my_log"
match => ["message", "%{MYDATE:date} %{WORD:loglevel} ${ID.id.int}"]
}
}
Шаблон ${ID.id.int} берёт класс – шаблон ID, полученное значение будет подставлено в поле id и строковое значение будет преобразовано к типу int.
В блоке «Output» мы можем указать: выводить данные в консоль с помощью блока "Stdout", в файл – "File", передавать по http через JSON REST API – "Elasticsearch" или отравлять по почте – "Email". Также можно заказать условия по полям, полученным в блоке filter. Например,:
output {
if [type] == "Info" {
elasticsearch {
host => localhost
index => "log-%{+YYYY.MM.dd}"
}
}
}
Здесь индекс Elasticsearch (база данных, если проводить аналогию с SQL) меняется каждый день. Для создания нового индекса не нужно его специально создавать – так поступают БД NoSQL, так как нет жёсткого требования описывать структуру – свойство и тип. Но всё же описать рекомендуется, иначе все поля будут со строковыми значениями, если не задано число. Для отображения данных Elasticsearch используется плагин WEB-ui интерфейса на AngularJS – Kibana. Для отображения временной шкалы в её графиках нужно описать хотя бы одно поле с типом дата, а для агрегатных функция – числовое, будь то целое или с плавающей точкой. Также, если добавляются новые поля, для их индексации и отображения требуется произвести пере индексацию всего индекса, поэтому наиболее полное описание структуры поможет избежать очень трудозатратные операции – переиндексации.
Разделение индекса по дням сделано для ускорения работы Elasticsearch, а в Kibana можно выбрать несколько по шаблону, здесь log-*, также снимается ограничение в один миллион документов на индекс.
Рассмотрим более подробный плагин вывода у Logstash:
output {
if [type] == "Info" {
elasticsearch {
claster => elasticsearch
action => "create"
hosts => ["localhost:9200"]
index => "log-%{+YYYY.MM.dd}"
document_type => ....
document_id => "%{id}"
}
}
}
Взаимодействии с ElasticSearch осуществляется через JSON REST API, драйвера для которых есть для большинства современных языков. Но для того, чтобы не писать код, мы воспользуемся утилитой Logstash, которая также он умеет преобразовывать текстовые данные в JSON на основе регулярных выражений. Также есть заготовленные шаблоны, наподобие классов в регулярных выражениях, таких как %{IP:client } и других, которые можно посмотреть по https://github.com/elastic/logstash/tree/v1.1.9/patterns. Для стандартных сервисов со стандартными настройками в интернете есть множество готовых конфигов, например, для NGINX – https://github.com/zooniverse/static/blob/master/logstash— Nginx.conf. Более подобно описано в статье https://habr.com/post/165059/.
ElasticSearch – NoSQL база данных, поэтому не нужно задавать формат (набор полей и его типы). Для поиска ему он всё же нужен, поэтому он сам его определяет, и при каждом смене формата происходит пере индексации, при котором работа невозможно. Для поддержания унифицированной структуры в логгере Serilog (DOT Net) есть поле EventType в которое можно зашифровать набор полей и их типы, для остальных придётся реализовывать отдельно. Для анализа логов от приложения микро сервисной архитектуры важно задать ID пока выполнения, то есть ID запроса, который будет неизменен и передаваться от микросервиса к микросервису, чтобы можно было проследить весь путь выполнения запроса.
Установим ElasticSearch (https://habr.com/post/280488/) и проверим работу curl -X GET localhost:9200
sudo sysctl -w vm.max_map_count=262144
$ curl 'localhost:9200/_cat/indices?v'
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open graylog_0 h2NICPMTQlqQRZhfkvsXRw 4 0 0 0 1kb 1kb
green open .kibana_1 iMJl7vyOTuu1eG8DlWl1OQ 1 0 3 0 11.9kb 11.9kb
yellow open indexname le87KQZwT22lFll8LSRdjw 5 1 1 0 4.5kb 4.5kb
yellow open db i6I2DmplQ7O40AUzyA-a6A 5 1 0 0 1.2kb 1.2kb
Создадим запись в базе данных blog и таблице post curl -X PUT "$ES_URL/blog/post/1?pretty" -d'
Поисковой движок ElasticSearch
В предыдущем разделе мы рассмотрели стек ELK, который составляют ElasticSearch, Logstash и Kibana. В полном наборе, а часто его ещё расширяют Filebeat – более заточенный на работу с расширение Logstash, для работы с текстовыми логами. Несмотря на то, что Logstash выполняет быстро свою задачу без необходимости, не используют, а логи в формате JSON отравляют через API загрузки дампа прямо в Logstash.
Если же у нас приложение, то применяется чистый ElasticSearch, который используется как поисковой движок, а Kibana используется как средство написания и отладки запросов – блок Dev Tools. Хотя и базы реляционные данных имеют долгую историю развития, всё же остаётся принцип, что чем более данные деморализованы, тем они медленнее, ведь их приходится при каждом запросе объединять. Данная проблема решается созданием View, в которой хранится результирующая выборка. Но хоть современные базы данных обзавелись внушительным функционалом, вплоть до полнотекстового поиска, но всё же им не сравниться в эффективности и функциональности поиска с поисковыми движками. Приведу пример с работы: несколько таблиц с метриками, который объединяются в запросе в одну, и производится поиск по выбранным параметрам в админке, таким как диапазон дат, страница в пагинации и содержания в сроке столбца чата. Данный не много, на выходе получаем таблицу в пол миллиона строк, да и поиск по дате и части строки укладывается в миллисекунды. А вот пагинации тормозит, в начальных страницах её запрос выполняется около двух минут, в конечных – более четырёх. При этом объединить запрос на логичен данных и на получения пагинации в лоб не получится. А тот же зарос, при этом он не оптимизирован, в ElasticSearch выполняется за 22 миллисекунды и содержит как данные и, так и число всех данных для пагинации.
Читать дальше