[Документация Yandex Cloud](../../index.md) > [Monium](../index.md) > Алерты > Алерты-выражения

# Алерты-выражения

Алерт-выражение вычисляет произвольное выражение на [языке запросов](../concepts/querying.md) и определяет статус алерта на основе результата вычисления. Например, с помощью выражения можно настроить алерт на процентиль по значению множества метрик.

## Создание алерта-выражения {#create-alert-expression}

Выражение объединяет загрузку данных, их обработку и логику перехода алерта в нужный статус. В этом состоит отличие алерта-выражения от [обычного алерта](../concepts/alerting/alert.md), где запрос и условия срабатывания настраиваются отдельно.

Порядок создания алерта-выражения аналогичен [созданию обычного алерта](../operations/alert/create-alert.md), при этом:

* Вместо запроса задается выражение.
* В условиях срабатывания доступны только два параметра: **Окно вычисления** и **Задержка вычисления**.

{% note info %}

В один [алерт](../concepts/glossary.md#alert) или [подалерт](../concepts/glossary.md#subalert) можно загрузить не более 1 000 метрик. Если нужно выполнять вычисления по большему числу метрик, используйте один из следующих вариантов:

* создайте [мультиалерт](../concepts/alerting/alert.md#multi-alerts);
* примените [функции агрегации](../concepts/querying-functions.md#aggregation-functions) к метрикам, которые передаются в Monium Metrics;
* агрегируйте метрики на стороне клиента (например, в приложении) перед отправкой.

{% endnote %}

## Структура выражения {#structure-expression}

Выражение — программа, которая последовательно загружает данные, преобразует их и вычисляет итоговое значение или статус алерта. Обычно выражение состоит из селекторов метрик, переменных, функций агрегации и преобразования, арифметических и логических операций, а также функций управления статусами.

Выражение составляется на [языке запросов](../concepts/querying.md) со следующими дополнениями:

* Переменные — позволяют загружать данные и разбивать выражение на логические шаги:

    ```js
    let <var_name> = <expression>;
    ```

    В переменные можно загружать данные из текущего проекта или из других проектов, к которым у вас есть доступ. Для этого укажите метку `project`:

    ```js
    let data = { project='my_project', cluster='default', service='my_service', host='*', load_state='DONE' };
    ```

* Комментарии:

    ```js
    let a = 10 + 20; // my comment
    ```

* Тип данных — вектор.

    Сложный тип _Vector<T>_ — вектор значений определенного типа, например вектор метрик `Vector<Timeseries>` или вектор чисел `Vector<Scalar>`.

    Например, следующее выражение вернет вектор метрик `Vector<Timeseries>` с различными значениями метки `host`.

    ```
    {cluster='proxy', service='frontend', host='*', name='exceptionCount'}
    ```

### Управление статусами алерта {#status-functions}

Для управления статусами алерта используются [функции](#alert-functions):

```js
alarm_if(condition: Boolean): Void
warn_if(condition: Boolean): Void
no_data_if(condition: Boolean): Void
ok_if(condition: Boolean): Void
```

Если условие `condition` выполняется, функция прерывает выполнение программы и переводит алерт в соответствующий статус. Функции не возвращают значение, поэтому их результат нельзя присвоить переменной.

{% note warning %}

Функцию `alarm_if` необходимо вызывать раньше `warn_if`. Иначе в результате сравнения значения с порогом функция `warn_if` не передаст управление дальше, а переведет алерт в статус `OK`, так как условие для перехода в статус `Warning` не будет выполнено и алерт не перейдет в статус `Alarm`.

{% endnote %}

### Пример программы для выражения {#example}

```js
// Если по селектору не найдена ни одна метрика, алерт перейдет в статус No data еще до начала выполнения программы.
let data = {project="my_project", cluster="default", service="my_service", name="sinusoid"};

// Если метрика существует, но в окно вычисления алерта не попало ни одной точки — перевести алерт в статус No data.
no_data_if(count(data) == 0);

// Вычислить среднее значение метрики
let value = avg(data);

alarm_if(value > 100); // Перевести алерт в статус Alarm, если value превышает 100.
warn_if(value > 10);   // Перевести алерт в статус Warning, если value превышает 10.
```

В зависимости от результата вычисления алерт переходит в один из следующих статусов:

* `No data` — если метрика отсутствует в Monium, например удалена по [TTL](../concepts/glossary.md#ttl), или во временном окне нет точек.
* `Alarm` — если значение `value` превышает `100`. Функция `alarm_if` прерывает выполнение программы.
* `Warning` — если значение `value` находится в диапазоне `(10, 100]`. Функция `warn_if` прерывает выполнение программы.
* `OK` — если значение `value` не превышает `10`. Программа выполняется до конца.

## Описание функций {#alert-functions}

### Функции управления статусами {#status-functions}

{% note info %}

После перехода в статус дальнейшее вычисление алерта прекращается. Поэтому сначала проверяйте условие для `alarm_if`, а затем — для `warn_if`.

{% endnote %}

Например, в следующей программе `alarm_if` никогда не сработает, потому что выполнение остановится на строке с `warn_if`:

```js
let x = 10;

warn_if(x > 5);
alarm_if(x > 6);
```

#### alarm_if {#alarm-if}

Переводит алерт в статус `Alarm` при выполнении условия `condition`.

```js
alarm_if(condition: Boolean): Void
```

#### warn_if {#warn-if}

Переводит алерт в статус `Warning` при выполнении условия `condition`.

```js
warn_if(condition: Boolean): Void
```

#### no_data_if {#no-data-if}

Переводит алерт в статус `No data` при выполнении условия `condition`.

```js
no_data_if(condition: Boolean): Void
```

#### ok_if {#ok-if}

Переводит алерт в статус `OK` при выполнении условия `condition`.

```js
ok_if(condition: Boolean): Void
```

### Функции для работы с историей вычислений {#history-functions}

#### alert_evaluation_history {#alert-evaluation-history}

Возвращает историю вычислений алерта или подалерта в виде временного ряда. Точки ряда появляются с задержкой до одной минуты.

{% note info %}

Если алерт или подалерт находился под действием [мьюта](mutes.md), то в сырых метриках статусов к значению прибавляется `128`. Например, у алерта в статусе `Alarm` со значением `4` значение метрики будет равно `132` (`4 + 128`).

Функция `alert_evaluation_history` отбрасывает добавленное значение мьюта и возвращает временной ряд, значения которого соответствуют вычисленным статусам.

{% endnote %}

Функция имеет следующие варианты использования (перегрузки функции) в зависимости от количества входных параметров:

* **alert_evaluation_history**(): *Timeseries* — история вычислений текущего алерта.
* **alert_evaluation_history**(*projectId: String*, *alertId: String*): *Timeseries* — история вычислений алерта, который не является мультиалертом, в проекте. `alertId` — идентификатор алерта, `projectId` — идентификатор проекта.
* **alert_evaluation_history**(*projectId: String*, *alertId: String*, *parentId: String*): *Timeseries* — история вычислений подалерта в проекте. `projectId` — идентификатор проекта, `alertId` — идентификатор подалерта, `parentId` — идентификатор родительского мультиалерта.

В значениях `projectId`, `alertId` и `parentId` допускаются [шаблоны (glob-выражения)](https://ru.wikipedia.org/wiki/Шаблон_поиска). В этом случае функция возвращает несколько временных рядов для всех подходящих алертов.

Пример использования:

```js
let alert_statuses = alert_evaluation_history();
let problems = heaviside(alert_statuses - 1); // Точки со статусами No data и OK отображаются в 0, статусы Alarm, Warning, Error — в 1.
let good_points = drop_if(problems, data);    // Из ряда удаляются точки, в которых алерт был в статусе Alarm, Warning или Error.
```

#### multi_alert_evaluation_history {#multi-alert-evaluation-history}

Возвращает историю статусов мультиалерта в виде временного ряда. Точки ряда появляются с задержкой до одной минуты.

{% note info %}

Если подалерт находился под действием [мьюта](mutes.md), к значению метки `status` добавляется суффикс `:MUTED`. Например, у замьюченного подалерта в статусе `Alarm` будет записана метрика со значением метки `status=ALARM:MUTED`.

{% endnote %}

Функция **multi_alert_evaluation_history** имеет следующие варианты использования (перегрузки функции) в зависимости от количества входных параметров:

* **multi_alert_evaluation_history**(): *Vector\<Timeseries\>* — полный набор метрик с числом подалертов во всех статусах.
* **multi_alert_evaluation_history**(*status: String*): *Timeseries* — история вычисления подалертов данного мультиалерта с указанным статусом. `status` — интересующий статус подалертов (например `ALARM`).
* **multi_alert_evaluation_history**(*alertId: String*, *status: String*): *Timeseries* — история вычисления подалертов другого мультиалерта в текущем проекте с указанным статусом. `alertId` — идентификатор алерта, `status` — интересующий статус подалертов (например `ALARM`).
* **multi_alert_evaluation_history**(*projectId: String*, *alertId: String*, *status: String*): *Timeseries* — история вычисления подалертов другого мультиалерта в другом проекте с указанным статусом. `projectId` — идентификатор проекта, `alertId` — идентификатор алерта, `status` — интересующий статус подалертов (например `ALARM`).

В значениях `projectId`, `alertId` и `status` допускаются [шаблоны (glob-выражения)](https://ru.wikipedia.org/wiki/Шаблон_поиска). В этом случае функция возвращает несколько временных рядов для всех подходящих алертов.

Пример использования:

```js
let alert_statuses = multi_alert_evaluation_history('ALARM'); // Число подалертов в статусе Alarm.
alarm_if(last(alert_statuses) > 10);                          // Переводит алерт в статус Alarm, если число подалертов в статусе Alarm больше 10.
```

### Особенности использования функций управления статусами {#features}

1. Порядок вызова `alarm_if` и `warn_if`.

    В следующем примере статус `Alarm` никогда не будет установлен: при `value > 100` сначала выполнится условие `value > 10`, и алерт перейдет в статус `Warning`:

    ```js
    let data = {project="my_project", cluster="default", service="my_service", name="sinusoid"};

    no_data_if(count(data) == 0);
    let value = avg(data);

    warn_if(value > 10);
    alarm_if(value > 100);
    ```

    Чтобы получить ожидаемое поведение, ограничьте условие `warn_if` диапазоном или измените порядок вызова функций:

    ```js
    let data = {project="my_project", cluster="default", service="my_service", name="sinusoid"};

    no_data_if(count(data) == 0);
    let value = avg(data);

    alarm_if(value > 100);
    warn_if((value > 10) && (value <= 100));
    ```

1. Переменные после функций управления статусами.

    Если переменная объявлена после вызова `alarm_if`, `warn_if`, `no_data_if` или `ok_if`, то при прерывании программы значение переменной будет недоступно в аннотациях.

    Например, в следующей программе значение `not_var{{expression.valuePretty}}` будет подставляться в аннотации только для статуса `OK`. Для остальных статусов аннотация будет пустой строкой:

    ```js
    let data = {project="my_project", cluster="default", service="my_service", name="sinusoid"};

    no_data_if(count(data) == 0);
    let value = avg(data);

    alarm_if(value > 100);
    warn_if(value > 10);

    let valuePretty = to_fixed(100 * value, 2) + '%';
    ```

1. Разбиение сложного условия.

    С помощью нескольких вызовов `alarm_if` можно разбить сложное условие срабатывания на несколько простых условий и добавить пояснение к каждому из них.

    Например, условие `(requests < 100) || (errors > 20)` можно записать так:

    ```js
    ...
    let reason = 'Number of requests is low!';
    alarm_if(requests < 100);
    let reason = 'Number of errors is large!';
    alarm_if(errors > 20);
    let reason = 'Everything is ok';
    ```

    Чтобы сохранить информацию, по какому условию сработал алерт, добавьте в алерт аннотацию со значением переменной `not_var{{expression.reason}}`.