Библиотека на OneScript для использования OpenTelemetry в оскриптовых проектах.
Позволяет собирать и отправлять телеметрию (трассировку, логи, метрики) в формате OTLP в любой совместимый коллектор - Grafana LGTM, OpenTelemetry Collector и другие. Поддерживает два транспорта: HTTP JSON и gRPC.
- Автоконфигурация - настройка SDK из переменных окружения или файла конфигурации (через configor)
- Трассировка - спаны, вложенные спаны, атрибуты, события, линки, статусы, семплирование
- Логирование - записи логов с уровнями серьезности и корреляцией с трассировкой
- Метрики - счетчики, реверсивные счетчики, датчики, гистограммы, экспоненциальные гистограммы, наблюдаемые инструменты
- Контекст - thread-safe implicit context propagation для автоматического наследования родительских спанов
- W3C Trace Context - внедрение и извлечение
traceparent/tracestateHTTP-заголовков - W3C Baggage - пропагация baggage через HTTP-заголовки
- Пакетная обработка - batch-процессоры для спанов и логов с фоновым экспортом
- Периодический экспорт метрик - автоматический сбор и отправка метрик по расписанию
- Экспорт по OTLP/HTTP - отправка данных в формате JSON на эндпоинты
/v1/traces,/v1/logs,/v1/metrics - Экспорт по OTLP/gRPC - отправка данных через gRPC с помощью библиотеки oint (OPI_GRPC)
- Интеграция с logos - аппендер для библиотеки logos, перенаправляющий логи в OpenTelemetry
- Централизованный SDK - единый объект
ОтелSdkдля доступа ко всем провайдерам
opm install opentelemetryСамый простой способ настроить OpenTelemetry - через автоконфигурацию. Модуль ОтелАвтоконфигурация читает переменные окружения и/или файл конфигурации, создает все необходимые провайдеры и регистрирует SDK глобально.
#Использовать opentelemetry
// Автоконфигурация из переменных окружения
Сдк = ОтелАвтоконфигурация.Инициализировать();
// Получение трассировщика и метра
Трассировщик = Сдк.ПолучитьТрассировщик("my-library");
Метр = Сдк.ПолучитьМетр("my-library");
// Работа с трассировкой
Спан = Трассировщик.НачатьСпан("операция", ОтелВидСпана.Сервер());
Область = Спан.СделатьТекущим();
// ... работа ...
Область.Закрыть();
Спан.Завершить();
// Или через глобальный доступ в любом месте кода
Трассировщик = ОтелГлобальный.ПолучитьТрассировщик("другая-библиотека");Переменные окружения:
export OTEL_SERVICE_NAME=my-service
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json # или grpcИли через файл конфигурации (configor):
{
"otel": {
"service": { "name": "my-service" },
"exporter": {
"otlp": {
"endpoint": "http://localhost:4318",
"protocol": "http/json"
}
}
}
}#Использовать opentelemetry
Ресурс = Новый ОтелРесурс();
Ресурс.Атрибуты().Установить("service.name", "my-service");
Транспорт = Новый ОтелHttpТранспорт("http://localhost:4318");
Экспортер = Новый ОтелЭкспортерСпанов(Транспорт);
Процессор = Новый ОтелПростойПроцессорСпанов(Экспортер);
Провайдер = Новый ОтелПровайдерТрассировки(Ресурс, Процессор);
Трассировщик = Провайдер.ПолучитьТрассировщик("my-library", "1.0.0");
// Создание спана (SpanKind задается при создании - immutable)
Спан = Трассировщик.НачатьСпан("обработка-запроса", ОтелВидСпана.Сервер());
Область = Спан.СделатьТекущим();
Спан.УстановитьАтрибут("http.method", "GET");
Спан.УстановитьАтрибут("http.url", "/api/data");
// Дочерний спан - НачатьСпан автоматически берет родителя из контекста
ДочернийСпан = Трассировщик.НачатьСпан("запрос-к-бд", ОтелВидСпана.Клиент());
ОбластьДочернего = ДочернийСпан.СделатьТекущим();
// ... выполнение работы ...
ДочернийСпан.УстановитьСтатус(ОтелКодСтатуса.Ок());
ОбластьДочернего.Закрыть();
ДочернийСпан.Завершить();
Спан.УстановитьСтатус(ОтелКодСтатуса.Ок());
Область.Закрыть();
Спан.Завершить();
Провайдер.Закрыть();#Использовать opentelemetry
Ресурс = Новый ОтелРесурс();
Ресурс.Атрибуты().Установить("service.name", "my-service");
Транспорт = Новый ОтелHttpТранспорт("http://localhost:4318");
Экспортер = Новый ОтелЭкспортерЛогов(Транспорт);
Процессор = Новый ОтелПростойПроцессорЛогов(Экспортер);
Провайдер = Новый ОтелПровайдерЛогирования(Ресурс, Процессор);
Логгер = Провайдер.ПолучитьЛоггер("my-library", "1.0.0");
Запись = Логгер.СоздатьЗаписьЛога();
Запись.УстановитьТело("Пользователь авторизован")
.УстановитьСерьезность(ОтелСтепеньСерьезности.Info())
.УстановитьАтрибут("user.id", "12345");
Логгер.Записать(Запись);#Использовать opentelemetry
Ресурс = Новый ОтелРесурс();
Ресурс.Атрибуты().Установить("service.name", "my-service");
Транспорт = Новый ОтелHttpТранспорт("http://localhost:4318");
Экспортер = Новый ОтелЭкспортерМетрик(Транспорт);
Читатель = Новый ОтелПериодическийЧитательМетрик(Экспортер, 60000);
Читатель.Запустить();
Провайдер = Новый ОтелПровайдерМетрик(Ресурс, Читатель);
Метр = Провайдер.ПолучитьМетр("my-library", "1.0.0");
// Счетчик
Счетчик = Метр.СоздатьСчетчик("http.requests", "Количество запросов", "1");
Счетчик.Добавить(1);
// Гистограмма
Гистограмма = Метр.СоздатьГистограмму("http.duration", "Время ответа", "ms");
Гистограмма.Записать(150);
// Реверсивный счетчик (UpDownCounter)
ОчередьСчетчик = Метр.СоздатьРеверсивныйСчетчик("queue.size", "Размер очереди", "1");
ОчередьСчетчик.Добавить(1); // добавлен элемент
ОчередьСчетчик.Добавить(-1); // элемент обработан
// Датчик (Gauge)
Датчик = Метр.СоздатьДатчик("cpu.usage", "Загрузка CPU", "%");
Датчик.Записать(75.5);#Использовать opentelemetry
// Внедрение контекста в исходящий HTTP-запрос
Спан = Трассировщик.НачатьСпан("http-запрос", ОтелВидСпана.Клиент());
Заголовки = Новый Соответствие();
ОтелW3CПропагатор.Внедрить(Спан.КонтекстСпана(), Заголовки);
// Заголовки теперь содержат "traceparent" и опционально "tracestate"
// Извлечение контекста из входящего запроса
КонтекстСпана = ОтелW3CПропагатор.Извлечь(ВходящиеЗаголовки);
Если КонтекстСпана <> Неопределено Тогда
Спан = Трассировщик.НачатьДочернийСпан("обработка", КонтекстСпана, ОтелВидСпана.Сервер());
КонецЕсли;Все экспортеры работают с обоими транспортами. Достаточно заменить ОтелHttpТранспорт на ОтелGrpcТранспорт:
#Использовать opentelemetry
// gRPC-транспорт - порт 4317 (стандартный OTLP gRPC)
Транспорт = Новый ОтелGrpcТранспорт("http://localhost:4317");
Экспортер = Новый ОтелЭкспортерСпанов(Транспорт);
Процессор = Новый ОтелПростойПроцессорСпанов(Экспортер);
Ресурс = Новый ОтелРесурс();
Ресурс.Атрибуты().Установить("service.name", "my-service");
Провайдер = Новый ОтелПровайдерТрассировки(Ресурс, Процессор);
Трассировщик = Провайдер.ПолучитьТрассировщик("my-library", "1.0.0");
Спан = Трассировщик.НачатьСпан("операция", ОтелВидСпана.Сервер());
Область = Спан.СделатьТекущим();
// ... работа ...
Область.Закрыть();
Спан.Завершить();
Провайдер.Закрыть();#Использовать opentelemetry
#Использовать logos
Ресурс = Новый ОтелРесурс();
Ресурс.Атрибуты().Установить("service.name", "my-service");
Транспорт = Новый ОтелHttpТранспорт("http://localhost:4318");
Экспортер = Новый ОтелЭкспортерЛогов(Транспорт);
Процессор = Новый ОтелПростойПроцессорЛогов(Экспортер);
Провайдер = Новый ОтелПровайдерЛогирования(Ресурс, Процессор);
ОтелЛоггер = Провайдер.ПолучитьЛоггер("my-library", "1.0.0");
Аппендер = Новый ОтелАппендерLogos(ОтелЛоггер);
Лог = Логирование.ПолучитьЛог("oscript.app.myapp");
Лог.ДобавитьСпособВывода(Аппендер);
// Теперь все сообщения logos автоматически отправляются в OpenTelemetry
Лог.Информация("Приложение запущено");
Лог.Ошибка("Произошла ошибка: файл не найден");Модуль ОтелАвтоконфигурация следует спецификации переменных окружения OpenTelemetry и читает стандартные параметры OpenTelemetry.
Параметры могут задаваться через переменные окружения (OTEL_*) или через менеджер параметров configor (файл конфигурации, программное создание). Переменные окружения преобразуются в ключи configor с заменой _ на . и приведением к нижнему регистру.
| Переменная окружения | Ключ configor | По умолчанию | Описание |
|---|---|---|---|
OTEL_ENABLED |
otel.enabled |
true |
Включить/выключить SDK. При false создается NoOp SDK |
OTEL_SERVICE_NAME |
otel.service.name |
- | Имя сервиса (service.name в ресурсе) |
OTEL_EXPORTER_OTLP_ENDPOINT |
otel.exporter.otlp.endpoint |
http://localhost:4318 (HTTP) / http://localhost:4317 (gRPC) |
Адрес OTLP-коллектора |
OTEL_EXPORTER_OTLP_PROTOCOL |
otel.exporter.otlp.protocol |
http/json |
Протокол: http/json или grpc |
| Переменная окружения | Ключ configor | По умолчанию | Описание |
|---|---|---|---|
OTEL_TRACES_EXPORTER |
otel.traces.exporter |
otlp |
Экспортер трассировки: otlp или none |
OTEL_LOGS_EXPORTER |
otel.logs.exporter |
otlp |
Экспортер логов: otlp или none |
OTEL_METRICS_EXPORTER |
otel.metrics.exporter |
otlp |
Экспортер метрик: otlp или none |
| Переменная окружения | Ключ configor | По умолчанию | Описание |
|---|---|---|---|
OTEL_TRACES_SAMPLER |
otel.traces.sampler |
always_on |
Стратегия семплирования |
OTEL_TRACES_SAMPLER_ARG |
otel.traces.sampler.arg |
1.0 |
Аргумент семплера (доля для traceidratio) |
Поддерживаемые семплеры: always_on, always_off, traceidratio, parentbased_always_on, parentbased_always_off, parentbased_traceidratio.
| Переменная окружения | Ключ configor | По умолчанию | Описание |
|---|---|---|---|
OTEL_BSP_MAX_QUEUE_SIZE |
otel.bsp.max.queue.size |
2048 |
Максимальный размер очереди |
OTEL_BSP_SCHEDULE_DELAY |
otel.bsp.schedule.delay |
5000 |
Интервал экспорта (мс) |
OTEL_BSP_MAX_EXPORT_BATCH_SIZE |
otel.bsp.max.export.batch.size |
512 |
Максимальный размер пакета |
| Переменная окружения | Ключ configor | По умолчанию | Описание |
|---|---|---|---|
OTEL_METRIC_EXPORT_INTERVAL |
otel.metric.export.interval |
60000 |
Интервал экспорта метрик (мс) |
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE |
otel.exporter.otlp.metrics.temporality.preference |
cumulative |
Временная агрегация: cumulative, delta, lowmemory |
| Переменная окружения | Ключ configor | По умолчанию | Описание |
|---|---|---|---|
OTEL_PROPAGATORS |
otel.propagators |
tracecontext,baggage |
Пропагаторы через запятую: tracecontext, baggage, none |
SDK следует архитектуре OpenTelemetry SDK Specification.
| Компонент | Класс/Модуль | Описание |
|---|---|---|
| SDK | ОтелSdk |
Централизованный объект, хранит все провайдеры и пропагаторы |
| Построитель SDK | ОтелПостроительSdk |
Fluent API для сборки SDK |
| Ресурс | ОтелРесурс |
Описание сущности, производящей телеметрию |
| Построитель ресурса | ОтелПостроительРесурса |
Fluent API для сборки ресурса |
| Атрибуты | ОтелАтрибуты |
Пары ключ-значение для описания телеметрии |
| Baggage | ОтелBaggage |
Контекстная информация, пропагируемая через границы сервисов |
| Область | ОтелОбласть |
Context Scope - управление активным спаном в контексте |
| Область инструментирования | ОтелОбластьИнструментирования |
InstrumentationScope - имя, версия и атрибуты инструментирующей библиотеки |
| Контекст | ОтелКонтекст |
Thread-safe хранение текущего спана (per-thread stack) |
| Глобальный | ОтелГлобальный |
Глобальный доступ к зарегистрированному SDK |
| Утилиты | ОтелУтилиты |
Генерация ID, временные метки, транслитерация |
| Автоконфигурация | ОтелАвтоконфигурация |
Настройка SDK из переменных окружения / configor |
| Компонент | Класс/Модуль | Описание |
|---|---|---|
| Провайдер | ОтелПровайдерТрассировки |
Точка входа, создает трассировщики |
| Трассировщик | ОтелТрассировщик |
Создает спаны |
| Спан | ОтелСпан |
Единица работы с атрибутами и событиями |
| NoOp-спан | ОтелНоопСпан |
Спан-заглушка (когда трассировка выключена или не отобрана семплером) |
| Контекст спана | ОтелКонтекстСпана |
TraceId (32 hex), SpanId (16 hex), TraceFlags, TraceState |
| Событие спана | ОтелСобытиеСпана |
Событие с временной меткой и атрибутами |
| Лимиты спана | ОтелЛимитыСпана |
Ограничения на количество атрибутов, событий, линков |
| Простой процессор | ОтелПростойПроцессорСпанов |
Синхронная обработка (для разработки) |
| Пакетный процессор | ОтелПакетныйПроцессорСпанов |
Асинхронная пакетная обработка (для продакшена) |
| Композитный процессор | ОтелКомпозитныйПроцессорСпанов |
Объединяет несколько процессоров |
| Виды спанов | ОтелВидСпана |
Внутренний, Сервер, Клиент, Производитель, Потребитель |
| Коды статуса | ОтелКодСтатуса |
НеУстановлен, Ок, Ошибка |
| Сэмплер | ОтелСэмплер |
Стратегии семплирования: ВсегдаВключен, ВсегдаВыключен, ПоДолеТрассировок, НаОсновеРодителя |
| Компонент | Класс/Модуль | Описание |
|---|---|---|
| Провайдер | ОтелПровайдерЛогирования |
Точка входа, создает логгеры |
| Логгер | ОтелЛоггер |
Создает и отправляет записи логов |
| Запись лога | ОтелЗаписьЛога |
Запись лога с серьезностью и атрибутами |
| Лимиты записей | ОтелЛимитыЗаписейЛога |
Ограничения на атрибуты и длину значений |
| Простой процессор | ОтелПростойПроцессорЛогов |
Синхронная обработка (для разработки) |
| Пакетный процессор | ОтелПакетныйПроцессорЛогов |
Асинхронная пакетная обработка (для продакшена) |
| Композитный процессор | ОтелКомпозитныйПроцессорЛогов |
Объединяет несколько процессоров |
| Степень серьезности | ОтелСтепеньСерьезности |
Trace, Debug, Info, Warn, Error, Fatal (1-24) |
| Компонент | Класс/Модуль | Описание |
|---|---|---|
| Провайдер | ОтелПровайдерМетрик |
Точка входа, создает метры |
| Метр | ОтелМетр |
Создает инструменты измерения |
| Счетчик | ОтелСчетчик |
Монотонно возрастающий счетчик (Counter) |
| Реверсивный счетчик | ОтелРеверсивныйСчетчик |
Счетчик с отрицательными значениями (UpDownCounter) |
| Датчик | ОтелДатчик |
Последнее значение (Gauge) |
| Гистограмма | ОтелГистограмма |
Explicit bucket histogram |
| Экспоненциальная гистограмма | ОтелЭкспоненциальнаяГистограмма |
Exponential bucket histogram (Base2) |
| Наблюдаемый счетчик | ОтелНаблюдаемыйСчетчик |
Асинхронный счетчик с callback |
| Наблюдаемый реверсивный счетчик | ОтелНаблюдаемыйРеверсивныйСчетчик |
Асинхронный реверсивный счетчик |
| Наблюдаемый датчик | ОтелНаблюдаемыйДатчик |
Асинхронный gauge с callback |
| Периодический читатель | ОтелПериодическийЧитательМетрик |
Сбор и экспорт метрик по таймеру |
| Представление | ОтелПредставление |
View для переименования/фильтрации метрик |
| Селектор инструментов | ОтелСелекторИнструментов |
Выбор инструментов для применения представлений |
| Агрегация | ОтелАгрегация |
Стратегии агрегации: Sum, LastValue, ExplicitBucketHistogram и др. |
| Временная агрегация | ОтелВременнаяАгрегация |
Cumulative или Delta |
| Компонент | Класс | Описание |
|---|---|---|
| HTTP-транспорт | ОтелHttpТранспорт |
OTLP HTTP JSON (порт 4318) |
| gRPC-транспорт | ОтелGrpcТранспорт |
OTLP gRPC через oint/OPI_GRPC (порт 4317) |
| InMemory-транспорт | ОтелВПамятьТранспорт |
Сохраняет данные в память (для тестов) |
| Конвертер | ОтелКонвертерOtlpВProto |
Конвертация camelCase -> snake_case для protobuf (gRPC) |
| Экспортер спанов | ОтелЭкспортерСпанов |
Экспорт на /v1/traces |
| Экспортер логов | ОтелЭкспортерЛогов |
Экспорт на /v1/logs |
| Экспортер метрик | ОтелЭкспортерМетрик |
Экспорт на /v1/metrics |
| Компонент | Класс/Модуль | Описание |
|---|---|---|
| W3C TraceContext | ОтелW3CПропагатор |
Внедрение/извлечение traceparent и tracestate |
| W3C Baggage | ОтелW3CBaggageПропагатор |
Внедрение/извлечение заголовка baggage |
| Композитный пропагатор | ОтелКомпозитныйПропагатор |
Объединяет несколько пропагаторов |
| Компонент | Класс | Описание |
|---|---|---|
| Аппендер logos | ОтелАппендерLogos |
Аппендер для библиотеки logos, отправляет логи через OTel |
- OneScript 2.0.0+
- logos 1.7.1+
- 1connector 2.2.1+
- collectionos 0.8.2+
- oint 1.33.0+ (для gRPC-транспорта)
- configor 0.11.1+ (для автоконфигурации)
- async 0.3.0+ (для пакетных процессоров)
Все зависимости устанавливаются автоматически через opm install.
opm install -l --devoneunit execute --recursiveДля получения отчета в формате JUnit XML (например, для CI):
oneunit execute --recursive --junit out/junit.xmltests/unit/- модульные тесты (655 тестов), организованы по подсистемамtests/e2e/- интеграционные тесты с реальным OTLP-коллектором (через testcontainers)
MIT