Creating watcher script if particular value ina field occurs more than five times in five minutes interval of time

Hi can anyone help how can we create a watcher script for the below requirement

I having a field called "log_message" contaning the below message

Failed to load TermRecord for TermID=

here the terminal id can be any characters , it may be number , alphabets or special characters

i want to get an alert in kibana, if the same log message containing the same terminal id occurs more than 5 times in a 5 minute interval of time. i dont know how to aggregate these in the watcher script. below is my watcher script.i used the regex pattern in the "query string" as the terminal id can be anything. but i am getting an error. is there any other way? Thanks.

            {
             "trigger": {
             "schedule": {
                  "interval": "5m"
                                     }
                                   },
                     "input": {
                               "search": {
                                      "request": {
                                  "search_type": "query_then_fetch",
                                  "indices": [
                 "testingalert*"
                                        ],
                                  "rest_total_hits_as_int": true,
                        "body": {
                                         "size": 0,
                                       "query": {
                                    "bool": {
                                                 "must": {
                       "query_string": {
                                 "query": "Failed to load TermRecord for TermID=^[a-zA-Z0-9_.-]*$"
                                }
                                    },
                                  "filter": {
                     "range": {
                       "@timestamp": {
                         "gte": "{{ctx.trigger.scheduled_time}}||-5m",
                           "lte": "{{ctx.trigger.scheduled_time}}",
                          "format": "strict_date_optional_time||epoch_millis"
                                }
                             }
                             }
                             }
                                },
                                  "aggs": {
                               "bucketAgg": {
                             "terms": {
                                    "field": "log_message.keyword",
                               "size": "5",
                                   "order": {
                              "_count": "desc"
                                      }
                                           }
                                    }
                                  }
                                            }
                                   }
                                            }
                          },

"condition": {
"script": {
"source": "ArrayList arr = ctx.payload.aggregations.bucketAgg.buckets; for (int i = 0; i < arr.length; i++) { if (arr[i].doc_count > params.threshold) { return true; } } return false;",
"lang": "painless",
"params": {
"threshold": 5
}
}
},
"actions": {
"send_email": {
"email": {
"profile": "standard",
"to": [
"anonymousbeendetected@gmail.com"
],
"subject": "Watcher Notification",
"body": {
"text": "Watch [{{ctx.metadata.name}}] The 'Warning' alert has occured more than 5 times in 5 minutes interval of time"
}
}
}
},
"transform": {
"script": {
"source": "HashMap result = new HashMap(); ArrayList arr = ctx.payload.aggregations.bucketAgg.buckets; ArrayList filteredHits = new ArrayList(); for (int i = 0; i < arr.length; i++) { HashMap filteredHit = new HashMap(); filteredHit.key = arr[i].key; filteredHit.value = arr[i].doc_count; if (filteredHit.value > params.threshold) { filteredHits.add(filteredHit); } } result.results = filteredHits; return result;",
"lang": "painless",
"params": {
"threshold": 5
}
}
}
}

Hi,

for this use case an aggregation would be as below, which checks last 5 mins data and aggregate based on message and term ID

{
"size": 0,
"query": {
"range": {
"Timefield": {
"lte": "now-5m"
}
}
},
"aggs": {
"message": {
"terms": {
"field": "message.keyword",
"size": 10
},
"aggs": {
"id": {
"terms": {
"field": "term_id.keyword",
"size": 10
}
}
}
}
}
}

And the Result looks as follows , wherein you have to loop through the payload and apply condition on the "doc_count", if(doc_count >= 5) trigger an action

From my example for Log message "Time Out" Term ID "1" and "8()(#$%" are appearing more than 5 times .

"aggregations" : {
"message" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Time Out",
"doc_count" : 13,
"id" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "1",
"doc_count" : 6
},
{
"key" : "8()(#$%",
"doc_count" : 6
},
{
"key" : "abc",
"doc_count" : 1
}
]
}
}
]
}
}

Hope my explanation is clear

Thanks,
Ramya

1 Like

Hi Ramya,

Thank you for your reply. By the way how will be my final watcher looks like which i have mentioned in the previous message? when i tested in my dev tools i am getting error like this

{
"error" : {
"root_cause" : [
{
"type" : "parsing_exception",
"reason" : "[range] query does not support [tte]",
"line" : 6,
"col" : 8
}
],
"type" : "parsing_exception",
"reason" : "[range] query does not support [tte]",
"line" : 6,
"col" : 8
},
"status" : 400
}

can you help me on this watcher script?

Thanks
M.Lokesh

There was a typo in the query which i have corrected.
This query & aggregation are input to watcher , you have to work on condition, transform and action.

Thanks,
Ramya

1 Like

Hi Ramya,

Yeah got it. Thank you so much :innocent:

Hi @RamyaGowda i have few doubts caan you clear that?

Failed to load TermRecord for TermID= /a-zA-Z0-9_.-/

is this regex pattern correct? di i need to enable any regex option in the elasticsearch.yml file ? and what is the "size" in aggregation means?

Are you trying to match any character using regex ? I believe no need to do this, term aggregation based the type keyword would solve your purpose.

size is the number of documents you want to aggregate , default is 10 you can change it.

{
"size": 0,
"aggs": {
"message": {
"terms": {
"field": "message.keyword",
"size": 10
},
"aggs": {
"id": {
"terms": {
"field": "term_id.keyword",
"size": 1
}
}
}
}
}
}

"aggregations" : {
"message" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Time Out",
"doc_count" : 17,
"id" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 11,
"buckets" : [
{
"key" : "1",
"doc_count" : 6
}
]
}
}
]
}
}

if suppose i am having a log like this

<#> 20200806 17:04:24.834 282005997 FD.INF [ MVINB-LSL2.T1G1_ATMTH1 main.main DAPoolManager.DAControl ] Failed to load TermRecord for TermID=bafldd3,MerchantID=gcl6upi

So what ever values comes after "Term Record for" whether it may be term id or merchant id, etc . what the query will be like for in this condition?
And thank you so much for the previous script its working perfectly fine and i am able to detect the alert :slightly_smiling_face:

If the condition for the above requirement is achieved, my entire requirement will be resolved. can you help me on this doubt alone please?

@RamyaGowda is there a way for this requirement?

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