Datadog Grok Parsing - извлечение полей из вложенных JSON - PullRequest
2 голосов
/ 29 мая 2020

Можно ли извлечь json полей, вложенных в журнал?

Пример, над которым я работал:

thread-191555 app.main - [cid: 2cacd6f9-546d-41ew-a7ce-d5d41b39eb8f, uid: e6ffc3b0-2f39-44f7-85b6-1abf5f9ad970] Request: protocol=[HTTP/1.0] method=[POST] path=[/metrics] headers=[Timeout-Access: <function1>, Remote-Address: 192.168.0.1:37936, Host: app:5000, Connection: close, X-Real-Ip: 192.168.1.1, X-Forwarded-For: 192.168.1.1, Authorization: ***, Accept: application/json, text/plain, */*, Referer: https://google.com, Accept-Language: cs-CZ, Accept-Encoding: gzip, deflate, User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko, Cache-Control: no-cache] entity=[HttpEntity.Strict application/json {"type":"text","extract": "text", "field2":"text2","duration": 451 }

я хотел достичь:

{
"extract": "text",
"duration": "451"
}

Я попытался объединить образец регулярного выражения ("(extract)"\s*:\s*"([^"]+)",?) с example_parser %{data::json} (для начала, используя JSON в качестве данных образца журнала), но мне не удалось заставить ничего работать.

Заранее спасибо!

1 Ответ

2 голосов
/ 30 мая 2020

Правильно ли отформатирован этот образец текста? В конечном объекте сущности отсутствует ] с конца.

entity=[HttpEntity.Strict application/json {"type":"text","extract": "text", "field2":"text2","duration": 451 }

должно быть

entity=[HttpEntity.Strict application/json {"type":"text","extract": "text", "field2":"text2","duration": 451 }]

Я иду чтобы продолжить эти инструкции, предполагая, что это была опечатка, и поле объекта фактически заканчивается на ]. Если это не так, я думаю, вам нужно исправить базовый журнал, чтобы он был правильно отформатирован, и закрыть скобку.


Вместо того, чтобы просто пропускать весь журнал и анализировать только этот json бит , Я решил разобрать все и показать, что будет хорошо выглядеть в конечном итоге. Итак, первое, что нам нужно сделать, это вытащить этот набор пар ключ / значение после объекта запроса:

Пример ввода: thread-191555 app.main - [cid: 2cacd6f9-546d-41ew-a7ce-d5d41b39eb8f, uid: e6ffc3b0-2f39-44f7-85b6-1abf5f9ad970] Request: protocol=[HTTP/1.0] method=[POST] path=[/metrics] headers=[Timeout-Access: <function1>, Remote-Address: 192.168.0.1:37936, Host: app:5000, Connection: close, X-Real-Ip: 192.168.1.1, X-Forwarded-For: 192.168.1.1, Authorization: ***, Accept: application/json, text/plain, */*, Referer: https://google.com, Accept-Language: cs-CZ, Accept-Encoding: gzip, deflate, User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko, Cache-Control: no-cache] entity=[HttpEntity.Strict application/json {"type":"text","extract": "text", "field2":"text2","duration": 451 }]

Правило парсера Grok: app_log thread-%{integer:thread} %{notSpace:file} - \[%{data::keyvalue(": ")}\] Request: %{data:request:keyvalue("=","","[]")}

Результат:

{
  "thread": 191555,
  "file": "app.main",
  "cid": "2cacd6f9-546d-41ew-a7ce-d5d41b39eb8f",
  "uid": "e6ffc3b0-2f39-44f7-85b6-1abf5f9ad970",
  "request": {
    "protocol": "HTTP/1.0",
    "method": "POST",
    "path": "/metrics",
    "headers": "Timeout-Access: <function1>, Remote-Address: 192.168.0.1:37936, Host: app:5000, Connection: close, X-Real-Ip: 192.168.1.1, X-Forwarded-For: 192.168.1.1, Authorization: ***, Accept: application/json, text/plain, */*, Referer: https://google.com, Accept-Language: cs-CZ, Accept-Encoding: gzip, deflate, User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko, Cache-Control: no-cache",
    "entity": "HttpEntity.Strict application/json {\"type\":\"text\",\"extract\": \"text\", \"field2\":\"text2\",\"duration\": 451 }"
  }
}

app log parser

Обратите внимание, как мы используем синтаксический анализатор значения ключа с цитируемой строкой [], что позволяет нам легко извлечь все из объекта запроса.


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

Итак, в этом же конвейере мы добавим еще один процессор синтаксического анализа Grok сразу после нашего первого

enter image description here

А затем настройте раздел дополнительных параметров для работы на request.entity, поскольку это то, что мы назвали атрибутом

enter image description here

Пример ввода: HttpEntity.Strict application/json {"type":"text","extract": "text", "field2":"text2","duration": 451 }

Правило парсера Grok: entity_rule %{notSpace:request.entity.class} %{notSpace:request.entity.media_type} %{data:request.entity.json:json}

Результат:

{
  "request": {
    "entity": {
      "class": "HttpEntity.Strict",
      "media_type": "application/json",
      "json": {
        "duration": 451,
        "extract": "text",
        "type": "text",
        "field2": "text2"
      }
    }
  }
}

Теперь, когда мы смотрим на последний проанализированный журнал, он есть все, что нам нужно:

enter image description here


Также просто потому, что это было действительно просто, я добавил третий процессор Grok для фрагмента заголовков также (расширенные настройки настроены на синтаксический анализ из request.headers):

Пример ввода: Timeout-Access: <function1>, Remote-Address: 192.168.0.1:37936, Host: app:5000, Connection: close, X-Real-Ip: 192.168.1.1, X-Forwarded-For: 192.168.1.1, Authorization: ***, Accept: application/json, text/plain, */*, Referer: https://google.com, Accept-Language: cs-CZ, Accept-Encoding: gzip, deflate, User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko, Cache-Control: no-cache

Правило парсера Grok: headers_rule %{data:request.headers:keyvalue(": ", "/)(; :")}

Результат:

{
  "request": {
    "headers": {
      "Timeout-Access": "function1",
      "Remote-Address": "192.168.0.1:37936",
      "Host": "app:5000",
      "Connection": "close",
      "X-Real-Ip": "192.168.1.1",
      "X-Forwarded-For": "192.168.1.1",
      "Accept": "application/json",
      "Referer": "https://google.com",
      "Accept-Language": "cs-CZ",
      "Accept-Encoding": "gzip",
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko",
      "Cache-Control": "no-cache"
    }
  }
}

Единственная хитрость здесь в том, что мне пришлось определить characterWhiteList из /)(; :. В основном для обработки всех этих специальных символов в поле User-Agent.


Ссылки :

Просто документация, некоторые предположения и проверки в моей личной учетной записи Datadog.

https://docs.datadoghq.com/logs/processing/parsing/?tab=matcher#key - значение-или-logfmt

...