Инструментирование entity
opentelemetry-instrumentation-entity подписывается на события источника данных entity и превращает их в телеметрию OpenTelemetry SDK. Библиотека устроена как инструментирования JDBC и Hibernate в Java: ORM не зависит от OpenTelemetry и отдает события через собственный интерфейс НаблюдательИсточникаДанных, а этот пакет реализует наблюдателя.
Регистрация
#Использовать entity
#Использовать opentelemetry
#Использовать opentelemetry-instrumentation-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.namespace | МенеджерСущностей |
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 | тип ошибки |
Ошибка операции или запроса записывается в спан событием exception, статус спана становится Error. Сама ошибка при этом доходит до вызывающего кода как обычно.
Транзакции долгоживущего спана не получают: 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: с пакетным процессором стоимость наблюдения сводится к созданию объектов, с простым - к синхронному экспорту, который для нагруженных приложений не подходит.
