Logstash - список синтаксического анализа JSON

Мне очень нравится ELK для разбора логов. Однако я застрял в точке, где нужно проанализировать список словарей. Ниже приведены мои журналы: -

IP - - 0.000 0.000 [24/May/2015:06:51:13 +0000] *"POST /c.gif HTTP/1.1"* 200 4 * user_id=UserID&package_name=SomePackageName&model=Titanium+S202&country_code=in&android_id=AndroidID&eT=1432450271859&eTz=GMT%2B05%3A30&events=%5B%7B%22eV%22%3A%22com.olx.southasia%22%2C%22eC%22%3A%22appUpdate%22%2C%22eA%22%3A%22app_activated%22%2C%22eTz%22%3A%22GMT%2B05%3A30%22%2C%22eT%22%3A%221432386324909%22%2C%22eL%22%3A%22packageName%22%7D%5D * "-" "-" "-"

Версия указанного выше журнала с декодированием URL-адреса:

IP - - 0.000 0.000 [24/May/2015:06:51:13  0000] *"POST /c.gif HTTP/1.1"* 200 4 * user_id=UserID&package_name=SomePackageName&model=Titanium S202&country_code=in&android_id=AndroidID&eT=1432450271859&eTz=GMT+05:30&events=[{"eV":"com.olx.southasia","eC":"appUpdate","eA":"app_activated","eTz":"GMT+05:30","eT":"1432386324909","eL":"packageName"}] * "-" "-" "-"

Где бы я ни пытался его разобрать, он показывает мне _jsonparsefailure. Я прошел через этот вопрос, а также прошел через различные форумы , но не нашел для этого идеального решения. Как я могу разобрать список json в logstash? Если до сих пор не существует, как можно обойтись с тем же?

Ниже приведен мой файл конфигурации.

filter {
    mutate {
        gsub => [
            "message", "\+", "%20"
        ]
    }

    urldecode{
        field => "message"
    }
    grok {
        match => [
            'message', '%{IP:clientip}%{GREEDYDATA} \[%{GREEDYDATA:timestamp}\] \*"%{WORD:method}%{GREEDYDATA}'
        ]
    }

    kv {
        field_split => "&?"
    }

    json{
        source => "events"
    }

    geoip {
        source => "clientip"
    }
}

person PythonEnthusiast    schedule 04.08.2015    source источник
comment
Фильтр kv {} должен сделать вас полем с именем events, которое содержит ваш json. Является ли?   -  person Alain Collins    schedule 04.08.2015
comment
Да. Но это не анализирует значения списка events   -  person PythonEnthusiast    schedule 04.08.2015
comment
Я понимаю это, но если kv {} не работает, json {} не будет вводить какие-либо данные для обработки. Если вы возьмете значение события после фильтра kv {} на валидатор json, это нормально?   -  person Alain Collins    schedule 04.08.2015
comment
Да, это нормально. Фильтр json успешно анализирует json в форме { "foo":"bar" }. Json, который он не может проанализировать, равен [ { "foo":"bar" } ]   -  person PythonEnthusiast    schedule 04.08.2015


Ответы (1)


Этот вопрос является точной копией Разобрать json в списке в logstash . Даже с такими же записями в журнале ?! Может ли кто-нибудь понять это?

Вы можете увидеть мой ответ там, но я подведу итог ... вариант д), вероятно, лучший подход


По-видимому, вы получаете jsonparsefailure из-за квадратных скобок. В качестве обходного пути вы можете удалить их вручную. Добавьте следующий фильтр mutate после вашего kv и перед вашим фильтром json:

mutate  {
    gsub => [ "events","\]",""]
    gsub => [ "events","\[",""]
}

Однако это не работает для ввода типа [{"foo":"bar"},{"foo":"bar1"}]. Итак, вот 4 варианта:

Вариант а) уродливый gsub

Уродливым решением будет другой gsub:

gsub => [ "event","\},\{",","]

Но это уберет внутренние отношения, так что я думаю, вы не хотите этого делать.

Вариант б) разделить

Лучшим подходом может быть использование разделенного фильтра:

split {
    field => "event"
    terminator => ","
}
mutate  {
    gsub => [ "event","\]",""]
    gsub => [ "event","\[",""]
   }
json{
    source=> "event"
}

Это приведет к возникновению нескольких событий. (Первый с foo = bar, второй с foo1 = bar1.)

Вариант c) изменение разделения

Возможно, вы захотите иметь все значения в одном событии logstash. Вы можете использовать фильтр mutate => split для создания массива и анализа json, если запись существует. К сожалению, вам придется установить условие для каждой записи, потому что logstash не поддерживает циклы в своей конфигурации.

mutate  {
    gsub => [ "event","\]",""]
    gsub => [ "event","\[",""]
    split => [ "event", "," ]
   }

json{
    source=> "event[0]"
    target => "result[0]"
}

if 'event[1]' {
    json{
        source=> "event[1]"
        target => "result[1]"
    }
    if 'event[2]' {
        json{
            source=> "event[2]"
            target => "result[2]"
        }
    }
    # You would have to specify more conditionals if you expect even more dictionaries
}

Вариант г) Ruby1

Следующие работы (после вашего фильтра kv): Скорее используйте вариант e)

mutate  {
    gsub => [ "event","\]",""]
    gsub => [ "event","\[",""]
}

ruby  {
    init => "require 'json'"
    code => "
        e = event['event'].split(',')
        ary = Array.new
        e.each do |x|
            hash = JSON.parse(x)
            hash.each do |key, value|
                ary.push( { key =>  value } )
            end
        end
        event['result'] = ary
    "
}

ОБНОВИТЬ

Вариант д) Ruby2

После некоторого тестирования это может быть лучшим подходом. Используйте это после вашего фильтра kv:

ruby  {
    init => "require 'json'"
    code => "event['result'] = JSON.parse(event['event'])"
}
person hurb    schedule 04.08.2015