# Monitors

> Alert when a metric or a count of matching logs crosses a threshold for a while.

A monitor watches one query over a sliding window and alerts when a condition holds.

- **Query:** a metric (`name`, optional `attrs`, and `avg`, `sum`, `min`, `max` or `count`), or logs (optional `service`, `minSev`, `contains`, `attrs`), whose value is the number of matching records.
- **Window:** 1 to 60 minutes.
- **Condition:** `>` or `<` a threshold.

Pulse evaluates every monitor once a minute. When the condition holds over the window, the monitor goes from `ok` to `alerting` and Pulse sends a trigger; when it stops holding, it goes back to `ok` and Pulse sends a resolve. A metric window with no data at all changes nothing.

```json
{ "name": "Queue backing up",
  "spec": { "query": { "signal": "metrics", "name": "queue.depth", "agg": "avg" }, "windowMin": 5, "op": ">", "threshold": 1000 } }
```

```json
{ "name": "Checkout errors",
  "spec": { "query": { "signal": "logs", "service": "checkout", "minSev": 17 }, "windowMin": 10, "op": ">", "threshold": 20 } }
```

A new monitor judges data that arrives after it was created, so its first full window ends `windowMin` minutes later.

Manage them in **Monitors** in the app, with `GET/POST /api/v1/monitors` and `PATCH/DELETE /api/v1/monitors/:id`, or with the MCP tools `list_monitors`, `create_monitor`, `update_monitor` and `delete_monitor`. Alerts go where [Alerts and Shift](/docs/alerts-and-shift/) says.
