<a id="http-metric"></a>

# Metric

Модуль `ngx_http_metric_module` позволяет создавать вычисляемые в реальном времени
произвольные метрики. Значения таких метрик сохраняются в разделяемой памяти
и отображаются в реальном времени в ветке API `/status/http/metric_zones/`.
Поддерживаются различные типы агрегации данных (счетчики, гистограммы, скользящие средние и др.)
с группировкой по произвольным ключам.

<a id="configuration-example-30"></a>

## Пример конфигурации

Подсчет запросов к API:

```nginx
http {
    metric_zone api_requests:1m count;

    server {
        listen 80;

        location /api/ {
            allow 127.0.0.1;
            deny all;
            api /status/;

            metric api_requests $http_user_agent on=request;
        }
    }
}
```

Если с такой конфигурацией выполнить запрос на `/api/`:

```console
$ curl 127.0.0.1/api/ --user-agent "Firefox"
```

В реальном времени происходит обновление метрики `api_requests`:

```json
{
    "http": {
       "metric_zones": {
           "api_requests": {
               "discarded": 0,
               "metrics": {
                   "Firefox": 1
               }
           }
       }
    }
}
```

<a id="directives-31"></a>

## Директивы

<a id="index-0"></a>

<a id="metric-zone"></a>

### metric_zone

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `metric_zone` название:размер [`expire`=`on`| `off`] [`discard_key`=`название`] режим [параметры];   |
|------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
| По умолчанию                                                                             | —                                                                                                    |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | http                                                                                                 |

Создает зону разделяемой памяти указанного размера с именем название,
в которой хранятся метрики. Имя зоны является узлом в ветке
`/status/http/metric_zones/`.

Параметры:

- `expire=<on|off>` — поведение при переполнении зоны:
  - Если `on`, самые старые метрики по времени обновления отбрасываются,
    освобождая память под поступающие;
  - Если `off` (по умолчанию) — отбрасываются поступающие метрики,
    сохраняя информацию об установленных.
- `discard_key=<название>` — задает метрику с ключом название,
  в которой сохраняются значения отброшенных метрик. По умолчанию такая метрика
  не создается. Зарезервированный ключ нельзя обновлять вручную.
- режим — алгоритм обработки значений (см. раздел [Режимы работы](#metric-modes));
- параметры — дополнительная настройка выбранного режима
  (например, `factor` для `average exp`).

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

```nginx
metric_zone request_time:1m max;
```

В API дереве шаблон зоны разделяемой памяти выглядит следующим образом:

```json
{
    "discarded": 0,
    "metrics": {
        "ключ1": 123,
        "ключ2": 10.5,
    }
}
```

| `discarded`   | Число; количество отброшенных метрик в зоне разделяемой памяти                  |
|---------------|---------------------------------------------------------------------------------|
| `metrics`     | Объект; его члены — метрики с установленными ключами и подсчитанными значениями |

#### NOTE
В зоне размером 1 мегабайт при размере ключа 39 байт и с одним режимом
метрики может разместиться около 8 тысяч записей с уникальным ключом.

<a id="index-1"></a>

<a id="metric-complex-zone"></a>

### metric_complex_zone

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `metric_complex_zone` название:размер [`expire`=`on`| `off`] [`discard_key`=`название`] { ... }   |
|------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
| По умолчанию                                                                             | —                                                                                                 |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | http                                                                                              |

Определяет составную метрику — набор метрик с независимыми режимами.
Каждая строка в теле блока задает название подметрики, режим
и необязательные параметры режима.

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

```nginx
metric_complex_zone requests:1m expire=on discard_key="old" {
    # название подметрики   режим работы    параметры
    min_time                min;
    avg_time                average exp     factor=60;
    max_time                max;
    total                   count;
}
```

В API дереве шаблон такой составной метрики выглядит следующим образом:

```json
{
    "discarded": 3,
    "metrics": {
        "ключ1": {
            "min_time": 20,
            "avg_time": 50,
            "max_time": 80,
            "total": 2
        },
        "old": {
             "min_time": 3,
             "avg_time": 40,
             "max_time": 152,
             "total": 80
        }
    }
}
```

| `discarded`   | Число; количество отброшенных метрик в зоне разделяемой памяти                                                                                        |
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
| `metrics`     | Объект; его члены — составные метрики с установленными ключами. Они представляют собой объекты, содержащие набор подметрик с подсчитанными значениями |

<a id="index-2"></a>

<a id="id5"></a>

### metric

| [Синтаксис](https://angie.software//angie/docs/configuration/configfile.md#configfile)   | `metric` название ключ=значение [`on`=`request`| `response`| `end`];   |
|------------------------------------------------------------------------------------------|------------------------------------------------------------------------|
| По умолчанию                                                                             | —                                                                      |
| [Контекст](https://angie.software//angie/docs/configuration/configfile.md#configfile)    | http, server, location                                                 |

Подсчитывает значение метрики с указанным названием зоны разделяемой памяти.

Параметры:

- ключ — произвольная строка (часто переменная), по которой группируются
  значения. Максимальная длина — 255 байт. Если ключ длиннее, он будет
  ограничен размером 255 байт и дополнен `...` многоточием;
- значение — число (может быть переменной), обрабатываемое выбранным режимом.
  Если пропущено, считается `0`. Если параметр невозможно преобразовать
  в число, считается `1`;
- `on` — необязательный параметр, указывающий в какой момент происходит
  подсчет метрики:
  - Если `on=request`, подсчет происходит при получении запроса;
  - Если `on=response`, подсчет происходит при подготовке ответа;
  - Если `on=end` (по умолчанию), подсчет происходит после отправки ответа.

#### NOTE
В случае внутреннего перенаправления, метрики на стадии `on=request`
посчитаются в исходном `location`. При этом метрики
`on=response` и `on=end` будут подсчитаны уже в новом
`location`.

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

```nginx
metric requests $http_user_agent=$request_time;
```

#### NOTE
Метрики с пустым ключом или неправильной парой `ключ=значение`
не учитываются. Пропущенное значение учитывается как `0`:

```nginx
metric foo $bar;  # Вместо $bar=0
```

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

#### NOTE
Важно помнить, что переменные вычисляются в разных фазах. Например,
невозможно использовать `$bytes_sent` (количество отправленных байт клиенту)
при `on=request` (при получении запроса).

<a id="metric-modes"></a>

## Режимы работы

Список доступных режимов работы метрик:

* `count` — счетчик обращений;
* `gauge` — стрелка (инкремент/декремент);
* `last` — последнее поступившее значение;
* `min` — минимальное значение;
* `max` — максимальное значение;
* `average exp` — скользящее среднее (параметр `factor`);
* `average mean` — среднее за окно (параметры `window` и `count`);
* `histogram` — распределение по "бакетам" (перечень пороговых значений).

<a id="count"></a>

### count

Счетчик увеличивает свое значение на `1` при каждом обновлении метрики.

Значение по умолчанию — `0`.

#### NOTE
Любое обновление метрики (с любым значением) монотонно увеличивает
счетчик на `1`.

Примеры:

```nginx
metric_zone count:1m count;

# В качесте составной метрики:
#
# metric_complex_zone count:1m {
#     some_metric_name  count;
# }

server {
    listen 80;

    location /metric/ {
        metric count KEY;
    }

    location ~ ^/metric/set/(.+)$ {
        metric count KEY=$1;
    }

    location /api/ {
        api /status/http/metric_zones/count/metrics/;
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/
$ curl 127.0.0.1/metric/set/1
$ curl 127.0.0.1/metric/set/23
$ curl 127.0.0.1/metric/set/-32
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": 4
}
```

<a id="gauge"></a>

### gauge

Счетчик увеличивает или уменьшает свое значение в зависимости
от знака переданного числа. При положительном — увеличивает счетчик.
При отрицательном — уменьшает. Переданное значение `0` не изменяет счетчик.

Значение по умолчанию — `0`.

Примеры:

```nginx
metric_zone gauge:1m gauge;

# В качесте составной метрики:
#
# metric_complex_zone gauge:1m {
#     some_metric_name  gauge;
# }

server {
    listen 80;

    location /metric/ {
        metric gauge KEY;
    }

    location ~ ^/metric/set/(.+)$ {
        metric gauge KEY=$1;
    }

    location /api/ {
        api /status/http/metric_zones/gauge/metrics/;
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": 0
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/5
$ curl 127.0.0.1/metric/set/-5
$ curl 127.0.0.1/metric/set/8
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": 8
}
```

<a id="last"></a>

### last

Хранит последнее полученное значение без какой-либо агрегации.
Если значение опущено, используется `0`.

Примеры:

```nginx
metric_zone last:1m last;

# В качесте составной метрики:
#
# metric_complex_zone last:1m {
#     some_metric_name  last;
# }

server {
    listen 80;

    location /metric/ {
        metric last KEY;
    }

    location ~ ^/metric/set/(.+)$ {
        metric last KEY=$1;
    }

    location /api/ {
        api /status/http/metric_zones/last/metrics/;
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": 0
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/8000
$ curl 127.0.0.1/metric/set/37
$ curl 127.0.0.1/metric/set/-3.5
```

Ожидаемое значение метрики в API:

```json
{
   "KEY": -3.5
}
```

<a id="min"></a>

### min

Сохраняет минимальное из двух значений — уже сохраненного и нового.

Примеры:

```nginx
metric_zone min:1m min;

# В качесте составной метрики:
#
# metric_complex_zone min:1m {
#     some_metric_name  min;
# }

server {
    listen 80;

    location /metric/ {
        metric min KEY;
    }

    location ~ ^/metric/set/(.+)$ {
        metric min KEY=$1;
    }

    location /api/ {
        api /status/http/metric_zones/min/metrics/;
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/42.999
$ curl 127.0.0.1/metric/set/-512
$ curl 127.0.0.1/metric/set/1
$ curl 127.0.0.1/metric/
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": -512
}
```

<a id="max"></a>

### max

Сохраняет наибольшее из двух значений — уже сохраненного и нового.

Примеры:

```nginx
metric_zone max:1m max;

# В качесте составной метрики:
#
# metric_complex_zone max:1m {
#     some_metric_name  max;
# }

server {
    listen 80;

    location /metric/ {
        metric max KEY;
    }

    location ~ ^/metric/set/(.+)$ {
        metric max KEY=$1;
    }

    location /api/ {
        api /status/http/metric_zones/max/metrics/;
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/42.999
$ curl 127.0.0.1/metric/set/-512
$ curl 127.0.0.1/metric/set/1
$ curl 127.0.0.1/metric/
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": 42.999
}
```

<a id="average-exp"></a>

### average exp

Вычисляет среднее значение по алгоритму
[экспоненциального сглаживания](https://en.wikipedia.org/wiki/Exponential_smoothing).

Принимает необязательный параметр `factor=<число>` — коэффициент,
по которому установленное значение учитывается при расчете среднего.
Допустимы целые числа от `0` до `99`. По умолчанию — `90`.

Чем больше коэффициент, тем сильнее новые значения влияют на среднее.
Если указать `90`, то будет взято `90%` от нового значения
и лишь `10%` от предыдущего.

Примеры:

```nginx
metric_zone avg_exp:1m average exp factor=60;

# В качесте составной метрики:
#
# metric_complex_zone avg_exp:1m {
#     some_metric_name  average exp  factor=60;
# }

server {
    listen 80;

    location ~ ^/metric/set/(.+)$ {
        metric avg_exp KEY=$1;
    }

    location /api/ {
        api /status/http/metric_zones/avg_exp/metrics/;
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/100
$ curl 127.0.0.1/metric/set/200
$ curl 127.0.0.1/metric/set/0
$ curl 127.0.0.1/metric/set/8
$ curl 127.0.0.1/metric/set/30
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": 30.16
}
```

<a id="average-mean"></a>

### average mean

Вычисляет среднее арифметическое. Принимает необязательные параметры
`window=<off|время>` и `count=<число>`,
задающие соответственно интервал времени и объем выборки для усреднения.
По умолчанию: `window=off` (учитывается вся выборка) и `count=10`.

#### NOTE
Например, `window=5s` будет учитывать только события последних 5 секунд.
Параметрик `window` не может принимать значение `0`. Параметр
`count=число` управляет размером выборки (закэшированных значений)
для более плавного подсчета среднего.

Примеры:

```nginx
metric_zone avg_mean:1m average mean window=5s count=8;

# В качесте составной метрики:
#
# metric_complex_zone avg_mean:1m {
#     some_metric_name  average mean  window=5s count=8;
# }

server {
    listen 80;

    location ~ ^/metric/set/(.+)$ {
        metric avg_mean KEY=$1;
    }

    location /api/ {
        api /status/http/metric_zones/avg_mean/metrics/;
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/0.1
$ curl 127.0.0.1/metric/set/0.1
$ curl 127.0.0.1/metric/set/0.4
$ curl 127.0.0.1/metric/set/10
$ curl 127.0.0.1/metric/set/1
$ curl 127.0.0.1/metric/set/1
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": 2.1
}
```

Если подождать 5 секунд, с момента последнего обновления метрики, то
ожидаемое значение метрики в API:

```json
{
    "KEY": 0
}
```

<a id="histogram"></a>

### histogram

Создает набор "бакетов", увеличивая соответствующий счетчик,
если новое значение не превосходит порога бакета.
Формат параметров — список числовых порогов.
Полезен для анализа распределения, например времени ответа.

В качестве обязательных параметров передаются числа — предельные значения
бакетов, перечисленные в порядке возрастания.

#### NOTE
Значение бакета `inf` или `+Inf` можно использовать
для захвата всех значений, превышающих максимальный бакет.

Примеры:

```nginx
metric_zone hist:1m histogram 0.1 0.2 0.5 1 2 inf;

# В качесте составной метрики:
#
# metric_complex_zone hist:1m {
#     some_metric_name  histogram  0.1 0.2 0.5 1 2 inf;
# }

server {
    listen 80;

    location ~ ^/metric/set/(.+)$ {
        metric histogram KEY=$1;
    }

    location /api/ {
        api /status/http/metric_zones/hist/metrics/;
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/0.25
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": {
        "0.1": 0,
        "0.2": 0,
        "0.5": 1,
        "1": 1,
        "2": 1,
        "inf": 1
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/2
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": {
        "0.1": 0,
        "0.2": 0,
        "0.5": 1,
        "1": 1,
        "2": 2,
        "inf": 2
    }
}
```

Обновление метрики:

```console
$ curl 127.0.0.1/metric/set/1000
```

Ожидаемое значение метрики в API:

```json
{
    "KEY": {
       "0.1": 0,
       "0.2": 0,
       "0.5": 1,
       "1": 1,
       "2": 2,
       "inf": 3
    }
}
```

<a id="built-in-variables-5"></a>

## Встроенные переменные

Для каждой метрики создаются переменные:

- `$metric_<name>`
- `$metric_<name>_key`
- `$metric_<name>_value`

Для составной метрики добавляется переменная:

- `$metric_<name>_value_<metric>`

<a id="v-metric-zone"></a>

### `$metric_<name>`

Аналогично директиве [metric](#id5), можно использовать сеттер переменной
`$metric_<name>` для подсчета метрики. Подсчет метрики будет происходить в фазе
[Rewrite](https://angie.software/angie/docs/configuration/modules/http/http_rewrite/),
что позволяет производить обработку метрики, например, из модуля
[njs](https://angie.software/angie/docs/configuration/modules/http/http_js/).

В качестве значения для установки переменной должна использоваться конструкция
`ключ=значение`. В качестве ключа и значения можно использовать текст,
переменные и их комбинации. Ключ — произвольная строка, по которой группируются значения.
Значение — число, обрабатываемое выбранным режимом.
Если пропущено, считается `0`.
Если параметр невозможно преобразовать в число, считается `1`.

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

```nginx
http {
    metric_zone counter:1m count;

    # В этот момент добавилась переменная $metric_counter

    server {
        listen 80;

        location /metric/ {
            set $metric_counter $http_user_agent;  # Вместо $http_user_agent=0
        }

        location /api/ {
            allow 127.0.0.1;
            deny all;
            api /status/http/metric_zones/counter/;
        }
    }
}
```

Подсчет метрики с помощью модуля
[njs](https://angie.software/angie/docs/configuration/modules/http/http_js/):

```nginx
http {
    js_import metrics.js;

    resolver 127.0.0.53;

    metric_complex_zone requests:1m {
        min_time        min;
        max_time        max;
        total           count;
    }

    location /metric/ {
        js_content metrics.js_request;
        js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
    }

    location /api/ {
        allow 127.0.0.1;
        deny all;
        api /static/http/metric_zones/requests/;
    }
}
```

Файл `metrics.js`:

```js
async function js_request(r) {
    let start_time = Date.now();

    let results = await Promise.all([ngx.fetch('https://google.com/'),
                                     ngx.fetch('https://google.ru/')]);

    // Используем сеттер переменной $metric_requests
    r.variables.metric_requests = `google={Date.now() - start_time}`;
}

export default {js_request};
```

После нескольких запросов на `location /metric/` значения метрики могут быть
следующими:

```json
{
    "discarded": 0,
    "metrics": {
        "google": {
            "min_time": 70,
            "max_time": 432,
            "total": 6
        }
    }
}
```

#### NOTE
После установки переменной можно получить ее значение. Оно будет равно
указанной паре `ключ=значение`.

Также изменится значение, хранящееся в переменной `$metric_<name>_key`
на указанный ключ.

<a id="v-metric-zone-key"></a>

<a id="v-metric-zone-value"></a>

### `$metric_<name>_key` и `$metric_<name>_value`

Переменные `$metric_<name>_key` и `$metric_<name>_value` задают
соответственно ключ и значение. Обновление метрики происходит в момент установки
значения `$metric_<name>_value`, если ключ в `$metric_<name>_key`
уже задан.

#### NOTE
Для составной метрики значения подметрик в переменной `$metric_<name>_value`
объединены при помощи разделяющего символа `", "`.

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

```nginx
http {
    metric_zone gauge:1m gauge;

    # В этот момент добавилась переменная $metric_gauge
    # А еще переменные $metric_gauge_key и $metric_gauge_value

    metric_complex_zone complex:1m {
        hist histogram 1 2 3;
        avg  average exp;
    }

    # В этот момент добавилась переменная $metric_complex
    # А еще переменные $metric_complex_key и $metric_complex_value

    server {
        listen 80;

        location /gauge/ {
            set $metric_gauge_key "foo";
            set $metric_gauge_value 1;

            # Либо set $metric_gauge foo=1;

            return 200 "Updated with '$metric_gauge'\nValue='$metric_gauge_value'\n";
        }

        location /complex/ {
            set $metric_complex_key "foo";
            set $metric_complex_value 3;

            # Либо set $metric_complex foo=3;

            return 200 "Updated with '$metric_complex'\nValue='$metric_complex_value'\n";
        }
    }
}
```

Для такой конфигурации после запроса к `/gauge/` ожидается слудующий ответ:

```console
$ curl 127.0.0.1/gauge/
Updated with 'foo=1'
Value='1'
```

Для `/complex/`:

```console
$ curl 127.0.0.1/complex/
Updated with 'foo=3'
Value='0 0 1, 3'
```

#### NOTE
Если в качестве значения для переменной `$metric_<name>_value` указать
пустую строку, значение будет распознано как `0`. Если строка состоит из
символов, которые невозможно преобразовать в число,
она будет распознана как `1`.

Подсчет метрики произойдет только после того, как заданы значения переменных
`$metric_<name>_key` и `$metric_<name>_value`.

В таком случае значение, сохраненное в `$metric_<name>`, станет равным
новой паре `ключ=значение`, указанной при помощи `$metric_<name>_key`
и `$metric_<name>_value`.

Значение, которое хранится в `$metric_<name>_key`, является последним
указанным через переменные ключом метрики.

Значение, которое хранится в `$metric_<name>_value`, является последним
подсчитанным значением метрики с ключом, установленным в `$metric_<name>_key`.

<a id="v-metric-zone-value-metric"></a>

### `$metric_<name>_value_<metric>`

Для составной метрики значение конкретной подметрики можно получить при помощи
переменной `$metric_<name>_value_<metric>`, указав имя подметрики в качестве
<metric>.

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

```nginx
http {
    metric_complex_zone foo:1m {
        count count;
        min   min;
        avg   average exp;
    }

    # В этот момент добавилась переменная $metric_foo
    # А еще переменные $metric_foo_key и $metric_foo_value
    # А так же $metric_foo_value_count, $metric_foo_value_min и $metric_foo_value_avg

    server {
        listen 80;

        location /foo/ {
            set $metric_foo_key   bar;
            set $metric_foo_value 9;

            # Либо set $metric_foo bar=9;

            return 200 "Updated with '$metric_foo'\nValues='$metric_foo_value'\nCount='$metric_foo_value_count'\n";
        }
    }
}
```

Для такой конфигурации после запроса к `/foo/` ожидается слудующий ответ:

```console
$ curl 127.0.0.1/foo/
Updated with 'bar=9'
Values='1, 9, 9'
Count='1'
```

<a id="additional-examples"></a>

## Дополнительные примеры

<a id="monitoring-http-methods"></a>

### Мониторинг HTTP-методов

```nginx
metric_zone http_methods:1m count;

server {
    listen 80;

    location / {
        metric http_methods $request_method;
    }

    location /metrics/ {
        allow 127.0.0.1;
        deny all;
        api /status/http/metric_zones/http_methods/metrics/;
    }
}
```

Ответ:

```json
{
    "GET": 65,
    "POST": 20,
    "PUT": 10,
    "DELETE": 5
}
```

<a id="upstream-response-time-distribution"></a>

### Распределение времени ответа upstream

```nginx
metric_zone upstream_time:10m expire=on histogram
    0.05 0.1 0.3 0.5 1 2 5 10 inf;

server {
    listen 80;

    location /backend/ {
        proxy_pass http://backend;
        metric upstream_time $upstream_addr=$upstream_response_time on=end;
    }

    location /metrics/ {
        allow 127.0.0.1;
        deny all;
        api /status/http/metric_zones/upstream_time/;
    }
}
```

Ответ:

```json
{
    "discarded": 0,
    "metrics": {
        "backend1:8080": {
            "0.05": 12,
            "0.1": 28,
            "0.3": 56,
            "0.5": 78,
            "1": 92,
            "2": 97,
            "5": 99,
            "10": 100,
            "inf": 100
        }
    }
}
```

<a id="active-connections"></a>

### Активные подключения

```nginx
metric_zone active_connections:2m gauge;

server {
    listen 80;
    server_name site1.com;

    location / {
        # Увеличиваем при подключении
        metric active_connections site1=1 on=request;

        # Уменьшаем при завершении
        metric active_connections site1=-1 on=end;
    }
}

server {
    listen 80;
    server_name site2.com;

    location / {
        metric active_connections site2=1 on=request;
        metric active_connections site2=-1 on=end;
    }
}

server {
    listen 8080;

    location /connections/ {
        allow 127.0.0.1;
        deny all;
        api /status/http/metric_zones/active_connections/metrics;
    }
}
```

Ответ:

```json
{
    "site1": 42,
    "site2": 17
}
```

<a id="prometheus-support"></a>

## Поддержка Prometheus

Angie имеет [встроенный модуль](https://angie.software//angie/docs/configuration/modules/http/http_prometheus.md#http-prometheus) для отображения метрик в
[формате Prometheus](https://prometheus.io/docs/instrumenting/exposition_formats/),
поддерживающий произвольные метрики.

В качестве примера интеграции рассмотрим следующую конфигурацию:

```nginx
http {
    # Создание метрики "upload"
    metric_complex_zone upload:1m discard_key="other" {
        stats    histogram 64 256 1024 4096 16384 +Inf;
        sum      gauge;
        count    count;
        avg_size average exp;
    }

    # Описание шаблона Prometheus для метрики "upload"
    prometheus_template upload_metric {
        'stats{le="$1"}' $p8s_value
                         path=~^/http/metric_zones/upload/metrics/angie/stats/(.+)$
                         type=histogram;

        'stats_sum'      $p8s_value
                         path=/http/metric_zones/upload/metrics/angie/sum;
        'stats_count'    $p8s_value
                         path=/http/metric_zones/upload/metrics/angie/count;

        'avg_size'       $p8s_value
                         path=/http/metric_zones/upload/metrics/angie/avg_size;
    }

    server {
        listen 80;

        # Обновление метрики
        location ~ ^/upload/(.*)$ {
            api /status/http/metric_zones/upload/metrics/angie/;
            metric upload angie=$1 on=request;
        }

        # Таргет для сбора метрик
        location /prometheus/upload_metric/ {
            prometheus upload_metric;
        }
    }
}
```

После нескольких запросов на `/upload/...`:

```console
$ curl 127.0.0.1/upload/16384
$ curl 127.0.0.1/upload/64448
$ curl 127.0.0.1/upload/64
$ curl 127.0.0.1/upload/1028
$ curl 127.0.0.1/upload/1028
```

Значения метрики будут следующими:

```json
{
    "stats": {
        "64": 1,
        "256": 1,
        "1024": 1,
        "4096": 3,
        "16384": 4,
        "+Inf": 5
    },

    "sum": 82952,
    "count": 5,
    "avg_size": 1077.9376
}
```

В [формате Prometheus](https://prometheus.io/docs/instrumenting/exposition_formats/)
метрика доступна на `/prometheus/upload_metric/`:

```text
# Angie Prometheus template "upload_metric"
# TYPE stats histogram
stats{le="64"} 1
stats{le="256"} 1
stats{le="1024"} 1
stats{le="4096"} 3
stats{le="16384"} 4
stats{le="+Inf"} 5
stats_sum 82952
stats_count 5
avg_size 1077.9376
```
