# Alarms

An **alarm** is what OpenGate raises when a rule detects something worth a human's attention: a device that
stopped reporting, a value out of range, an identification conflict. This API is how a back-office
application finds them, counts them, and records that somebody dealt with them.

## The alarm life cycle

```mermaid
stateDiagram-v2
    direction LR
    [*] --> OPEN: a rule raises the alarm
    OPEN --> ATTENDED: action ATTEND
    OPEN --> CLOSED: action CLOSE
    ATTENDED --> CLOSED: action CLOSE
    CLOSED --> [*]
```

| Status | Meaning |
|---|---|
| `OPEN` | The alarm is active |
| `ATTENDED` | An operator is dealing with it |
| `CLOSED` | The alarm is closed |

Two more attributes tell you how much it matters:

| Attribute | Values |
|---|---|
| `severity` | `INFORMATIVE` (only informative) · `URGENT` (needs attention soon) · `CRITICAL` (critical for service operation) |
| `priority` | `LOW` · `MEDIUM` · `HIGH` |

## Endpoints

| To | POST to |
|---|---|
| Search alarms on any entity | `/north/v80/search/entities/alarms` |
| Search alarms on devices | `/north/v80/search/entities/devices/alarms` |
| Search alarms on subscriptions | `/north/v80/search/entities/subscriptions/alarms` |
| Count instead of list | The same three URLs with `/summary` |
| Attend or close alarms | `/north/v80/alarms` |

Searches follow the standard [query language](../data_lake/): `filter`, `select`, `sort`, `group` and
`limit`, with results in JSON by default or CSV through header options.

## Finding alarms

```bash
curl --request POST \
     --header "X-ApiKey: <your-api-key>" \
     --header "Content-Type: application/json" \
     --data '{"filter": {"like": {"alarm.channel": "default_channel"}}}' \
     https://api.opengate.es/north/v80/search/entities/alarms
```

```json
{
  "alarms": [
    {
      "identifier": "6c6c3bcb-633e-4418-ae6d-ed69a1db7e96",
      "name": "alarmForDevice",
      "severity": "CRITICAL",
      "priority": "HIGH",
      "status": "CLOSED",
      "entityIdentifier": "device_ogmapiXXX9",
      "organization": "org_ogmapiXXX9",
      "channel": "chn_ogmapiXXX9",
      "openingDate": "2020-08-21T10:42:35.507Z",
      "closureDate": "2020-08-21T10:42:54.186Z"
    }
  ],
  "page": { "number": 1 }
}
```

### Fields you can filter and sort on

| Group | Fields |
|---|---|
| Identity | `alarm.identifier` · `alarm.name` · `alarm.rule` · `alarm.description` |
| Classification | `alarm.severity` · `alarm.priority` · `alarm.status` |
| Where | `alarm.organization` · `alarm.channel` · `alarm.entityIdentifier` · `alarm.subEntityIdentifier` · `alarm.resourceType` |
| Opening | `alarm.openingDate` |
| Attention | `alarm.attentionDate` · `alarm.attentionUser` · `alarm.attentionNote` |
| Closure | `alarm.closureDate` · `alarm.ClosureUser` · `alarm.closureNote` |

Everyday queries follow from those: everything still open and critical, everything a given operator
attended, everything raised on one device last week.

```json
{
  "filter": {
    "and": [
      { "eq": { "alarm.status": "OPEN" } },
      { "eq": { "alarm.severity": "CRITICAL" } }
    ]
  },
  "sort": { "parameters": [ { "name": "alarm.openingDate", "type": "DESCENDING" } ] }
}
```

## Counting alarms

The `/summary` endpoints answer *how many*, which is what a dashboard needs. An empty filter summarizes
everything:

```json
{ "filter": {} }
```

The response counts alarms and breaks them down by group:

```json
{
  "summary": {
    "date": "2020-08-14T11:06:26.04Z",
    "count": 6,
    "summaryGroup": [
      { "severity": { "count": 6, "list": [
        { "count": 1, "name": "URGENT" },
        { "count": 3, "name": "CRITICAL" },
        { "count": 2, "name": "INFORMATIVE" }
      ] } },
      { "rule": { "count": 3, "list": [
        { "count": 1, "name": "alarmForSubsInDevice" },
        { "count": 1, "name": "alarmForDevice" },
        { "count": 1, "name": "alarmForSubscription" }
      ] } },
      { "status": { "count": 3, "list": [ { "count": 3, "name": "OPEN" } ] } },
      { "name": { "count": 3, "list": [ { "count": 3, "name": "identificationConflict" } ] } }
    ]
  }
}
```

{{% notice style="warning" title="Only four fields can group a summary" icon="triangle-exclamation" %}}
Summaries group by `alarm.name`, `alarm.rule`, `alarm.status` and `alarm.severity`. Any other field
returns `400 Bad Request`.
{{% /notice %}}

## Attending and closing

Alarms are not deleted, they are moved along their life cycle. One request handles a batch, and the `notes`
field records why — which is what makes the alarm history auditable afterwards:

```bash
curl --request POST \
     --header "X-ApiKey: <your-api-key>" \
     --header "Content-Type: application/json" \
     --data '{"action": "CLOSE", "alarms": ["50dca9ab-f552-4805-9cff-019090d5b92b"], "notes": "notes of the reason"}' \
     https://api.opengate.es/north/v80/alarms
```

| Field | Holds |
|---|---|
| `action` | `ATTEND` or `CLOSE` |
| `alarms` | The identifiers to act on, one or many |
| `notes` | The reason, stored as `attentionNote` or `closureNote` |

The user performing the action is recorded in `attentionUser` or `ClosureUser`, with its timestamp, so you
can query later who handled what.

## API specification

{{< openapi src="alarms.yaml" >}}
