Skip to content

ИнтерфейсСэмплер ​

Интерфейс сэмплера (Sampler): контракт встроенных и своих сэмплеров.

Описание ​

Сэмплер решает при создании каждого спана, записывается ли спан и экспортируется ли он. Встроенные сэмплеры — AlwaysOn, AlwaysOff, TraceIdRatioBased, ParentBased и AlwaysRecord — создаёт модуль ОтелСэмплер. Свой сэмплер пишут, например, чтобы не записывать служебные запросы по имени спана или сэмплировать операции с разной долей. Аналог Java SDK: Sampler.

Интерфейс — класс ИнтерфейсСэмплер с аннотацией &Интерфейс библиотеки extends. Встроенные сэмплеры объявляют реализацию аннотацией &Реализует("ИнтерфейсСэмплер") у конструктора ПриСозданииОбъекта.

Регистрация сэмплера ​

Сэмплер задаётся провайдеру трассировки при создании: методом УстановитьСэмплерпостроителя провайдера или параметром конструктора провайдера. Без сэмплера провайдер использует сэмплер по умолчанию ParentBased(root=AlwaysOn). Свой сэмплер можно сделать корневым сэмплером или делегатом ОтелСэмплер.НаОсновеРодителя, обернуть в ОтелСэмплер.ВсегдаЗаписывать и наоборот: сэмплеры комбинируются, как объекты одного интерфейса.

Реализацию интерфейса SDK не проверяет: трассировщик вызывает методы по имени. Проверить класс заранее, например в тестах, можно валидатором библиотеки extends: метод ИнтерфейсыРеализованыКорректно(Сэмплер) объекта ВалидаторРеализации выбрасывает исключение, если у класса с аннотацией &Реализует("ИнтерфейсСэмплер") нет метода интерфейса или у метода неподходящее число параметров.

Потоки ​

ДолженСэмплировать и Описание вызываются из разных потоков (фоновых заданий) одновременно: спаны создаются параллельно. Сэмплер должен быть потокобезопасным (спецификация Trace SDK, раздел Concurrency requirements): встроенные сэмплеры после создания не изменяются, общие изменяемые данные своего сэмплера защищайте блокировкой.

Методы ​

ДолженСэмплировать ​

Принимает решение о сэмплировании создаваемого спана (ShouldSample). Трассировщик вызывает метод при создании каждого спана в SDK-режиме, до вызова процессоров. Порядок по спецификации Trace SDK (раздел SDK Span creation): TraceId родителя или новый TraceId, решение сэмплера, новый SpanId, спан по решению.

ПараметрТипОписание
КонтекстФиксированноеСоответствиеКонтекст (Context) с родительским спаном. Спана нет или его SpanContext невалиден — создаётся корневой спан. Контекст спана родителя возвращает ОтелСэмплер.КонтекстСпанаРодителя; Baggage — ОтелКонтекст.BaggageИзКонтекста(Контекст)
ИдТрассировкиСтрокаTraceId создаваемого спана (32 hex-символа). При валидном родителе совпадает с TraceId родителя
ИмяСпанаСтрокаИмя создаваемого спана
ВидСпанаЧислоВид создаваемого спана, значение ОтелВидСпана; не заданный при создании вид — Внутренний
АтрибутыСоответствие, ФиксированноеСоответствиеНачальные атрибуты создаваемого спана; без атрибутов — пустое соответствие
ЛинкиМассив, ФиксированныйМассив из ОтелЛинкЛинки создаваемого спана; без линков — пустой массив

Атрибуты и линки сэмплер только читает: это коллекции создаваемого спана.

Возвращает: ОтелРезультатСэмплирования — решение, атрибуты, которые получит спан, и TraceState спана:

  • решение ОтелСэмплер.РешениеОтбросить() (DROP) — спан не записывается: возвращается незаписывающий спан с новыми TraceId и SpanId, процессоры его не получают;
  • ОтелСэмплер.РешениеЗаписать() (RECORD_ONLY) — спан записывается и передаётся процессорам, флаг sampled не устанавливается, экспортер спан не получает;
  • ОтелСэмплер.РешениеЗаписатьИЭкспортировать() (RECORD_AND_SAMPLE) — спан записывается, флаг sampled устанавливается, спан экспортируется.

Атрибуты результата устанавливаются у записывающего спана после начальных (одноименные заменяют их) и видны процессорам уже в ПриНачале. TraceState результата становится TraceState спана: пустой очищает состояние трассировки, а результат без TraceState сохраняет TraceState родителя. Результат без атрибутов и TraceState возвращает ОтелСэмплер.Результат(Решение) — без создания объекта на каждый спан.


Описание ​

Возвращает имя сэмплера или краткое описание с настройками (GetDescription), например TraceIdRatioBased{0.000100}. Описание предназначено для логов и отладки. Оно может меняться со временем, если сэмплер меняет параметры: не кэшируйте его.

Возвращает: Строка

Пример ​

Сэмплер, который не записывает проверки работоспособности, а остальные спаны передаёт другому сэмплеру, — класс приложения в файле СэмплерБезПроверок.os:

bsl
Перем Делегат;

Функция ДолженСэмплировать(Контекст, ИдТрассировки, ИмяСпана, ВидСпана, Атрибуты, Линки) Экспорт
    Если ИмяСпана = "GET /health" Тогда
        Возврат ОтелСэмплер.Результат(ОтелСэмплер.РешениеОтбросить());
    КонецЕсли;
    Возврат Делегат.ДолженСэмплировать(Контекст, ИдТрассировки, ИмяСпана, ВидСпана, Атрибуты, Линки);
КонецФункции

Функция Описание() Экспорт
    Возврат "SkipHealthChecks{" + Делегат.Описание() + "}";
КонецФункции

&Реализует("ИнтерфейсСэмплер")
Процедура ПриСозданииОбъекта(НовыйДелегат)
    Делегат = НовыйДелегат;
КонецПроцедуры

Регистрация сэмплера: корневые спаны без проверок работоспособности сэмплируются с долей 10%, дочерние наследуют решение родителя:

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

ПодключитьСценарий(ОбъединитьПути(ТекущийСценарий().Каталог, "СэмплерБезПроверок.os"), "СэмплерБезПроверок");

Корневой = Новый СэмплерБезПроверок(ОтелСэмплер.ПоДолеТрассировок(0.1));
Провайдер = Новый ОтелПостроительПровайдераТрассировки()
    .УстановитьСэмплер(ОтелСэмплер.НаОсновеРодителя(Корневой))
    .Построить();

Сэмплер, который добавляет атрибут к сэмплированным спанам:

bsl
Функция ДолженСэмплировать(Контекст, ИдТрассировки, ИмяСпана, ВидСпана, Атрибуты, Линки) Экспорт
    Результат = Делегат.ДолженСэмплировать(Контекст, ИдТрассировки, ИмяСпана, ВидСпана, Атрибуты, Линки);
    Если Результат.Решение() = ОтелСэмплер.РешениеОтбросить() Тогда
        Возврат Результат;
    КонецЕсли;
    АтрибутыСэмплера = Новый Соответствие();
    АтрибутыСэмплера.Вставить("sampler.name", Делегат.Описание());
    Возврат Новый ОтелРезультатСэмплирования(Результат.Решение(), АтрибутыСэмплера,
        Результат.СостояниеТрассировки());
КонецФункции

См. также ​