Раздел 40 · Elasticsearch и ELK

Discover и язык запросов KQL

junior~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Логи собраны, разобраны на поля и лежат в Elasticsearch. Дежурный «Гонца» открывает Kibana, раздел Discover, и пишет в строке поиска. Не JSON на десять строк, как в консоли, а короткую строку вроде service.name : payments and log.level : ERROR. Это KQL, язык запросов Kibana. Разберём его по шагам.

Экран Discover

У Discover четыре части:

  • строка запроса сверху, туда пишут KQL;
  • полоса времени рядом с ней: за какой период искать. Kibana превратит её в фильтр по полю @timestamp;
  • гистограмма: сколько событий в каждый отрезок времени. По ней сразу видно всплески;
  • таблица документов и список полей слева. Клик по полю добавляет его колонкой.

Какие индексы Discover ищет, задаёт data view, об этом урок 14. В нашей учебной Discover это logs-*.

Основы KQL

ЗапросЧто найдёт
service.name : paymentsполе равно значению
log.level : ERROR and service.name : paymentsоба условия
log.level : (ERROR or WARN)любое из значений поля
not log.level : INFOвсё, кроме
http.response.status_code >= 500сравнение чисел и дат: >, >=, <, <=
url.original : /api/payments*звёздочка: любое продолжение
error.type : *у документа есть поле
message : "Bank gateway"фраза в кавычках, слова подряд
Bankслово в любом поле

Пара тонкостей:

  • and сильнее or, как в математике умножение сильнее сложения. Если сомневаешься, ставь скобки: (a or b) and c.
  • Текстовые поля сравниваются по словам после анализа, как match, а точные поля keyword целиком, как term. service.name : Payments с большой буквы не найдёт payments.
  • Запрос без имени поля ищет по всем полям сразу. Удобно, но медленнее и находит случайные совпадения.

Поле меняет смысл запроса

Представь карточку заказа. На ней есть номер, имя клиента и свободный комментарий. Номер ищут целиком: заказ 104549 не тот же самый, что 10454. Комментарий ищут по словам: фраза «позвони перед доставкой» должна находиться по слову «доставкой». У логов такая же разница.

service.name и log.level описывают категории, поэтому в учебных данных имеют тип keyword. Запрос service.name : payments проверяет одно точное значение. Поле message содержит человеческое описание события и имеет тип text. Для него Elasticsearch разбирает запрос и документ на слова своим анализатором. Поэтому message : gateway может найти и Bank gateway timeout, и Bank gateway connection reset.

Кавычки не превращают текстовое поле в точное. Они задают фразу: message : "Bank gateway" ищет эти слова рядом в указанном порядке. Полная строка документа при этом может содержать ещё слово timeout. Если нужно проверить всю строку целиком, нужен подходящий маппинг, а не ещё одна пара кавычек.

Проверяй имя поля по списку Discover, а не по внешнему виду сообщения. Число 504 внутри message и число в http.response.status_code различаются: первое часть текста, второе значение типизированного поля. Условие http.response.status_code >= 500 сравнивает числа. Поиск message : 504 ищет слово и может пропустить событие, где текст ошибки другой.

Скобки задают границу выбора

Дежурному нужны ошибки платежей и предупреждения платежей. Правильная мысль: «сервис payments, а уровень один из двух». Её прямо выражает service.name : payments and log.level : (ERROR or WARN). Скобки после имени поля позволяют не повторять log.level для каждого значения.

Без скобок запрос service.name : payments and log.level : ERROR or log.level : WARN читается иначе: сначала объединяются условия с and, потом добавляются все WARN, уже независимо от сервиса. Это не ошибка синтаксиса. Такой запрос выполнится и вернёт лишние события, поэтому опаснее незакрытой скобки.

Можно записать выбор и полностью: service.name : payments and (log.level : ERROR or log.level : WARN). Две записи дают одну и ту же границу поиска. Начни с полной формы, если сокращение мешает понять, к какому полю относится значение.

Звёздочка: продолжение или наличие

В url.original : /api/payments* звёздочка разрешает любое продолжение пути. Она не означает «похожий текст» и не исправляет опечатки. Например, путь /api/orders не подойдёт, а /api/payments/104549 подойдёт, если такое значение есть в данных.

В error.type : * перед звёздочкой нет начала слова. Здесь вопрос другой: есть ли у события индексированное значение поля. Это полезно, когда разные исключения имеют разные имена, а дежурному пока нужны все записи с заполненным типом ошибки.

Не путай отсутствие поля с безопасным событием. Лог nginx может описывать ответ 504, но вообще не иметь error.type. Для него ошибка выражена кодом HTTP. Выбор поля зависит от источника и вопроса расследования, а не от слова «ошибка» в голове.

урок из курса

Урок из курса «Elasticsearch и ELK». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.