Фильтр геостатистики Logstash - имена полей динамически

У меня есть строки журнала в следующем формате и вы хотите извлечь поля:

[field1: content1] [field2: content2] [field3: content3] ...

Мне не известны имена полей или количество полей.

Я попробовал его с обратными ссылками и в формате sprintf, но не получил никаких результатов:

match => [ "message", "(?:\[(\w+): %{DATA:\k<-1>}\])+" ] # not working
match => [ "message", "(?:\[%{WORD:fieldname}: %{DATA:%{fieldname}}\])+" ] # not working

Кажется, что это работает только для одного поля, но не более:

match => [ "message", "(?:\[%{WORD:field}: %{DATA:content}\] ?)+" ]
add_field => { "%{field}" => "%{content}" }

Фильтр kv также не подходит, поскольку содержимое полей может содержать пробелы.

Есть ли какой-либо плагин/стратегия для решения этой проблемы?

Ответ 1

Плагин Logstash Ruby может помочь вам.:)

Вот конфигурация:

input {
    stdin {}
}

filter {
    ruby {
        code => "
            fieldArray = event['message'].split('] [')
            for field in fieldArray
                field = field.delete '['
                field = field.delete ']'
                result = field.split(': ')
                event[result[0]] = result[1]
            end
        "
    }
}

output {
    stdout {
        codec => rubydebug
    }
}

С вашими журналами:

[field1: content1] [field2: content2] [field3: content3]

Это вывод:

{
   "message" => "[field1: content1] [field2: content2] [field3: content3]",
  "@version" => "1",
"@timestamp" => "2014-07-07T08:49:28.543Z",
      "host" => "abc",
    "field1" => "content1",
    "field2" => "content2",
    "field3" => "content3"
}

Я попробовал с 4 полями, он также работает.

Обратите внимание, что event в ruby-коде - это событие logstash. Вы можете использовать его для получения всего поля событий, например message, @timestamp и т.д.

Наслаждайтесь!!!

Ответ 2

Я нашел другой способ с помощью regex:

ruby {
    code => "
        fields = event['message'].scan(/(?<=\[)\w+: .*?(?=\](?: |$))/)
        for field in fields
            field = field.split(': ')
            event[field[0]] = field[1]
        end
    "
}