# OpenSearch

EvoHub receives OpenSearch Alerting notifications through a **Custom webhook** notification channel. Each notification from a monitor's trigger opens an EvoHub alert. The default action message works as it is; a short JSON template adds structured fields.

## Set it up

:::steps
### Create the integration
In EvoHub, go to **On-Call → Integrations → + Add Integration**, choose **OpenSearch**, pick an **Escalation Policy** and click **Create Integration**. Copy the **Webhook URL**.
### Create a channel
In OpenSearch, go to **Notifications → Channels → Create channel** and choose **Custom webhook**.
### Set the URL
Set **Define endpoint by** to **Webhook URL** and paste your webhook URL.

```text
https://evohub.io/ingest/opensearch?key=YOUR_INTEGRATION_KEY
```
### Use it in monitors
Select the channel in the actions of your monitors' triggers.
:::

> [!WARNING]
> Use **Webhook URL**, not **Custom attributes URL**. In the custom attributes mode the `?key=` part is dropped, and every delivery is refused with `401`.

### Use the JSON template (optional)

For richer fields, replace the trigger action's message with:

```json
{
  "monitor": "{{ctx.monitor.name}}",
  "trigger": "{{ctx.trigger.name}}",
  "severity": "{{ctx.trigger.severity}}",
  "message": "{{ctx.trigger.name}}",
  "period_start": "{{ctx.periodStart}}",
  "period_end": "{{ctx.periodEnd}}"
}
```

## No auto-resolve

EvoHub does not read a recovery from anything OpenSearch sends, so these alerts do not resolve automatically. Resolve them in EvoHub when the problem is handled. On a bucket-level monitor with per-alert actions, leave **Completed** out of the actionable alerts: EvoHub would read that notification as another alert, not a recovery.

## What EvoHub reads

With the JSON template:

| EvoHub alert | Taken from |
| --- | --- |
| Title | `trigger`, else `monitor`, else "OpenSearch Alert". |
| Description | `message`. |
| Labels | `monitor` and `trigger`. |
| Fingerprint | The monitor and trigger names together. |

With the default message ("Monitor … just entered alert status. Please investigate the issue." followed by `- Trigger:`, `- Severity:` and period lines), EvoHub reads the monitor name, the trigger and the severity from the text, and the whole message becomes the description. Title, labels and fingerprint are as above.

### Severity

| OpenSearch trigger severity | EvoHub severity |
| --- | --- |
| 1 (highest) | critical |
| 2 | high |
| 3 | medium |
| 4 | low |
| 5 | info |
| missing or anything else | medium |

## Resolve and deduplication

- Another notification for the same monitor and trigger while its alert is open is recorded as **Retriggered**. Once you resolve the alert, the next notification opens a new one.
- Nothing from OpenSearch resolves an alert.

## Test messages

The channel's **Send test message** opens a real alert titled "OpenSearch test message received", severity **medium**, under the integration's escalation policy, so the whole path is exercised, paging included. It carries the label `test=true`. Repeated test messages while it is open are recorded as **Retriggered**. Resolve it in EvoHub afterwards.

## Troubleshooting

- **`401 INVALID_KEY`**: the key is wrong or the integration is disabled — or the channel uses **Custom attributes URL**, which drops `?key=`. Switch **Define endpoint by** to **Webhook URL**.
- **`400 INVALID_BODY`**: the action message is neither JSON nor OpenSearch's default text. Go back to the default message or paste the JSON template above.
- **Several triggers of one monitor share one alert**: the JSON template leaves out `trigger`. Keep both `monitor` and `trigger`; together they tell alerts apart.

## Related

- [Integrations overview](https://docs.evohub.io/integrations-overview.md)
- [Elastic / Kibana](https://docs.evohub.io/elastic-kibana.md)
- [Escalation policies](https://docs.evohub.io/escalation-policies.md)
