Примеры логов
Примеры логов
Управление логами и аналитика позволяют точно определять и извлекать любые данные логов с помощью Языка запросов Ключ-АСТРОМ (DQL). После ознакомления с основами запросов DQL используйте примеры на этой странице, чтобы начать получать ответы из ваших данных логов.
Пример 1: Коды состояния и количество
В этом примере вы получаете распределение кодов состояния HTTP и количество ошибок по типам. Прокси-сервер записывает коды состояния HTTP-ответов. Вам нужно увидеть распределение кодов ответов за определённый временной диапазон и сосредоточиться на ошибках.
Поиск соответствующих логов
Начните с поиска логов от экземпляра HAProxy. Поскольку строка haproxy включена в сообщение лога, используйте функцию contains().
fetch logs | filter contains(content, "haproxy")
Поиск строки haproxy выполняется по всем записям за временной диапазон, поэтому его следует сузить для оптимизации запроса. Если сущность, создающая логи, может быть определена заранее, гораздо эффективнее искать в пределах этой конкретной сущности.
fetch logs | filter dt.entity.process_group=="PROCESS_GROUP-123F4A56BCDA0EA9"
Таблица результатов
| timestamp | content | log.source | dt.entity.host |
|---|---|---|---|
| 2022-08-10 14:05:42 2022-08-10T11:05:42Z | localhost haproxy[12529]: 123.45.67.891:23456 http-in~ individual_servers/abcde1 123/0/0/1/456 HTTP_STATUS 200 284 - - –NN 5749/5745/0/1/0… | /var/abcde/abc/defrghytji/HOST-1… | HOST-AB-12-34567 |
| 2022-08-10 14:05:46 2022-08-10T11:05:46Z | localhost haproxy[12528]: 12.345.67.123:12345 http-in~ local/local1 5432/0/0/103/1234 HTTP_STATUS 200 138 - - – 7416/7413/407/408/0 0/… | /var/abcde/abc/defrghytji/HOST-A2… | HOST-CD-76-54321 |
| 2022-08-10 14:05:50 2022-08-10T11:05:50Z | localhost haproxy[12529]: 11.222.33.123:45678 http-in~ local/local1 19/0/1/110/123 HTTP_STATUS 204 64 - - – 5753/5749/358/359/0 0/0… | /var/abcde/abc/defrghytji/HOST-A23… | HOST-AR-78-12345 |
Извлечение метрики из поля content
Поле content лога содержит нужные коды HTTP_STATUS. Теперь используйте команду parse, чтобы создать шаблон Языка шаблонов Ключ-АСТРОМ со следующими элементами:
LD: начните с сопоставления любых строчных данных в начале поля.'HTTP_STATUS ': литеральное выражение, которое непосредственно предшествует числовому HTTP-статусу и учитывает пробел.INT:httpstatus: целое число, которое будет выделено в новое полеhttpstatus.
fetch logs | filter dt.entity.process_group=="PROCESS_GROUP-123F4A56BCDA0EA9" | parse content, "LD 'HTTP_STATUS ' INT:httpstatus"
Таблица результатов
| timestamp | content | httpstatus |
|---|---|---|
| 2022-08-10 14:05:42 2022-08-10T11:05:42Z | localhost haproxy[12529]: 123.45.67.891:23456 http-in~ individual_servers/abcde1 123/0/0/1/456 HTTP_STATUS 200 284 - - –NN 5749/5745/0/1/ 0… | 200 |
| 2022-08-10 14:05:46 2022-08-10T11:05:46Z | localhost haproxy[12528]: 12.345.67.123:12345 http-in~ local/local1 5432/0/0/103/1234 HTTP_STATUS 200 138 - - – 7416/7413/407/408/0 0/… | 200 |
| 2022-08-10 14:05:50 2022-08-10T11:05:50Z | localhost haproxy[12529]: 11.222.33.123:45678 http-in~ local/local1 19/0/1/110/123 HTTP_STATUS 204 64 - - – 5753/5749/358/359/0 0/0… | 204 |
Фильтрация диапазона значений
Вы можете выбрать диапазон значений для дальнейшего анализа с помощью DQL. Мы выбираем только коды состояния HTTP, начинающиеся с 400 и выше, так как они включают ошибки на стороне клиента и сервера.
fetch logs | filter dt.entity.process_group=="PROCESS_GROUP-802F3A32CECA0EA9" | parse content, "LD 'HTTP_STATUS ' INT:httpstatus" | filter httpstatus >= 400
Агрегация результатов
Вам нужно агрегировать результаты с помощью count(), чтобы получить сводку о том, сколько раз встречается каждый код состояния.
fetch logs
| filter dt.entity.process_group=="PROCESS_GROUP-802F3A32CECA0EA9"
| parse content, "LD 'HTTP_STATUS ' INT:httpstatus"
| filter httpstatus >= 400
| summarize count(), by:{httpstatus}Таблица результатов
| count() | httpstatus |
|---|---|
| 4 | 403 |
| 779 | 404 |
| 1 | 500 |
| 9 | 503 |
Пример 2: Средний размер корзины
В этом примере вы определите средний размер корзины на основе логов. Ваше приложение записывает контекстные данные, relevant для вашего бизнеса. Вам нужно извлечь эти данные из логов и создать отчёт за определённый временной диапазон.
Выбор конкретных данных процесса за определённый временной диапазон
Вам нужно запросить логи за последние три часа (это ваш временной диапазон), а затем указать процесс, который обрабатывает действия с корзиной в вашем магазине, — cartservice cartservice-*.
fetch logs, from:now()-3h | filter dt.process.name=="cartservice cartservice-*"
Таблица результатов
| timestamp | content | log.source | dt.process.name |
|---|---|---|---|
| 2022-08-05 11:29:57 | {"@t":"2022-08-05T08:29:57.6864969Z","@m":"Slow GetCartAsync request detected for userId=a433448b-c38d-4144-9591-f510829d4gh2","@i":"abc0f94a"} | /var/log/pods/prod_cartservice-74c8d7d674-7dqf | cartservice cartservice-* |
| 2022-08-05 11:29:57 | {"@t":"2022-08-05T08:29:57.8068740Z","@m":"No carts for user ab51dc18-7724-44fb-cdf8-8bda633f0022","@i":"c9315217"} | /var/log/pods/prod_cartservice-74c8d7d674-7dqf | cartservice cartservice-* |
| 2022-08-05 11:29:58 | {"@t":"2022-08-05T08:29:57.6864541Z","@m":"GetCartAsync called with userId=z433448a-c38d-4123-9591-f510829d4ab2","@i":"1feab40c"} | /var/log/pods/prod_cartservice-74c8d7d674-7dqf | cartservice cartservice-* |
| 2022-08-05 11:30:01 | {"@t":"2022-08-05T08:30:01.1058085Z","@m":"Checking CartService Health","@i":"a01f1123"} | /var/log/pods/prod_cartservice-74c8d7d674-7dqf | cartservice cartservice-* |
Проверка типов и количества товаров, добавленных в корзины
Вам нужно получить обзор типов и количества товаров, которые пользователи добавили в свои корзины. Поскольку логи содержат различные события, нужно указать события, в которых товары были добавлены в корзины, используя функцию contains(). Чтобы очистить таблицу результатов, рекомендуется оставить только timestamp и содержимое лога.
fetch logs, from:now()-3h | filter dt.process.name=="cartservice cartservice-*" | filter contains(content, "AddItemAsync") | fields timestamp, content
Таблица результатов
| timestamp | content |
|---|---|
| 2022-08-05 11:55:04 | {"@t":"2022-08-05T08:55:04.9934166Z","@m":"AddItemAsync called with userId=a332eabc-f52f-40d5-a09f-51bb96f5d119, productId=1ZYFJ3GM2N, quantity=1","@i":"18b35248"} |
| 2022-08-05 11:55:07 | {"@t":"2022-08-05T08:55:07.1405993Z","@m":"AddItemAsync called with userId=5ddcdd66-f0fd-4608-839e-0cd7841a3bbc, productId=L2ECAV7KIM, quantity=5","@i":"04fe325f"} |
| 2022-08-05 11:55:32 | {"@t":"2022-08-05T08:55:32.5027148Z","@m":"AddItemAsync called with userId=66734557-683c-4864-b3c7-8f08b52f0b17, productId=LS3PSXUNUM, quantity=5","@i":"987426bd"} |
| 2022-08-05 11:30:01 | {"@t":"2022-08-05T08:55:58.6888309Z","@m":"AddItemAsync called with userId=c673ca76-3966-4174-b950-4c3f3aa22dfe, productId=4SIQT8TOJO, quantity=2","@i":"99a07cd5"} |
Извлечение товаров и соответствующих количеств
Вам нужно извлечь идентификаторы товаров и количества из логов с помощью команды parse. Используя Язык шаблонов Ключ-АСТРОМ, создайте шаблон и сопоставьте следующие части поля content:
LD: начните с сопоставления любых строчных данных в начале поля.'userId=': литеральное выражение, которое непосредственно предшествует ID пользователя.LD:userId: любые строчные данные, которые будут выделены в новое поле с именемuserId.', productId=': литеральное выражение, которое завершает ID пользователя и отделяет его от ID товара.LD:productId: любые строчные данные, которые будут выделены в новое поле с именемproductId.', quantity=': литеральное выражение, которое завершает ID товара и отделяет его от количества.INT:productQuantity: целое число, которое будет выделено в новое поле с именемproductQuantity.
Остальные поля игнорируются.
fetch logs, from:now()-3h | filter dt.process.name=="cartservice cartservice-*" | filter contains(content, "AddItemAsync") | fields timestamp, content | parse content, "LD 'userId=' LD:userId ', productId=' LD:productId ', quantity=' INT:productQuantity"
Таблица результатов
| timestamp | content | userId | productId | productQuantity |
|---|---|---|---|---|
| 2022-08-05 11:55:04 | {"@t":"2022-08-05T08:55:04.9934166Z","@m":"AddItemAsync called with userId=a332efea-f52f-40d5-a09f-51bb96f5d119, productId=1ZYFJ3GM2N, quantity=1","@i":"18b35248"} | a332efea-f52f-40d5-a09f-51bb96f5d119 | 1ZYFJ3GM2N | 1 |
| 2022-08-05 11:55:07 | {"@t":"2022-08-05T08:55:07.1405993Z","@m":"AddItemAsync called with userId=5bdcdd66-f0fd-4608-839e-0cd7841a3bbc, productId=L2ECAV7KIM, quantity=5","@i":"04fe325f"} | 5bdcdd66-f0fd-4608-839e-0cd7841a3bbc | L2ECAV7KIM | 5 |
| 2022-08-05 11:55:32 | {"@t":"2022-08-05T08:55:32.5027148Z","@m":"AddItemAsync called with userId=66734557-683c-4864-c3c7-8f08b52f0b17, productId=LS3PSXUNUM, quantity=5","@i":"987426bd"} | 66734557-683c-4864-c3c7-8f08b52f0b17 | LS3PSXUNUM | 5 |
| 2022-08-05 11:30:01 | {"@t":"2022-08-05T08:55:58.6888309Z","@m":"AddItemAsync called with userId=d673ca76-3966-4174-b950-4c3f3aa22dfe, productId=4SIQT8TOJO, quantity=2","@i":"99a07cd5"} | d673ca76-3966-4174-b950-4c3f3aa22dfe | 4SIQT8TOJO | 2 |
Очистка данных
Поскольку ID пользователя и исходная запись лога больше не relevant, давайте очистим таблицу результатов с помощью команды fields.
fetch logs, from:now()-3h | filter dt.process.name=="cartservice cartservice-*" | filter contains(content, "AddItemAsync") | fields timestamp, content | parse content, "LD 'userId=' LD:userId ', productId=' LD:productId ', quantity=' INT:productQuantity" | fields productId, productQuantity
Таблица результатов
| productId | productQuantity |
|---|---|
| 1ZYFJ3GM2N | 1 |
| L2ECAV7KIM | 5 |
| LS3PSXUNUM | 5 |
| 4SIQT8TOJO | 2 |
Сводка событий по товарам
Чтобы увидеть общее количество каждого товара, добавленного в корзину, используйте функцию sum().
fetch logs, from:now()-3h
| filter dt.process.name=="cartservice cartservice-*"
| filter contains(content, "AddItemAsync")
| fields timestamp, content
| parse content, "LD 'userId=' LD:userId ', productId=' LD:productId ', quantity=' INT:productQuantity"
| fields productId, productQuantity
| summarize sum(productQuantity), by:{productId}Таблица результатов
| productId | sum(productQuantity) |
|---|---|
| APUK6V6EV0 | 61 |
| B9ECA1YMWWN1N4OV7KIM | 47 |
| 66CDHSJNUP | 38 |
| 9DIQT8TOJO | 32 |
Поиск самых популярных товаров
Чтобы понять поведение среднего пользователя, мы хотим определить средний размер корзины для каждого товара. Для этого мы используем функцию avg() и называем новое поле averageProductQuantity. Затем мы сортируем средние значения от наибольшего к наименьшему и ограничиваем результаты, чтобы увидеть пять самых популярных товаров.
fetch logs, from:now()-3h
| filter dt.process.name=="cartservice cartservice-*"
| filter contains(content, "AddItemAsync")
| fields timestamp, content
| parse content, "LD 'userId=' LD:userId ', productId=' LD:productId ', quantity=' INT:productQuantity"
| fields productId, productQuantity
| summarize averageProductQuantity = avg(productQuantity), by:{productId}
| sort averageProductQuantity desc
| limit 5Таблица результатов
| averageProductQuantity | productId |
|---|---|
| 4.746268656716418 | 1ZYFJ3GM2N |
| 4.4375 | 26VCHSJNUP |
| 4.415584415584416 | LS3PSXUNUM |
| 4.3604651162790695 | L4ECAV7KIM |
| 4.2682926829268295 | 1YMWWN1N4O |
Пример 3: Отслеживание изменений пользователей
В этом примере вы отслеживаете изменения пользователей с помощью логов аудита. Вы хотите отслеживать тип и количество действий, выполняемых пользователями.
Проверка доступности последних логов аудита
- Узнайте, были ли доступны какие-либо логи аудита за последние пять минут.
- Установите временной диапазон и отфильтруйте только логи, исходный путь которых заканчивается на ваш designated path.
fetch logs, from:now()-5m | filter endsWith(log.source,"change.log")
Таблица результатов
| content | timestamp | dt.entity.host | dt.entity.process_group |
|---|---|---|---|
| {"eventType":"UPDATE","tenantId":"abc","use… | 2022-07-15 09:08:00 UTC 15.7.2022 12:08 | HOST-1 | PROCESS_GROUP-12ED48520DB559D1 |
| {"eventType":"CREATE","tenantId":"efg","use… | 2022-07-15 09:08:07 UTC 15.7.2022 12:08:07 | HOST-2 | PROCESS_GROUP-34ED48520DB559D2 |
| {"eventType":"UPDATE","tenantId":"hij","use… | 2022-07-15 09:11:19 UTC 15.7.2022 12:11:19 | HOST-3 | PROCESS_GROUP-56ED48520DB559D3 |
| {"eventType":"DELETE","tenantId":"klm","use… | 2022-07-15 09:11:19 UTC 15.7.2022 12:11:19 | HOST-4 | PROCESS_GROUP-78ED48520DB559D4 |
Извлечение relevant полей для одного пользователя
- Полученная таблица включает обновления, удаления и создания записей.
- Если вы ограничите запрос последним результатом, вы сможете понять действия, выполненные одним пользователем. Затем мы делаем следующее:
- Используйте
parse, чтобы превратить полеcontentв объект JSON. - Используйте
fieldsAdd, чтобы извлечь relevant поля из этого объекта. - Используйте
fields, чтобы добавить relevant поле. - Используйте
fieldsRemove, чтобы получить только нужные столбцы.
- Используйте
fetch logs, from:now()-5m
| filter endsWith(log.source,"change.log")
| limit 1
| parse content, "TIMESTAMP('yyyy-MM-dd HH:mm:ss'):ts LD JSON:settings"
| fields ts, settings
| fieldsAdd type = settings[eventType], tenant = settings[tenantId], user = settings[userId]
| fieldsRemove settingsТаблица результатов
| ts | type | tenant | user |
|---|---|---|---|
| 2022-07-14 09:19:34 | UPDATE | abc | 1aae042c-ab34-4f01-8d46-128971703d5a |
Получение пользователей, выполнивших обновления и удаления
Чтобы получить пользователей, которые выполнили только обновления или удаления:
- Удалите команду
limit. - Добавьте фильтр для двух типов действий: update и delete.
fetch logs, from:now()-5m
| filter endsWith(log.source,"change.log")
| parse content, "TIMESTAMP('yyyy-MM-dd HH:mm:ss'):ts LD JSON:settings"
| fields ts, settings
| fieldsAdd type = settings[eventType], tenant = settings[tenantId], user = settings[userId]
| fieldsRemove settings
| filter in(type,array("UPDATE","DELETE"))Таблица результатов
| ts | type | tenant | user |
|---|---|---|---|
| 2022-07-14 09:19:34 | UPDATE | abc | 2aae042c-ab34-4f01-8d46-128971703d5b |
| 2022-07-14 05:11:04 | UPDATE | abc | 386b63fc-1516-4b46-9714-ee53dd76c99c |
| 2022-07-14 05:00:49 | DELETE | abc | 486b63fc-1516-4b46-9714-ee53dd76c99d |
| 2022-07-14 04:21:43 | DELETE | abc | 586b63fc-1516-4b46-9714-ee53dd76c99e |
Определение типов изменений и количества изменений, выполненных каждым пользователем
Вы можете подсчитать записи с помощью команды summarize.
fetch logs, from:now()-5m
| filter endsWith(log.source,"change.log")
| parse content, "TIMESTAMP('yyyy-MM-dd HH:mm:ss'):ts LD JSON:settings"
| fields ts, settings
| fieldsAdd type = settings[eventType], tenant = settings[tenantId], user = settings[userId]
| fieldsRemove settings
| filter in(type,array("UPDATE","DELETE"))
| summarize count(), by:{user,type}Таблица результатов
| user | type | count() |
|---|---|---|
| 686b63fc-1516-4b46-9714-ee53dd76c99f | DELETE | 78 |
| 786b63fc-1516-4b46-9714-ee53dd76c99g | UPDATE | 34 |
| 8aae042c-ab34-4f01-8d46-128971703d5h | UPDATE | 20 |
| 9d4a7ac8-e451-6469-cced-6f4358ef343i | UPDATE | 17 |
Подсчёт событий по пользователю с разбивкой по типу действия
Вы можете выполнить расчёт, объединив команду summarize с функцией countIf.
fetch logs, from:now()-5m
| filter endsWith(log.source,"change.log")
| parse content, "TIMESTAMP('yyyy-MM-dd HH:mm:ss'):ts LD JSON:settings"
| fields ts, settings
| fieldsAdd type = settings[eventType], tenant = settings[tenantId], user = settings[userId]
| fieldsRemove settings
| filter in(type,array("UPDATE","DELETE"))
| summarize {countIf(type=="CREATE"), countIf(type=="UPDATE"), countIf(type=="DELETE")}, by:{tenant, user}Таблица результатов
| tenant | user | countIf(type=="CREATE") | countIf(type=="UPDATE") | countIf(type=="DELETE") |
|---|---|---|---|---|
| def | 186b63fc-1516-4b46-9714-ee53dd76c99a | 0 | 34 | 78 |
| ghi | 2aae042c-ab34-4f01-8d46-128971703d5b | 19 | 20 | 8 |
| jkl | 3d4a7ac8-e451-6469-cced-6f4358ef343c | 2 | 17 | 11 |
Пример 4: Создание метрики лога
В этом примере вам нужно подсчитать, сколько отклонённых соединений зафиксировано в ваших данных логов. Для этого отфильтруйте нужные логи и превратите количество вхождений в метрику лога. В этом примере вам нужно отслеживать атрибут ваших логов и следить за уровнями ошибок, сообщаемыми в логах из вашего кластера K8s.
Пример 5: Создание оповещения по логам
В этом примере вам нужно настроить оповещение на основе появления событий логов. Посмотрите, как можно извлечь данные из логов, создать правило обработки, построить оповещение путём формирования события лога и проверить, захватывает ли ваше оповещение логи, соответствующие предопределённым критериям.
Создание метрики обнаружения аномалий
В этом варианте использования вам нужно автоматизировать обнаружение аномалий. Посмотрите, как можно извлечь данные из логов, создать правило обработки, создать метрику и создать оповещение, которое генерирует уведомление при возникновении аномалии.