Метрики
OpenTelemetry Metrics API позволяет измерять числовые характеристики системы: счётчики запросов, время ответа, использование ресурсов и другие показатели. Метрики периодически собираются и экспортируются в формате OTLP.
Архитектура
ОтелПровайдерМетрик
└── ОтелМетр
├── ОтелСчетчик
├── ОтелРеверсивныйСчетчик
├── ОтелДатчик
├── ОтелГистограмма
├── ОтелНаблюдаемыйСчетчик
├── ОтелНаблюдаемыйРеверсивныйСчетчик
└── ОтелНаблюдаемыйДатчикИнструмент записывает измерения в потоки метрик: по потоку на каждого читателя провайдера и на каждое совпавшее представление (View). Поэтому у каждого читателя свои данные: агрегацию, лимит мощности и временную агрегацию (cumulative/delta) задаёт читатель, и сбор одним читателем не сбрасывает данные другого.
Создание провайдера
#Использовать opentelemetry
Ресурс = ОтелРесурсы.ПоУмолчанию();
Ресурс.Атрибуты().Установить("service.name", "my-service");
Транспорт = Новый ОтелHttpТранспорт("http://localhost:4318");
Экспортер = Новый ОтелЭкспортерМетрик(Транспорт);
// Периодический читатель — экспортирует каждые 60 секунд
Читатель = Новый ОтелПериодическийЧитательМетрик(Экспортер, 60000);
Читатель.Запустить();
Провайдер = Новый ОтелПостроительПровайдераМетрик()
.УстановитьРесурс(Ресурс)
.ЗарегистрироватьЧитатель(Читатель)
.Построить();
Метр = Провайдер.ПолучитьМетр("my-library", "1.0.0");Синхронные инструменты
Counter (Счётчик)
Монотонно возрастающий счётчик. Используется для подсчёта событий, запросов, байт и т.п.
// Создание
Счетчик = Метр.СоздатьСчетчик("http.requests", "Количество запросов", "1");
// Использование
Счетчик.Добавить(1);
// С атрибутами
Атрибуты = Новый ОтелАтрибуты();
Атрибуты.Установить("http.method", "GET");
Атрибуты.Установить("http.status_code", 200);
Счетчик.Добавить(1, Атрибуты);UpDownCounter (Реверсивный счётчик)
Счётчик, который может как увеличиваться, так и уменьшаться. Используется для очередей, пула соединений.
ОчередьСчетчик = Метр.СоздатьРеверсивныйСчетчик("queue.size", "Размер очереди", "1");
ОчередьСчетчик.Добавить(1); // задача добавлена
ОчередьСчетчик.Добавить(-1); // задача обработанаGauge (Датчик)
Фиксирует последнее измеренное значение. Используется для CPU, памяти, температуры.
Датчик = Метр.СоздатьДатчик("cpu.usage", "Загрузка CPU", "%");
Датчик.Записать(75.5);
// С атрибутами
Атрибуты = Новый ОтелАтрибуты();
Атрибуты.Установить("cpu.core", "0");
Датчик.Записать(62.3, Атрибуты);Histogram (Гистограмма)
Распределяет значения по корзинам. Идеально для времени ответа, размеров запросов.
Гистограмма = Метр.СоздатьГистограмму("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).
Провайдер.ЗарегистрироватьПредставление(
Новый ОтелСелекторИнструментов("db.query.duration"),
Новый ОтелПредставление(, , , , ОтелАгрегация.ГистограммаЭкспоненциальная()));
Гистограмма = Метр.СоздатьГистограмму("db.query.duration", "Время запроса к БД", "ms");
Гистограмма.Записать(45);Метод СоздатьЭкспоненциальнуюГистограмму из версий 1.x удалён: замените его на СоздатьГистограмму с View, как в примере.
Наблюдаемые (асинхронные) инструменты
Наблюдаемые инструменты вызывают callback-функцию при каждом сборе метрик. Это удобно для измерений, которые дорого получать по запросу.
Callback вызывается при каждом сборе каждым читателем, наблюдения попадают только к этому читателю. Если после фильтра атрибутов представления несколько наблюдений одного сбора попадают в одну серию, они объединяются: у счётчиков значения складываются, у датчика берётся последнее.
Callback выполняется в фоновом задании с таймаутом (по умолчанию 30 секунд): не завершившийся вовремя callback не задерживает сбор, его наблюдения отбрасываются с предупреждением в логе. Фоновое задание OneScript нельзя прервать, поэтому оно продолжает работу, и до его завершения сбор инструмента не начинается: callback-и инструмента должны завершиться до следующего раунда его сбора. Таймаут задаётся для провайдера или метра:
Провайдер.УстановитьТаймаутОбратныхВызововМс(5000);
// 0 — callback-и выполняются в потоке сбора без таймаута
Метр.УстановитьТаймаутОбратныхВызововМс(0);ObservableCounter
// Регистрация callback
Функция ПолучитьОшибки(Наблюдение) Экспорт
// вызывается при каждом сборе метрик
Наблюдение.Записать(ПолучитьКоличествоОшибокИзСистемы());
КонецФункции
НаблСчетчик = Метр.СоздатьНаблюдаемыйСчетчик("process.errors",
Новый Действие(ЭтотОбъект, "ПолучитьОшибки"), "Количество ошибок", "1");ObservableUpDownCounter
Функция ПолучитьРазмерПула(Наблюдение) Экспорт
Наблюдение.Записать(ПулСоединений.Размер());
КонецФункции
НаблРеверсивный = Метр.СоздатьНаблюдаемыйРеверсивныйСчетчик("db.pool.size",
Новый Действие(ЭтотОбъект, "ПолучитьРазмерПула"), "Размер пула", "1");ObservableGauge
Функция ПолучитьПамять(Наблюдение) Экспорт
Наблюдение.Записать(ПолучитьИспользуемуюПамятьМб());
КонецФункции
НаблДатчик = Метр.СоздатьНаблюдаемыйДатчик("process.memory",
Новый Действие(ЭтотОбъект, "ПолучитьПамять"), "Использование памяти", "MB");Периодический читатель метрик
ОтелПериодическийЧитательМетрик запускает фоновый поток, который собирает и экспортирует метрики с заданным интервалом.
// Интервал задаётся в миллисекундах (60000 = 60 секунд)
Читатель = Новый ОтелПериодическийЧитательМетрик(Экспортер, 60000);
Читатель.Запустить();
// ... работа приложения ...
// При завершении — сброс накопленных метрик
Провайдер.Закрыть();Настройка через переменную окружения:
export OTEL_METRIC_EXPORT_INTERVAL=30000 # каждые 30 секунд
export OTEL_METRIC_EXPORT_TIMEOUT=10000 # таймаут одного экспортаТаймаут экспорта и размер пакета можно задать и в коде: при УстановитьМаксРазмерПакетаЭкспорта данные сбора экспортируются пакетами не больше заданного числа точек.
Читатель.УстановитьТаймаутЭкспортаМс(10000);
Читатель.УстановитьМаксРазмерПакетаЭкспорта(1000);Агрегацию и лимит мощности по умолчанию читатель задаёт по виду инструмента — они действуют для потоков, у которых представление не задало свои:
Читатель = Новый ОтелПериодическийЧитательМетрик(Экспортер, 60000);
Читатель.УстановитьАгрегациюПоУмолчанию("UpDownCounter", ОтелАгрегация.Отбросить());
Читатель.УстановитьЛимитМощностиДляВида("Histogram", 500);Читатель Prometheus
ОтелПрометеусЧитательМетрик предоставляет метрики в формате Prometheus для scraping. HTTP-сервера в SDK нет: метрики отдаёт приложение из своего HTTP-обработчика /metrics:
Читатель = Новый ОтелПрометеусЧитательМетрик();
Провайдер = Новый ОтелПостроительПровайдераМетрик()
.УстановитьРесурс(Ресурс)
.ЗарегистрироватьЧитатель(Читатель)
.Построить();
// В 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 у серий не создаются вовсе.
// Оставить только нужные атрибуты, убрать чувствительные данные
Селектор = Новый ОтелСелекторИнструментов("http.requests");
РазрешенныеКлючи = Новый Массив();
РазрешенныеКлючи.Добавить("http.method");
РазрешенныеКлючи.Добавить("http.status_code");
Представление = Новый ОтелПредставление(
Неопределено, // НовоеИмя
Неопределено, // НовоеОписание
РазрешенныеКлючи); // РазрешенныеКлючиАтрибутов
Провайдер = Новый ОтелПостроительПровайдераМетрик()
.ЗарегистрироватьПредставление(Селектор, Представление)
.Построить();// Атрибуты, исключенные представлением, могут попасть в exemplars как filteredAttributes.
// Чтобы чувствительные данные не уходили и в exemplars, выключите их сбор:
Провайдер = Новый ОтелПостроительПровайдераМетрик()
.ЗарегистрироватьПредставление(Селектор, Представление)
.УстановитьФильтрЭкземпляров(ОтелФильтрЭкземпляров.ВсегдаВыключен())
.Построить();
// или для отдельного потока: резервуар без exemplars в представлении
// (параметр РезервуарЭкземпляров = Новый ОтелФабрикаNoopРезервуаров())// Использовать экспоненциальную гистограмму вместо явных корзин
Селектор = Новый ОтелСелекторИнструментов("http.duration");
Представление = Новый ОтелПредставление(
Неопределено, // НовоеИмя
Неопределено, // НовоеОписание
Неопределено, // РазрешенныеКлючиАтрибутов
Неопределено, // ГраницыГистограммы
ОтелАгрегация.ГистограммаЭкспоненциальная());
Провайдер = Новый ОтелПостроительПровайдераМетрик()
.ЗарегистрироватьПредставление(Селектор, Представление)
.Построить();Агрегации
ОтелАгрегация определяет, как измерения объединяются в точку данных:
| Метод | Описание |
|---|---|
ОтелАгрегация.ПоУмолчанию() | Агрегация по виду инструмента |
ОтелАгрегация.Сумма() | Сумма всех измерений (Counter, UpDownCounter) |
ОтелАгрегация.ПоследнееЗначение() | Последнее значение (Gauge) |
ОтелАгрегация.ГистограммаСЯвнымиГраницами(Границы, ЗаписыватьМинМакс) | Гистограмма с явными корзинами; без границ - границы по умолчанию; ЗаписыватьМинМакс = Ложь - без min и max |
ОтелАгрегация.ГистограммаЭкспоненциальная(МаксБакетов, МаксШкала, ЗаписыватьМинМакс) | Экспоненциальная гистограмма: до 160 корзин и шкала до 20 по умолчанию |
ОтелАгрегация.Отбросить() | Отбросить измерения (отключить инструмент) |
Временна́я агрегация
ОтелВременнаяАгрегация определяет, как агрегируются данные во времени:
| Значение | Описание |
|---|---|
ОтелВременнаяАгрегация.Кумулятивная() | Накопительные значения с начала работы (по умолчанию) |
ОтелВременнаяАгрегация.Дельта() | Разница за интервал экспорта |
# Настройка через переменную окружения
export OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=deltaOTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE | Дельта | Кумулятивная |
|---|---|---|
cumulative | — | все виды |
delta | Counter, ObservableCounter, Histogram, Gauge, ObservableGauge | UpDownCounter, ObservableUpDownCounter |
lowmemory | Counter, Histogram | остальные виды |
Временную агрегацию каждого потока выбирает читатель по виду инструмента.
Смотрите также
- Автоконфигурация — настройка через
OTEL_METRICS_EXPORTER,OTEL_METRIC_EXPORT_INTERVAL - Экспорт — эндпоинт
/v1/metrics - API: ОтелМетр
- API: ОтелПровайдерМетрик
