Aggregate filter plugin throwing undefined method error

Hi,

I am trying to get the difference between startDt and endDt but I am getting the below error -

Aggregate exception occurred {:error=>#<NoMethodError: undefined method `-' for "2018-06-15T03:50:26.109":String

Both startDt and endDt are date types. Here is my logstash code:

 if [ivrCall][startDt] {
      aggregate {
       task_id => "%{[ivrCall][callId]}"
       code => "map['call_duration'] = event.get('[ivrCall][startDt]')"
       map_action => "create"
     }
     }
     if [ivrCall][endDt] {
      aggregate {
       task_id => "%{[ivrCall][callId]}"
       code => "map['call_duration'] = event.get('[ivrCall][endDt]') - map['call_duration']; event.set('call_duration', map['call_duration'])"
       map_action => "update"
       end_of_task => true
       timeout => 120
     }
     }

I have no idea what is wrong. I tried multiple times by changing the code. Why it's not recognizing - ? Please suggest. Thanks.

I think it is telling you right there in the error message that at least one of them is a "String". You may have to convert them using DateTime.strptime.

Thanks @Badger. If I do like this, below error I am getting -

[2018-06-15T17:11:38,753][ERROR][logstash.filters.aggregate] Aggregate exception occurred {:error=>#<TypeError: no implicit conversion to rational from string>, :code=>"map['duration'] = event.get('endt') - map['stdt']; event.set('call_duration', map['duration'])", :map=>{"stdt"=>"2018-06-15T17:11:30.508"},

if [ivrCall][startDt] {
      aggregate {
       task_id => "%{[ivrCall][callId]}"
       code => "map['stdt'] = event.get('[ivrCall][startDt]')"
       map_action => "create"
     }
     }
      date {
        match => [ "stdt", "yyyy-MM-dd'T'HH:mm:ss.SSS" ]
        target => "stdt"
      }
     if [ivrCall][endDt] {
      date {
        match => [ "[ivrCall][endDt]", "yyyy-MM-dd'T'HH:mm:ss.SSS" ]
        target => "endt"
      }
      aggregate {
       task_id => "%{[ivrCall][callId]}"
       code => "map['duration'] = event.get('endt') - map['stdt']; event.set('call_duration', map['duration'])"
       map_action => "update"
       end_of_task => true
       timeout => 120
     }
     }

The delta between two DateTime objects is a Rational (a fraction of a day such as 380287/43200000) and you cannot do an implicit to_s on it.

What I was thinking was some ruby more like this. I will let you fit it into the aggregate filter.

output { stdout { codec => rubydebug } }
input { generator { count => 1 message => '' } }
filter {
    mutate { add_field => { "[ivrCall][startDt]" => "2018-06-15T17:11:30.508" "[ivrCall][endDt]" => "2018-06-15T17:24:11.082" } }
    ruby {
        code => "
            event.set('duration', 86400 * (DateTime.strptime(event.get('[ivrCall][endDt]'), '%Y-%m-%dT%H:%M:%S.%L') -
                                  DateTime.strptime(event.get('[ivrCall][startDt]'), '%Y-%m-%dT%H:%M:%S.%L')).to_f)
        "
    }
}

Running that I get

      "duration" => 760.5740000000001

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