# Watcher - Actions conditions in foreach

**URL:** <https://discuss.elastic.co/t/watcher-actions-conditions-in-foreach/324349>\
**Category:** Elasticsearch\
**Tags:** elastic-stack-alerting, painless, runtime-fields\
**Created:** [January 31, 2023, 2:37pm UTC](https://discuss.elastic.co/t/watcher-actions-conditions-in-foreach/324349 "2023-01-31T14:37:36Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![v\_watch](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/v_watch/32/116601_2.png) [@v\_watch](https://discuss.elastic.co/u/v_watch)\
**Post date:** [January 31, 2023, 2:37pm UTC](https://discuss.elastic.co/t/watcher-actions-conditions-in-foreach/324349/1 "2023-01-31T14:37:37Z")

</div>

Hello,  
I am trying to create a watcher that must send a different slack message depending on the field "state" from each log in the hits.hits The slack message must have:  
"color" = "good" if the state is finished  
"color" = "warning" if the state is started  
"color" = "error" if the state is failed.

Basically, for every hit that the watcher receives from the query, I want to send a slack message with a specific color based on the state field.

A very simplified input of what the watcher might be receiving:

```auto
{
    "hits": {
        "hits": [
          {
            "_index": "com1:log-1-4X-7",
            "_type": "_doc",
            "_source": {
              "level": 30,
              "description": "Log description here",
              "state": "finished",
              "clientId": "1",
              "eventName" : "RENTING"
            },
            "_id": "7-x",
            "_score": 49.16513
          },
          {
            "_index": "com1:log-1-4X-7",
            "_type": "_doc",
            "_source": {
              "level": 30,
              "description": "Another Log description here",
              "state": "started",
              "clientId": "2",
              "eventName" : "BUYING"
            },
            "_id": "A-x",
            "_score": 48.56805
          }      
        ],
        "total": 2,
        "max_score": 49.16513
      }
    }

```

How could I set up these multiple actions for the conditions mentioned above?  
I've tried to create a watcher like the one bellow, but I receive this error below in the simulate tab:

```auto
    "actions": [
      {
        "id": "notify-slack2",
        "type": "slack",
        "status": "condition_failed",
        "reason": "condition failed. skipping: runtime error"
      },
      {
        "id": "notify-slack",
        "type": "slack",
        "status": "condition_failed",
        "reason": "condition failed. skipping: runtime error"
      }
    ]
  }

```

The watcher that I am using to test this:

```auto
{
  "trigger": {
    "schedule": {
      "interval": "30m"
    }
  },
  "input": {
    "search": {
      "request": {
        "body": {
          "size": 0,
          "query": {
            "match_all": {}
          }
        },
        "indices": [
          "*"
        ]
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.hits.total": {
        "gte": 0
      }
    }
  },
   "actions": {
        "notify-slack": {
            "foreach": "ctx.payload.hits.hits",
            "condition": {
                "script": {
                    "source": " return ctx.payload._source.state == 'started'",
                    "lang": "painless"
                }
            },
            "slack": {
                "message": {
                    "to": [
                        "#test-channel"
                    ],
                    "attachments": [
                        {
                            "color": "warning",
                            "title": "It is starting",
                            "text": "{{ctx.payload._source.state}}"
                        }
                    ]
                }
            }
        },
        "notify-slack2": {
            "foreach": "ctx.payload.hits.hits",
            "condition": {
                "script": {
                    "source": " return ctx.payload._source.state == 'finished'",
                    "lang": "painless"
                }
            },
            "slack": {
                "message": {
                    "to": [
                        "#test-channel"
                    ],
                    "attachments": [
                        {
                            "color": "good",
                            "title": "It is finisehd",
                            "text": "{{ctx.payload._source.state}}"
                        }
                    ]
                }
            }
        }
    }
}

```

I am not sure if it is an issue accessing ctx.payload.\_source.state in the script because it is under a foreach.

I tested setting the script condition to 1==1 and the message came with the text state right, so {{ctx.payload.\_source.state}} works fine inside the action.  
How could I set up this script condition for each action as it must run foreach hit? Elastic version: 7.17.7

---

<div class="post-metadata">

**Author:** ![richcollier](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/richcollier/32/115035_2.png) [@richcollier](https://discuss.elastic.co/u/richcollier)\
**Post date:** [January 31, 2023, 9:40pm UTC](https://discuss.elastic.co/t/watcher-actions-conditions-in-foreach/324349/2 "2023-01-31T21:40:03Z")

</div>

I did a simple mockup using your two example documents.

I used a `transform` block to build a data structure (and ArrayList, for example) of all of the things you want to alert on. For example:

```auto
    "transform": {
      "script": """
            def my_hits = new ArrayList();
            for (def my_hit : ctx.payload.hits.hits) {
              if (my_hit._source.state == "started") {
                  def info = new HashMap();
                  info.put("color","warning");
                  info.put("state","started");
                  info.put("title","It is starting");
                  my_hits.add(info);
                }
                else if (my_hit._source.state == "finished") {
                  def info = new HashMap();
                  info.put("color","good");
                  info.put("state","finished");
                  info.put("title","It is finished");
                  my_hits.add(info);
                }
                else if (my_hit._source.state == "failed") {
                  def info = new HashMap();
                  info.put("color","error");
                  info.put("state","failed");
                  info.put("title","It is failed");
                  my_hits.add(info);
                }
            }
      return my_hits;
      """
    },
    "actions": {
      "log": {
        "foreach": "ctx.payload._value",
        "logging": {
          "text": """
		        {{ctx.payload}}
		      """
        }
      }
    }

```

The output data structure after the `transform` block looks like:

```auto
        "payload": {
          "_value": [
            {
              "color": "good",
              "state": "finished",
              "title": "It is finished"
            },
            {
              "color": "warning",
              "state": "started",
              "title": "It is starting"
            }
          ]
        }
      },

```

Obviously I chose to log rather than slack, but you get the idea

---

<div class="post-metadata">

**Author:** ![Ayush\_Mathur](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/ayush_mathur/32/77134_2.png) [@Ayush\_Mathur](https://discuss.elastic.co/u/Ayush_Mathur)\
**Post date:** [February 1, 2023, 7:57am UTC](https://discuss.elastic.co/t/watcher-actions-conditions-in-foreach/324349/3 "2023-02-01T07:57:33Z")

</div>

@v_watch I'd rather prefer using aggregations instead of querying the data and then transforming.

1. Use terms aggregation on event -\> key will be the event name
2. Use terms aggregation on state -\> key will give state of the event
3. Condition can simply check if event buckets length \> 0
4. A single slack action with `{{#ctx.payload.aggregations.event.buckets}}{{key}} has state {{state.buckets[0].key}}{{/ctx.payload.aggregations.event.buckets}}`

Also, you can refer to conditional actions on watcher here: [Adding conditions to Watcher actions | Elasticsearch Guide [master] | Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/master/action-conditions.html)

---

<div class="post-metadata">

**Author:** ![richcollier](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/richcollier/32/115035_2.png) [@richcollier](https://discuss.elastic.co/u/richcollier)\
**Post date:** [February 1, 2023, 11:59am UTC](https://discuss.elastic.co/t/watcher-actions-conditions-in-foreach/324349/4 "2023-02-01T11:59:06Z")

</div>

@Ayush_Mathur that's true except there's still the missing requirement of mapping `state` to `color`

> [@v\_watch](#):
>
> "color" = "good" if the state is finished  
> "color" = "warning" if the state is started  
> "color" = "error" if the state is failed.

---

<div class="post-metadata">

**Author:** ![v\_watch](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/v_watch/32/116601_2.png) [@v\_watch](https://discuss.elastic.co/u/v_watch)\
**Post date:** [February 1, 2023, 1:56pm UTC](https://discuss.elastic.co/t/watcher-actions-conditions-in-foreach/324349/5 "2023-02-01T13:56:41Z")

</div>

Thank you soo much Rich!!!!

Using the transform approach as you did worked perfectly and now I can customize the slack message further to make it even better if I need.  
This made the watcher much better than trying to set up a bunch of actions with conditions.

I really appreacite your help, thank you again!

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [March 1, 2023, 1:56pm UTC](https://discuss.elastic.co/t/watcher-actions-conditions-in-foreach/324349/6 "2023-03-01T13:56:47Z")

</div>

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