Help! Is it possible to make alarm like this?

Hi team, I am struggling to find whether Kibana is feasible to do this.

Is it possible to make alarm like picture 2?

If you know, would you guided me how I can do this?

Thanks !

Hi Isacc_Lee - welcome to the community!

I think we need to also understand the requirement of time here. Is this over "all time"? Only for the last 1 hour, day, week, etc?

Also, is the condition always on "Group A" (and there are no conditions for the other groups)?

Lastly, can you provide a real example of what a sample document looks like for this. That would be helpful

Hi @richcollier

It is last 1 hour and condition always for Group A.

Example doc would be

Doc1 {age: 7, group: classroomA }
Doc2 {age: 10, group: classroomA }
Doc3 {age: 8, group: classroomB }

Group | Avg of Age | alarm when A is smaller than any in [B or C]
A | 10 |
B | 11 |
C | 7 |

Something is missing...

Can I assume that the doc should also contain a timestamp? Otherwise, how else are you going to average ages per group over the last hour?

Correct. There is timestamp as well

Well, certainly you can do this with Watcher. So for example for the data:

PUT /students/
{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"   
        },
      "student": {
        "type": "keyword"
      },
      "group": {
        "type": "keyword"
      },
      "age": {
        "type": "long"
      }
    }
  }
}

PUT students/_doc/1
{
  "@timestamp": "2023-05-23 11:00:00",
  "student": "1",
  "group": "classroomA",
  "age": "8"
}

PUT students/_doc/2
{
  "@timestamp": "2023-05-23 11:01:00",
  "student": "2",
  "group": "classroomB",
  "age": "9"
}

PUT students/_doc/3
{
  "@timestamp": "2023-05-23 11:02:00",
  "student": "3",
  "group": "classroomC",
  "age": "12"
}

PUT students/_doc/4
{
  "@timestamp": "2023-05-23 11:03:00",
  "student": "4",
  "group": "classroomC",
  "age": "13"
}

A search that could query for the last hour, then aggregate the average age of students for each group would look like this (assuming your timestamps are truly in the last hour (now-1h):

GET students/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "@timestamp": {
              "gte": "now-1h"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "by_hour": {
      "date_histogram": {
        "field": "@timestamp",
        "calendar_interval": "hour"
      },
      "aggs": {
        "by_group": {
          "terms": {
            "field": "group",
            "size": 10
          },
          "aggs": {
            "avg_age": {
              "avg": {
                "field": "age"
              }
            }
          }
        }
      }
    }
  }
}

So then your Watch would only focus on the aggs part and put logic on the condition to only return true only if Classroom A has an average student age less than Classroom B or Classroom C :

POST _watcher/watch/_execute
{
  "watch": {
    "trigger": {
      "schedule": {
        "interval": "1h"
      }
    },
    "input": {
      "search": {
        "request": {
          "indices": [
            "students"
            ],
            "body": {
              "size": 0,
              "query": {
                "bool": {
                  "filter": [
                    {
                      "range": {
                        "@timestamp": {
                          "gte": "now-1h"
                        }
                      }
                    }
                    ]
                }
              },
              "aggs": {
                "by_hour": {
                  "date_histogram": {
                    "field": "@timestamp",
                    "calendar_interval": "hour"
                  },
                  "aggs": {
                    "by_group": {
                      "terms": {
                        "field": "group",
                        "size": 10
                      },
                      "aggs": {
                        "avg_age": {
                          "avg": {
                            "field": "age"
                          }
                        }
                      }
                    }
                  }
                }
              }
              
            }
        }
      }
    },
    "condition": {
      // make the data into a simple data structure - a HashMap
      "script": """
        Map student_group_avgs = new HashMap();
	          for (def bucket : ctx.payload.aggregations.by_hour.buckets.0.by_group.buckets) {
                student_group_avgs.put(bucket.key, bucket.avg_age.value); 
	            }
	    //return true only if Classroom A has an average student age less than Classroom B or Classroom C   
	       if ( (student_group_avgs.get("classroomA") <  student_group_avgs.get("classroomB")) || (student_group_avgs.get("classroomA") <  student_group_avgs.get("classroomC")))  return true;
      """
    },
    "actions": {
      "log": {
        "logging": {
          "text": """
          Alert - Classroom A has an average student age less than Classroom B or Classroom C. Data:
          {{ctx.payload}}
          """
        }
      }
    }
  }
}

Hope that's the kind of thing you were looking for

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