DSL query in Kibana Rules does not work the same as from Dev Tools

Hello,

I'm using Elastic 7.17.6 and I have an alert rule set up which is using the below DSL query to search for the data:

{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        { "match": { "empty": "true" }},
        { "match": { "type": "LINECARD" }}
      ]
    }
  },
  "aggs": {
    "unique_sources": {
      "filter": {
        "bool": {
          "must": [
            { "match": { "empty": "true" }},
            { "match": { "type": "LINECARD" }}
          ]
        }
      },
      "aggs": {
        "sources": {
          "terms": {
            "field": "source.keyword",
            "size": 10
          },
          "aggs": {
            "top_source": {
              "top_hits": {
                "size": 1
              }
            }
          }
        }
      }
    }
  }
}

I'm trying to only get one unique data set returned based on source.keyword.
When I click on "Test Rule" I get this result Query matched 6 documents in the last 1m.
I'm streaming data in from a network device so I do get duplicate data sets sent within a minute and I would like to receive a unique data set based on source.keyword.

Then in the "Message" section of the rule, I have this handlebar code to print the data from the above search result:

Alert
=
Date: {{context.date}}

Hardware removal was detected from below device:

{{ #context.hits }}
source: {{_source.source}}

slot: {{_source.slot}}

description: {{_source.description}}

type: {{_source.type}}

parent: {{_source.parent}}

slot empty: {{_source.empty}}

power status: {{_source.power_admin_state}}

{{/context.hits}}

I'm getting an email that prints all 6 documents that the DSL query matched. These 6 documents are duplicates. All six documents are from the same source. I would like the email to only return 1 unique data set. I hope that makes sense.

I don't know if there is a way in the handlebar code to parse the #context.hits to only return unique data? Or if the DSL query can be edited to accomplish this?

I think your problem is that Kibana Rules does not yet fully support Elasticsearch aggregations (follow the GitHub issue here: Elasticsearch Query Stack Alert Aggregation Support · Issue #95161 · elastic/kibana · GitHub)

In the meantime, you could accomplish this with Watcher.

Thanks for the info. I'll look into Watcher.

I don't think Watcher works with boolean fields. I'm trying to create a watch and my options are:

  • count()
  • avg()
  • sum()
  • min()
  • max()

watcher allows for any arbitrary elasticsearch query or aggregation. You can then evaluate the result of that query using the script type of the condition to do anything you want.

See example here: Watcher condition context | Painless Scripting Language [8.6] | Elastic

I'm able to get Watcher to fire when I run simulate. How can I iterate the "hits" in my email?

"actions": {
    "email_1": {
      "email": {
        "profile": "standard",
        "to": [
          "myeamil@email.com"
        ],
        "subject": "Watch [{{ctx.metadata.name}}] has exceeded the threshold",
        "body": {
          "text": "{{ #ctx.payload.hits}} ???? {{ /ctx.payload.hits }}"
        }
      }
    }
  }
}

The handlebar code from my Rules is not working here.

If I print just {{ ctx }} in the email body I get the following response:

Click Me
{
    metadata = {
        name = Test Lab Watch,
        xpack = {
            type = json
        }
    }, watch_id = _inlined_, payload = {
        _shards = {
            total = 1,
            failed = 0,
            successful = 1,
            skipped = 0
        },
        hits = {
            hits = [],
            total = 6,
            max_score = null
        },
        took = 1,
        timed_out = false,
        aggregations = {
            unique_sources = {
                doc_count = 6,
                sources = {
                    doc_count_error_upper_bound = 0,
                    sum_other_doc_count = 0,
                    buckets = [{
                        doc_count = 6,
                        top_source = {
                            hits = {
                                hits = [{
                                    _index = Test - components - 2023.03 .17,
                                    _type = _doc,
                                    _source = {
                                        part - no = ,
                                        parent = SLOT - 1,
                                        hardware - version = ,
                                        oper - status = INACTIVE,
                                        mfg - name = Test,
                                        description = ,
                                        serial - no = ,
                                        slot = LM - 1,
                                        source = 10.10 .10 .1,
                                        type = LINECARD,
                                        tid = site1,
                                        empty = true,
                                        power - admin - state = POWER_DISABLED,
                                        @timestamp = 2023 - 03 - 17 T22: 55: 34.618 Z,
                                        host = lab - agent,
                                        @version = 1,
                                        name = components
                                    },
                                    _id = Qe7J8YYB6ZJARmddHeVJ,
                                    _score = 6.320991
                                }],
                                total = 6,
                                max_score = 6.320991
                            }
                        },
                        key = 10.10 .10 .1
                    }]
                },
                meta = {}
            }
        }
    }, id = _inlined__6d3b8a0f - c477 - 4259 - 811 d - 4e086350 f191 - 2023 - 03 - 17 T22: 55: 40.412949059 Z, trigger = {
        triggered_time = 2023 - 03 - 17 T22: 55: 40.412937978 Z,
        scheduled_time = 2023 - 03 - 17 T22: 55: 40.412937978 Z
    }, vars = {}, execution_time = 2023 - 03 - 17 T22: 55: 40.412949059 Z
}

I can print {{ ctx.metadata }} but can't figure out how to get into the hits array.

How can I iterate {{ ctx }} and print the source, slot and empty fields?

Hi - nice job getting most of your watch to work.

There's a clue to what you need to do when you look at the contents of ctx. Notice that first of all, you need to reference the things by their hierarchy in the ctx object. So, really, ctx.payload.aggregations.unque_sources.sources.buckets is the array that you'll need to loop through (not ctx.payload.hits).

So, something like:

{{#ctx.payload.aggregations.airlines.buckets}}
IP={{key}} in slot {{top_source.hits.hits.0.slot}} had the following problem: {{top_source.hits.hits.0.description}} 
{{/ctx.payload.aggregations.airlines.buckets}}

Give it a shot!

Thanks for the guidance. I was able to get it working following your instructions. Here is what it looks like now:

{{#ctx.payload.aggregations.unique_sources.sources.buckets}}
<div><b>Source</b>:{{key}}<br>
  {{#top_source.hits.hits}}
    <b>Description</b>: {{_source.description}}<br>
    <b>TID</b>: {{_source.tid}}<br>
    <b>Slot</b>: {{_source.slot}}<br>
    <b>Parent</b>: {{_source.parent}}<br>
    <b>Slot empty</b>: {{_source.empty}}<br>
    <b>Power Status</b>: {{_source.power_admin_state}}<br><br></div>
  {{/top_source.hits.hits}}
{{/ctx.payload.aggregations.unique_sources.sources.buckets}}
1 Like

nice!

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