I wanted to display XML data using logstash and Kibana in grid format. using below conf file I am able to display data into grid but not able to split row data. Example:
Output
logstash.conf file :
input {
file {
path => "C:/ELK Stack/logstash-8.2.0-windows-x86_64/logstash-8.2.0/Test.xml"
start_position => "beginning"
sincedb_path => "NUL"
codec => multiline {
pattern => "^<?stations.*>"
negate => "true"
what => "previous"
auto_flush_interval => 1
max_lines => 3000
}}}
filter
{
xml
{
source => "message"
target => "parsed"
store_xml => "false"
xpath => [
"/stations/station/id/text()", "station_id",
"/stations/station/name/text()", "station_name"
]
}
mutate {
remove_field => [ "message"]
}
}
output {
elasticsearch {
action => "index"
hosts => "localhost:9200"
index => "logstash_index123xml"
workers => 1
}
stdout {
codec => rubydebug
}
}
CodePudding user response:
xpath will always return arrays, to associate the members of the two arrays you are going to need to use a ruby filter. To get multiple events you can use a split filter to split an array which you build in the ruby filter. If you start with
<stations>
<station>
<id>1</id>
<name>a</name>
<id>2</id>
<name>b</name>
</station>
</stations>
then if you use
xml {
source => "message"
store_xml => "false"
xpath => {
"/stations/station/id/text()" => "[@metadata][station_id]"
"/stations/station/name/text()" => "[@metadata][station_name]"
}
remove_field => [ "message" ]
}
ruby {
code => '
ids = event.get("[@metadata][station_id]")
names = event.get("[@metadata][station_name]")
if ids.is_a? Array and names.is_a? Array
a = []
ids.each_index { |x|
a << { "station_name" => names[x], "station_id" => ids[x] }
}
event.set("[@metadata][theData]", a)
end
'
}
split {
field => "[@metadata][theData]"
add_field => {
"station_name" => "%{[@metadata][theData][station_name]}"
"station_id" => "%{[@metadata][theData][station_id]}"
}
}
You will get two events
{
"station_name" => "a",
"station_id" => "1",
...
}
{
"station_name" => "b",
"station_id" => "2",
...
}