Skip to content

Метрики ​

OpenTelemetry Metrics API позволяет измерять числовые характеристики системы: счётчики запросов, время ответа, использование ресурсов и другие показатели. Метрики периодически собираются и экспортируются в формате OTLP.

Архитектура ​

ОтелПровайдерМетрик
    └── ОтелМетр
            ├── ОтелСчетчик
            ├── ОтелРеверсивныйСчетчик
            ├── ОтелДатчик
            ├── ОтелГистограмма
            ├── ОтелНаблюдаемыйСчетчик
            ├── ОтелНаблюдаемыйРеверсивныйСчетчик
            └── ОтелНаблюдаемыйДатчик

Инструмент записывает измерения в потоки метрик: по потоку на каждого читателя провайдера и на каждое совпавшее представление (View). Поэтому у каждого читателя свои данные: агрегацию, лимит мощности и временную агрегацию (cumulative/delta) задаёт читатель, и сбор одним читателем не сбрасывает данные другого.

Создание провайдера ​

bsl
#Использовать opentelemetry

Ресурс = ОтелРесурсы.ПоУмолчанию();
Ресурс.Атрибуты().Установить("service.name", "my-service");

Транспорт = Новый ОтелHttpТранспорт("http://localhost:4318");
Экспортер = Новый ОтелЭкспортерМетрик(Транспорт);

// Периодический читатель — экспортирует каждые 60 секунд
Читатель = Новый ОтелПериодическийЧитательМетрик(Экспортер, 60000);
Читатель.Запустить();

Провайдер = Новый ОтелПостроительПровайдераМетрик()
    .УстановитьРесурс(Ресурс)
    .ЗарегистрироватьЧитатель(Читатель)
    .Построить();

Метр = Провайдер.ПолучитьМетр("my-library", "1.0.0");

Синхронные инструменты ​

Counter (Счётчик) ​

Монотонно возрастающий счётчик. Используется для подсчёта событий, запросов, байт и т.п.

bsl
// Создание
Счетчик = Метр.СоздатьСчетчик("http.requests", "Количество запросов", "1");

// Использование
Счетчик.Добавить(1);

// С атрибутами
Атрибуты = Новый ОтелАтрибуты();
Атрибуты.Установить("http.method", "GET");
Атрибуты.Установить("http.status_code", 200);
Счетчик.Добавить(1, Атрибуты);

UpDownCounter (Реверсивный счётчик) ​

Счётчик, который может как увеличиваться, так и уменьшаться. Используется для очередей, пула соединений.

bsl
ОчередьСчетчик = Метр.СоздатьРеверсивныйСчетчик("queue.size", "Размер очереди", "1");

ОчередьСчетчик.Добавить(1);   // задача добавлена
ОчередьСчетчик.Добавить(-1);  // задача обработана

Gauge (Датчик) ​

Фиксирует последнее измеренное значение. Используется для CPU, памяти, температуры.

bsl
Датчик = Метр.СоздатьДатчик("cpu.usage", "Загрузка CPU", "%");
Датчик.Записать(75.5);

// С атрибутами
Атрибуты = Новый ОтелАтрибуты();
Атрибуты.Установить("cpu.core", "0");
Датчик.Записать(62.3, Атрибуты);

Histogram (Гистограмма) ​

Распределяет значения по корзинам. Идеально для времени ответа, размеров запросов.

bsl
Гистограмма = Метр.СоздатьГистограмму("http.duration", "Время ответа", "ms");

// Запись измерения
Гистограмма.Записать(150);

// С атрибутами
Атрибуты = Новый ОтелАтрибуты();
Атрибуты.Установить("http.route", "/api/orders");
Гистограмма.Записать(230, Атрибуты);

Экспоненциальная гистограмма ​

Экспоненциальная гистограмма (Base2 Exponential Bucket Histogram) — агрегация инструмента Histogram с автоматическими логарифмическими корзинами, более точная при широком диапазоне значений. Отдельного инструмента для неё в спецификации нет: гистограмма создаётся через СоздатьГистограмму, а агрегация задаётся View или агрегацией гистограмм по умолчанию (default_histogram_aggregation, OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION).

bsl
Провайдер.ЗарегистрироватьПредставление(
    Новый ОтелСелекторИнструментов("db.query.duration"),
    Новый ОтелПредставление(, , , , ОтелАгрегация.ГистограммаЭкспоненциальная()));
Гистограмма = Метр.СоздатьГистограмму("db.query.duration", "Время запроса к БД", "ms");
Гистограмма.Записать(45);

Метод СоздатьЭкспоненциальнуюГистограмму из версий 1.x удалён: замените его на СоздатьГистограмму с View, как в примере.

Наблюдаемые (асинхронные) инструменты ​

Наблюдаемые инструменты вызывают callback-функцию при каждом сборе метрик. Это удобно для измерений, которые дорого получать по запросу.

Callback вызывается при каждом сборе каждым читателем, наблюдения попадают только к этому читателю. Если после фильтра атрибутов представления несколько наблюдений одного сбора попадают в одну серию, они объединяются: у счётчиков значения складываются, у датчика берётся последнее.

Callback выполняется в фоновом задании с таймаутом (по умолчанию 30 секунд): не завершившийся вовремя callback не задерживает сбор, его наблюдения отбрасываются с предупреждением в логе. Фоновое задание OneScript нельзя прервать, поэтому оно продолжает работу, и до его завершения сбор инструмента не начинается: callback-и инструмента должны завершиться до следующего раунда его сбора. Таймаут задаётся для провайдера или метра:

bsl
Провайдер.УстановитьТаймаутОбратныхВызововМс(5000);
// 0 — callback-и выполняются в потоке сбора без таймаута
Метр.УстановитьТаймаутОбратныхВызововМс(0);

ObservableCounter ​

bsl
// Регистрация callback
Функция ПолучитьОшибки(Наблюдение) Экспорт
    // вызывается при каждом сборе метрик
    Наблюдение.Записать(ПолучитьКоличествоОшибокИзСистемы());
КонецФункции

НаблСчетчик = Метр.СоздатьНаблюдаемыйСчетчик("process.errors",
    Новый Действие(ЭтотОбъект, "ПолучитьОшибки"), "Количество ошибок", "1");

ObservableUpDownCounter ​

bsl
Функция ПолучитьРазмерПула(Наблюдение) Экспорт
    Наблюдение.Записать(ПулСоединений.Размер());
КонецФункции

НаблРеверсивный = Метр.СоздатьНаблюдаемыйРеверсивныйСчетчик("db.pool.size",
    Новый Действие(ЭтотОбъект, "ПолучитьРазмерПула"), "Размер пула", "1");

ObservableGauge ​

bsl
Функция ПолучитьПамять(Наблюдение) Экспорт
    Наблюдение.Записать(ПолучитьИспользуемуюПамятьМб());
КонецФункции

НаблДатчик = Метр.СоздатьНаблюдаемыйДатчик("process.memory",
    Новый Действие(ЭтотОбъект, "ПолучитьПамять"), "Использование памяти", "MB");

Периодический читатель метрик ​

ОтелПериодическийЧитательМетрик запускает фоновый поток, который собирает и экспортирует метрики с заданным интервалом.

bsl
// Интервал задаётся в миллисекундах (60000 = 60 секунд)
Читатель = Новый ОтелПериодическийЧитательМетрик(Экспортер, 60000);
Читатель.Запустить();

// ... работа приложения ...

// При завершении — сброс накопленных метрик
Провайдер.Закрыть();

Настройка через переменную окружения:

bash
export OTEL_METRIC_EXPORT_INTERVAL=30000  # каждые 30 секунд
export OTEL_METRIC_EXPORT_TIMEOUT=10000   # таймаут одного экспорта

Таймаут экспорта и размер пакета можно задать и в коде: при УстановитьМаксРазмерПакетаЭкспорта данные сбора экспортируются пакетами не больше заданного числа точек.

bsl
Читатель.УстановитьТаймаутЭкспортаМс(10000);
Читатель.УстановитьМаксРазмерПакетаЭкспорта(1000);

Агрегацию и лимит мощности по умолчанию читатель задаёт по виду инструмента — они действуют для потоков, у которых представление не задало свои:

bsl
Читатель = Новый ОтелПериодическийЧитательМетрик(Экспортер, 60000);
Читатель.УстановитьАгрегациюПоУмолчанию("UpDownCounter", ОтелАгрегация.Отбросить());
Читатель.УстановитьЛимитМощностиДляВида("Histogram", 500);

Читатель Prometheus ​

ОтелПрометеусЧитательМетрик предоставляет метрики в формате Prometheus для scraping. HTTP-сервера в SDK нет: метрики отдаёт приложение из своего HTTP-обработчика /metrics:

bsl
Читатель = Новый ОтелПрометеусЧитательМетрик();

Провайдер = Новый ОтелПостроительПровайдераМетрик()
    .УстановитьРесурс(Ресурс)
    .ЗарегистрироватьЧитатель(Читатель)
    .Построить();

// В HTTP-обработчике /metrics
ТелоОтвета = Читатель.СобратьВТексте();
ТипКонтента = Читатель.ContentType(); // "text/plain; version=0.0.4; charset=utf-8"

Читатель переводит метрики OTel в семейства Prometheus, а текст в Prometheus text format 0.0.4 формирует библиотека prometheus. Атрибуты ресурса в лейблы метрик по умолчанию не копируются (УстановитьАтрибутыРесурсаВЛейблах). Читатель можно также зарегистрировать в реестре библиотеки prometheus (Collect) и отдавать реестр, например, через prometheus-metrics. Формат выдачи реестра выбирает библиотека; единицу (# UNIT), время создания серий (_created) и exemplars счётчиков и бакетов гистограмм она выводит только в OpenMetrics. Подробности — в описании читателя.

Представления (Views) ​

ОтелПредставление позволяет переименовывать инструменты, фильтровать атрибуты и менять агрегацию.

  • Каждое представление, выбравшее инструмент, даёт отдельную метрику.
  • Настройки представления приоритетнее advisory-параметров инструмента.
  • Представление с агрегацией, несовместимой с видом инструмента, игнорируется целиком, в лог пишется предупреждение. Предупреждение пишется и когда представление даёт двум метрикам одно имя — обе экспортируются.
  • Представление, зарегистрированное после создания инструмента, действует для измерений, записанных после регистрации.

Exemplars и отфильтрованные атрибуты. Атрибуты, которые представление исключило из потока метрики, всё равно могут экспортироваться в exemplars как filteredAttributes — так требует спецификация, чтобы exemplar сохранял исходное измерение. Если фильтр атрибутов убирает чувствительные данные, выключите exemplars: фильтром ОтелФильтрЭкземпляров.ВсегдаВыключен() (или OTEL_METRICS_EXEMPLAR_FILTER=always_off) для всего провайдера либо резервуаром ОтелФабрикаNoopРезервуаров в параметре РезервуарЭкземпляров представления для отдельного потока. С фильтром ВсегдаВыключен резервуары exemplars у серий не создаются вовсе.

bsl
// Оставить только нужные атрибуты, убрать чувствительные данные
Селектор = Новый ОтелСелекторИнструментов("http.requests");

РазрешенныеКлючи = Новый Массив();
РазрешенныеКлючи.Добавить("http.method");
РазрешенныеКлючи.Добавить("http.status_code");
Представление = Новый ОтелПредставление(
    Неопределено,       // НовоеИмя
    Неопределено,       // НовоеОписание
    РазрешенныеКлючи);  // РазрешенныеКлючиАтрибутов

Провайдер = Новый ОтелПостроительПровайдераМетрик()
    .ЗарегистрироватьПредставление(Селектор, Представление)
    .Построить();
bsl
// Атрибуты, исключенные представлением, могут попасть в exemplars как filteredAttributes.
// Чтобы чувствительные данные не уходили и в exemplars, выключите их сбор:
Провайдер = Новый ОтелПостроительПровайдераМетрик()
    .ЗарегистрироватьПредставление(Селектор, Представление)
    .УстановитьФильтрЭкземпляров(ОтелФильтрЭкземпляров.ВсегдаВыключен())
    .Построить();
// или для отдельного потока: резервуар без exemplars в представлении
// (параметр РезервуарЭкземпляров = Новый ОтелФабрикаNoopРезервуаров())
bsl
// Использовать экспоненциальную гистограмму вместо явных корзин
Селектор = Новый ОтелСелекторИнструментов("http.duration");

Представление = Новый ОтелПредставление(
    Неопределено,       // НовоеИмя
    Неопределено,       // НовоеОписание
    Неопределено,       // РазрешенныеКлючиАтрибутов
    Неопределено,       // ГраницыГистограммы
    ОтелАгрегация.ГистограммаЭкспоненциальная());

Провайдер = Новый ОтелПостроительПровайдераМетрик()
    .ЗарегистрироватьПредставление(Селектор, Представление)
    .Построить();

Агрегации ​

ОтелАгрегация определяет, как измерения объединяются в точку данных:

МетодОписание
ОтелАгрегация.ПоУмолчанию()Агрегация по виду инструмента
ОтелАгрегация.Сумма()Сумма всех измерений (Counter, UpDownCounter)
ОтелАгрегация.ПоследнееЗначение()Последнее значение (Gauge)
ОтелАгрегация.ГистограммаСЯвнымиГраницами(Границы, ЗаписыватьМинМакс)Гистограмма с явными корзинами; без границ - границы по умолчанию; ЗаписыватьМинМакс = Ложь - без min и max
ОтелАгрегация.ГистограммаЭкспоненциальная(МаксБакетов, МаксШкала, ЗаписыватьМинМакс)Экспоненциальная гистограмма: до 160 корзин и шкала до 20 по умолчанию
ОтелАгрегация.Отбросить()Отбросить измерения (отключить инструмент)

Временна́я агрегация ​

ОтелВременнаяАгрегация определяет, как агрегируются данные во времени:

ЗначениеОписание
ОтелВременнаяАгрегация.Кумулятивная()Накопительные значения с начала работы (по умолчанию)
ОтелВременнаяАгрегация.Дельта()Разница за интервал экспорта
bash
# Настройка через переменную окружения
export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCEДельтаКумулятивная
cumulative—все виды
deltaCounter, ObservableCounter, Histogram, Gauge, ObservableGaugeUpDownCounter, ObservableUpDownCounter
lowmemoryCounter, Histogramостальные виды

Временную агрегацию каждого потока выбирает читатель по виду инструмента.

Смотрите также ​