Инструментирование entity
opentelemetry-instrumentation-entity подписывается на события источника данных entity и превращает их в телеметрию OpenTelemetry SDK. Библиотека устроена как инструментирования JDBC и Hibernate в Java: ORM не зависит от OpenTelemetry и отдает события через собственный интерфейс НаблюдательИсточникаДанных, а этот пакет реализует наблюдателя.
Регистрация
#Использовать entity
#Использовать opentelemetry
#Использовать opentelemetry-instrumentation-entity
Сдк = ОтелАвтоконфигурация.Инициализировать();
Наблюдатель = Новый ОтелНаблюдательИсточникаДанных(
Сдк.ПолучитьТрассировщик("entity"),
Сдк.ПолучитьМетр("entity"),
Сдк.ПолучитьЛоггер("entity")
);
Источник = Новый ИсточникДанных("Основной", Тип("КоннекторPostgreSQL"), СтрокаСоединения);
Источник.ДобавитьНаблюдателя(Наблюдатель);
МенеджерСущностей = Новый МенеджерСущностей(Источник);
МенеджерСущностей.ДобавитьКлассВМодель(Тип("Автор"));
МенеджерСущностей.Инициализировать();Наблюдатель регистрируется на источнике данных и видит все, что с ним происходит у каждого менеджера, созданного из источника: операции менеджера, его хранилищ сущностей и активной записи, запросы, соединения и транзакции, включая создание таблиц при Инициализировать.
Второй способ инструментирования — вокруг вызовов методов хранилища сущностей. Наблюдатель видит операции entity, но не видит, из какого метода прикладного хранилища сущностей они пришли; ОтелИнструментированиеХранилищаСущностей оборачивает хранилище и замеряет каждый вызов:
Инструментирование = Новый ОтелИнструментированиеХранилищаСущностей(Сдк.ПолучитьМетр("entity"));
ХранилищеСущностей = Инструментирование.Обернуть(
МенеджерСущностей.ПолучитьХранилищеСущностей(Тип("Автор")),
"ХранилищеАвторы"
);Обертка дает только метрику. Спанов вокруг вызовов она не создает: в трейсе видны операции entity и запросы к СУБД, которые метод выполнил, а сам вызов метода виден в гистограмме entity.repository.invocation.duration с атрибутами entity.repository и code.function.name.
Подробности — в справочнике.
В приложениях на Autumn регистрацию делает связка autumn-data и autumn-opentelemetry: наблюдатель создается завязью при включенном otel.entity.enabled и регистрируется на всех источниках данных.
Трейс
Дерево спанов повторяет вызовы:
Получить Автор INTERNAL entity.type=Автор entity.result.count=2
├─ SELECT Авторы CLIENT db.system.name=postgresql db.operation.name=SELECT
├─ ПолучитьОдно Издательство INTERNAL entity.depth=1
│ └─ SELECT Издательства CLIENT
└─ ПолучитьОдно Издательство INTERNAL entity.depth=1
└─ SELECT Издательства CLIENTОперация из прикладного кода - корень с entity.depth = 0. Разыменование ссылок и чтение подчиненных таблиц - дочерние операции с большей глубиной, запросы к СУБД - листья. Каскад и N+1 видны как вложенность: два ПолучитьОдно Издательство под одним чтением - повод для отбора по ссылке.
Спан операции:
| Атрибут | Значение |
|---|---|
code.function.name | полное имя операции: МенеджерСущностей.Сохранить, МенеджерСущностей.Получить, МенеджерСущностей.ПолучитьОдно, МенеджерСущностей.Удалить, МенеджерСущностей.Инициализировать, МенеджерСущностей.ВыполнитьСКоннектором, МенеджерСущностей.ВычислитьСКоннектором |
entity.type | тип сущности |
entity.table | таблица сущности |
entity.depth | вложенность операции |
entity.result.count | строк прочитано (после выполнения) |
error.type | тип ошибки, если операция ею завершилась |
Спан запроса:
| Атрибут | Значение |
|---|---|
db.system.name | postgresql, sqlite, inmemory, json |
db.namespace | база данных, путь к файлу или каталогу |
db.collection.name | таблица запроса |
db.operation.name | SELECT, INSERT, DELETE, CREATE TABLE, BEGIN, COMMIT, ROLLBACK |
db.query.text | текст запроса с плейсхолдерами; у коннекторов без SQL отсутствует |
db.response.returned_rows | строк вернул SELECT |
server.address, server.port | сервер СУБД; у файловых баз отсутствуют |
error.type | тип ошибки |
При ошибке операции или запроса статус спана становится Error, а исключение записывается записью лога по семантическим соглашениям exceptions-logs: событие entity.operation.exception у операции или db.client.operation.exception у запроса, серьезность WARN, атрибуты exception.*, контекст спана. Без трассировщика запись пишется так же, только без контекста спана наблюдателя. Для этого наблюдателю передается логгер (третий параметр конструктора, после трассировщика и метра). Процессор событий ядра, включенный в автоконфигурации по умолчанию, переносит запись в событие спана, поэтому исключение видно и в трассе. Сама ошибка при этом доходит до вызывающего кода как обычно.
error.type у спанов и метрик - код ошибки библиотеки errors либо код нативной ошибки OneScript, который распознал классификатор ядра (ОтелУтилиты.ТипОшибки). Нераспознанная ошибка получает запасное значение семантических соглашений _OTHER. Тип вычисляется один раз на событие, поэтому спан и метрика одной операции или запроса получают одно значение. Атрибуты exception.* записи исключения заполняет ядро из самого исключения.
Транзакции долгоживущего спана не получают: BEGIN, COMMIT и ROLLBACK приходят обычными спанами запроса внутри операций, которые их вызвали.
Метрики
| Инструмент | Имя | Единица | Атрибуты |
|---|---|---|---|
| Гистограмма | db.client.operation.duration | с | db.system.name, db.namespace, db.collection.name, db.operation.name, server.address, server.port, error.type |
| Гистограмма | entity.operation.duration | с | entity.operation, entity.type, error.type |
| Счетчик | entity.entities | {entity} | entity.operation, entity.type |
| Счетчик | entity.transactions | {transaction} | entity.transaction.result: commit, rollback, failed, abandoned |
| Датчик | db.client.connection.count | {connection} | db.client.connection.pool.name, db.client.connection.state: used, idle |
| Датчик | db.client.connection.max | {connection} | db.client.connection.pool.name |
| Датчик | db.client.connection.pending_requests | {request} | db.client.connection.pool.name |
| Гистограмма | db.client.connection.wait_time | с | db.client.connection.pool.name |
| Гистограмма | db.client.connection.create_time | с | db.client.connection.pool.name |
| Счетчик | db.client.connection.timeouts | {timeout} | db.client.connection.pool.name |
| Гистограмма | entity.repository.invocation.duration | с | entity.repository, code.function.name, entity.repository.state (success или error), error.type |
entity.entities считает сущности, прошедшие через операции: сохранение и удаление - по одной, чтение - по числу прочитанных строк. entity.transactions считает исходы: failed - фиксация или отмена завершились ошибкой, abandoned - поток исполнения завершился, не закрыв транзакцию, и пул откатил ее.
Метрики пула пишутся из снимка, который entity прикладывает к каждому захвату и освобождению соединения, поэтому датчики отражают состояние после последнего события. Имя пула - источник данных без секретов: postgresql://localhost:5432/shop или sqlite:/var/lib/shop.db.
Гистограммы длительности - в секундах с границами бакетов из semantic conventions (0.001 … 10 с), как у db.client.operation.duration.
Настройки
| Ключ | По умолчанию | Действие |
|---|---|---|
ТекстЗапроса | Истина | Писать текст запроса в db.query.text |
Метрики | Истина | Регистрировать инструменты и писать метрики |
Настройки передаются структурой третьим параметром конструктора. Неопределено вместо трассировщика выключает спаны, вместо метра - метрики. Выключенный в SDK трассировщик дает незаписывающие спаны без накладных расходов на экспорт, метрики при этом продолжают писаться.
Накладные расходы
Без наблюдателей entity событий не создает. С наблюдателем на каждую операцию приходится спан, точка гистограммы и, для запросов, еще по спану и точке. Экспорт спанов и метрик выполняют процессоры SDK: с пакетным процессором стоимость наблюдения сводится к созданию объектов, с простым - к синхронному экспорту, который для нагруженных приложений не подходит.
Семантические соглашения
Какие атрибуты семантических соглашений OpenTelemetry заполняет opentelemetry-instrumentation-entity. В таблицах — stable-атрибуты и метрики semconv (версия 1.44.0); атрибуты и метрики в статусе development отмечены отдельно. Группы атрибутов названы так же, как в semconv.
Ключи entity.* — собственные атрибуты библиотеки, они описаны в обзоре.
Спаны запросов
Спан вида CLIENT на каждый запрос к СУБД.
| Атрибут | Значение |
|---|---|
db.system.name | система СУБД коннектора: postgresql, sqlite, inmemory, json |
db.namespace | база данных, путь к файлу или каталогу |
db.collection.name | таблица запроса |
db.operation.name | SELECT, INSERT, DELETE, CREATE TABLE, BEGIN, COMMIT, ROLLBACK |
db.query.text | текст запроса с плейсхолдерами; у коннекторов без SQL не заполняется, выключается настройкой ТекстЗапроса |
server.address, server.port | сервер СУБД; у файловых баз не заполняются |
error.type | тип ошибки, если запрос завершился ошибкой, см. Error |
Из значений db.system.name в semconv описаны postgresql и sqlite, inmemory и json — собственные.
Атрибуты в статусе development
| Атрибут | Значение |
|---|---|
db.response.returned_rows | число строк, которые вернул SELECT |
Спаны операций
Спан вида INTERNAL на каждую операцию менеджера сущностей.
Code
| Атрибут | Значение |
|---|---|
code.function.name | полное имя операции: МенеджерСущностей.Сохранить, МенеджерСущностей.Получить, МенеджерСущностей.ПолучитьОдно, МенеджерСущностей.Удалить, МенеджерСущностей.Инициализировать, МенеджерСущностей.ВыполнитьСКоннектором, МенеджерСущностей.ВычислитьСКоннектором |
error.type | тип ошибки, если операция завершилась ошибкой, см. Error |
Метрики
| Метрика | Атрибуты |
|---|---|
db.client.operation.duration | db.system.name, db.namespace, db.collection.name, db.operation.name, server.address, server.port, error.type |
Длительность — в секундах, с границами бакетов из semconv.
Метрики в статусе development
| Метрика | Атрибуты |
|---|---|
db.client.connection.count | db.client.connection.pool.name, db.client.connection.state: used, idle |
db.client.connection.max | db.client.connection.pool.name |
db.client.connection.pending_requests | db.client.connection.pool.name |
db.client.connection.wait_time | db.client.connection.pool.name |
db.client.connection.create_time | db.client.connection.pool.name |
db.client.connection.timeouts | db.client.connection.pool.name |
Атрибуты db.client.connection.pool.name и db.client.connection.state — тоже в статусе development.
Гистограммы entity.operation.duration и entity.repository.invocation.duration — собственные метрики библиотеки. Из атрибутов semconv в них есть error.type, а в entity.repository.invocation.duration ещё code.function.name — полное имя метода ИмяХранилищаСущностей.ИмяМетода.
Исключения
Исключение операции или запроса записывается записью лога с серьёзностью WARN. Атрибуты exception.* заполняет ядро из переданного исключения, см. семантические соглашения opentelemetry.
| Событие | Статус в semconv |
|---|---|
db.client.operation.exception | development, Database exceptions |
entity.operation.exception | собственное событие библиотеки |
Error
| Атрибут | Значение |
|---|---|
error.type | ОтелУтилиты.ТипОшибки: код ошибки библиотеки errors или код нативной ошибки OneScript, для нераспознанной ошибки — _OTHER. Спан и метрика одного события получают одно значение |
