Разбор многострочного JSON с grok в logstash


У меня есть JSON формата:

{
    "SOURCE":"Source A",
    "Model":"ModelABC",
    "Qty":"3"
}

Я пытаюсь разобрать этот JSON с помощью logstash. В основном я хочу, чтобы вывод logstash был списком пар ключ: значение, которые я могу анализировать с помощью kibana. Я думал, что это можно сделать из коробки. Из большого количества прочитанного я понимаю, что должен использовать плагин grok (я все еще не уверен, для чего нужен плагин json). Но я не могу получить событие со всеми полями. Я получаю несколько событий (по одному даже для каждого атрибута моего JSON). Нравится Итак:

{
       "message" => "  "SOURCE": "Source A",",
      "@version" => "1",
    "@timestamp" => "2014-08-31T01:26:23.432Z",
          "type" => "my-json",
          "tags" => [
        [0] "tag-json"
    ],
          "host" => "myserver.example.com",
          "path" => "/opt/mount/ELK/json/mytestjson.json"
}
{
       "message" => "  "Model": "ModelABC",",
      "@version" => "1",
    "@timestamp" => "2014-08-31T01:26:23.438Z",
          "type" => "my-json",
          "tags" => [
        [0] "tag-json"
    ],
          "host" => "myserver.example.com",
          "path" => "/opt/mount/ELK/json/mytestjson.json"
}
{
       "message" => "  "Qty": "3",",
      "@version" => "1",
    "@timestamp" => "2014-08-31T01:26:23.438Z",
          "type" => "my-json",
          "tags" => [
        [0] "tag-json"
    ],
          "host" => "myserver.example.com",
          "path" => "/opt/mount/ELK/json/mytestjson.json"
}

Следует ли мне использовать многострочный кодек или кодек json_lines? Если да, то как я могу это сделать? Нужно ли мне написать свой собственный шаблон grok или есть что-то общее для JSONs, что даст мне одно событие с парами key:value, которые я получаю для одного события выше? Я не смог найти никаких документов, которые пролили бы свет на это. Любая помощь будет оценена по достоинству. Мой файл conf показан ниже:

input
{
        file
        {
                type => "my-json"
                path => ["/opt/mount/ELK/json/mytestjson.json"]
                codec => json
                tags => "tag-json"
        }
}

filter
{
   if [type] == "my-json"
   {
        date { locale => "en"  match => [ "RECEIVE-TIMESTAMP", "yyyy-mm-dd HH:mm:ss" ] }
   }
}

output
{
        elasticsearch
        {
                host => localhost
        }
        stdout { codec => rubydebug }
}
2 4

2 ответа:

Я думаю, что нашел рабочий ответ на свою проблему. Я не уверен, что это чистое решение, но оно помогает анализировать многострочные JSONs типа выше.

input 
{   
    file 
    {
        codec => multiline
        {
            pattern => '^\{'
            negate => true
            what => previous                
        }
        path => ["/opt/mount/ELK/json/*.json"]
        start_position => "beginning"
        sincedb_path => "/dev/null"
        exclude => "*.gz"
    }
}

filter 
{
    mutate
    {
        replace => [ "message", "%{message}}" ]
        gsub => [ 'message','\n','']
    }
    if [message] =~ /^{.*}$/ 
    {
        json { source => message }
    }

}

output 
{ 
    stdout { codec => rubydebug }
}

Мой кодек mutliline не обрабатывает последнюю скобку, и поэтому он не выглядит как JSON для json { source => message }. Отсюда и фильтр мутаций:

replace => [ "message", "%{message}}" ]

Это добавляет недостающую скобку. и

gsub => [ 'message','\n','']

Удаляет введенные символы \n. В конце его у меня есть однострочный JSON, который может быть прочитан json { source => message }

Если есть более чистый / простой способ преобразовать оригинальный многострочный JSON в однострочный JSON, пожалуйста, напишите, поскольку я чувствую, что выше не слишком чистый.

Вам потребуется использовать кодек multiline.

input {
  file {
    codec => multiline {
        pattern => '^{'
        negate => true
        what => previous
    }
    path => ['/opt/mount/ELK/json/mytestjson.json']
  }
}
filter {
  json {
    source => message
    remove_field => message
  }
}

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