Dynamic field names in logstash

I have a string which is dynamic .It represents resp time and ip address

60.006,0.001#10.10.24.14:8082,10.10.22.11:8082

The no of machine can grow and so will the subsequent resp time and ip address.

What I am trying is to split the string first on the basis of '#' and then on the basis of ',' and store the values. The code I have written in ruby is

ruby {

code => "
fields = event['data'].split('#')
for field in fields
field = field.split(',')
event['respTime1'] = field[0]
event['respTime2'] = field[1]
end
"
}

Can someone explain or tell how to make the fields dynamic so that if I have 100 different servers resp time & IP address, I can use dynamic names for it

I've probably mis-interpreted your expected outcome, but the code below

ruby { code => " times, hosts = event['data'].split('#') hosts.split(',').each_with_index { |val,index| event['respTime' + (index+1).to_s] = times.split(',')[index] } " }

would yield

event["respTime1"]=>"60.006"
event["respTime2"]=>"0.001"

Is that what you're after? If not, could you please post an expected output with actual values?

Edit: If you're after Host:Time pairs, which seems more logical, the snippet below

ruby {
code => "
   times, hosts = event['data'].split('#')
   hosts.split(',').each_with_index { 
     |val,index| 
     event[val.to_s] = times.split(',')[index]
   }
   "
}

will return

"10.10.24.14:8082"=>"60.006"
"10.10.22.11:8082"=>"0.001"
1 Like

Thank you so much for your reply.
The output I am expecting is

"respTime_1" => "60.006"
"respTime_2" => "0.001"
"IP_1" => "10.10.24.14:8082"
"IP_2" => "10.10.22.11:8082"

And _1 and _2 in the field have to be dynamic like if I have 5 inputs so o/p should be like
"respTime_1" => "60.006"
"respTime_2" => "64"
"respTime_3" => "63"
"respTime_4" => "62"
"respTime_5" => "61"

Ah, alright. You can try this then

ruby {
    code => "
        # splits the data field into 2 arrays, times and hosts
        times, hosts = event['data'].split('#')
        # split times on each , character and for every value create a field named with a respTime_ prefix and incremental values based on array index (plus 1, since index starts at 0).
        times.split(',').each_with_index { |val,index| event['respTime_' + (index+1).to_s] = val}
        # same process for hosts array, creating the IP_ fields.
        hosts.split(',').each_with_index { |val,index| event['IP_' + (index+1).to_s] = val}
    "
}

It will create the appropriate fields for any amount of included entries.

1 Like

Thank you so much....Exactly the same code I was looking for..
Can you please explain below line of the code.

each_with_index { |val,index| event['respTime_' + (index+1).to_s] = val

Sure thing,

each_with_index : is an iterator (basically a loop) where for each array object, it returns it's value and it's position (index). More info : https://apidock.com/ruby/Enumerator/each_with_index

|val,index| : defines the names of the returned variables.

event['respTime_' + (index+1).to_s : this takes the index number, increments it by 1 (because index starts at 0 and we want the first field to be respTime_1 instead of respTime_0), converts it to string with .to_s and joins it with the respTime_ prefix, creating the field name.

= val just puts the value we got from the iterator as the field value.

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.