Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Семплирование трейсов: head и tail sampling

Семплирование трейсов: head sampling против tail sampling

Семплирование трейсов: различие head и tail sampling, доля отбора, сохранение трейсов с ошибками, стоимость хранения и настройка в OpenTelemetry.

Прямой ответ

Семплирование — сохранение части трейсов вместо всех. При высокой нагрузке полный сбор трейсов стоит дороже, чем польза от них, поэтому сохраняется доля. Ключевой вопрос — в какой момент принимается решение об отборе, и от этого зависит, попадут ли в хранилище интересные случаи.

Head sampling — решение принимается в начале трейса, до того как известно, чем он завершится:

Head sampling Tail sampling
Момент решения Начало трейса После завершения трейса
Критерий Случайная доля Свойства завершённого трейса
Требует буферизации Нет Да
Сохраняет трейсы с ошибками Случайно Гарантированно
Стоимость инфраструктуры Ниже Выше

Head sampling реализуется на стороне приложения и не требует дополнительного компонента:

# OpenTelemetry: отбирается 1 трейс из 100
sampler = TraceIdRatioBased(0.01)

Ограничение head sampling: трейс с ошибкой сохраняется с той же вероятностью, что и успешный. При доле 1 процент и частоте ошибок 0,1 процента в хранилище окажется примерно один из ста ошибочных трейсов — ровно тогда, когда он нужен для разбора.

Tail sampling — решение принимается после завершения трейса, когда известны его длительность, наличие ошибок и пройденные сервисы:

# политики отбора в коллекторе
processors:
  tail_sampling:
    policies:
      - name: errors-always
        type: status_code
        status_code: {status_codes: [ERROR]}
      - name: slow-traces
        type: latency
        latency: {threshold_ms: 2000}
      - name: sample-rest
        type: probabilistic
        probabilistic: {sampling_percentage: 5}

Такая конфигурация сохраняет все трейсы с ошибками, все медленные трейсы и 5 процентов остальных. Это решает главную проблему head sampling: интересные случаи сохраняются гарантированно.

Цена tail sampling — буферизация. Коллектор должен хранить спаны трейса до его завершения, чтобы принять решение. При высокой нагрузке это требует памяти и ограничивает время ожидания; о сборе телеметрии — в статье про трейсинг распределённых транзакций.

Практическое правило: head sampling подходит при ограниченном бюджете и низкой частоте ошибок. Tail sampling оправдан, когда разбор инцидентов требует конкретных трейсов с ошибками, а не случайной выборки; о метриках — в статье про инструментирование приложения.

Стоимость хранения и выбор доли

Доля отбора напрямую определяет объём данных, а значит и счёт за хранилище. Расчёт помогает выбрать значение осознанно, а не наугад.

Оценка объёма строится от числа запросов:

запросов в сутки × спанов на запрос × размер спана × доля отбора = объём в сутки

Для сервиса с миллионом запросов в сутки, пятью спанами на запрос и размером спана 1 килобайт полный сбор даёт около 5 гигабайт в сутки. Доля 10 процентов снижает объём до 500 мегабайт, но вместе с ним снижает вероятность сохранения редкого события.

Tail sampling меняет экономику: объём растёт за счёт сохранения всех ошибочных трейсов, но снижается за счёт меньшей доли случайного отбора. Итоговый объём часто сопоставим с head sampling при существенно большей полезности данных.

Три практических правила выбора доли:

Ориентируйтесь на редкость события. Если интересующее событие происходит раз в тысяче запросов, доля 1 процент сохраняет одно событие из десяти.

Разделяйте долю по типам операций. Редкие операции сохраняются полностью, массовые — с малой долей. Это требует tail sampling, поскольку решение принимается по завершении.

Пересматривайте долю при изменении нагрузки. Настройка, выбранная для тысячи запросов в секунду, даёт избыточный объём при десяти тысячах.

Практика: настройка семплирования

1. Начните с head sampling. Доля 10 процентов даёт достаточно данных для анализа типичного поведения и не требует дополнительной инфраструктуры.

2. Переходите к tail при частых разборах инцидентов. Если разбор регулярно упирается в отсутствие трейса с ошибкой, случайный отбор себя исчерпал.

3. Сохраняйте все трейсы с ошибками. Правило «ошибки — всегда» даёт наибольшую пользу на единицу стоимости хранения.

4. Сохраняйте медленные трейсы. Порог выбирается по целевой задержке: если SLO составляет 500 миллисекунд, сохранять стоит трейсы дольше 1000; о расчёте — в статье про процентили.

5. Сохраняйте трейсы целиком, а не отдельные спаны. Частичный трейс не показывает путь запроса и бесполезен для анализа.

6. Согласуйте долю между сервисами. Разная доля в разных сервисах приводит к разрывам в трейсах: решение принимается в первом сервисе и передаётся дальше.

7. Контролируйте стоимость хранения. Доля отбора напрямую определяет объём данных; о запросах к накопленному — в статье про LogQL.

8. Проверяйте, что нужный трейс сохранился. После изменения политик убедитесь, что ошибочные запросы попадают в хранилище.

Рекомендации:

  1. Не отбирайте трейсы по идентификатору пользователя. Это приводит к систематическому смещению выборки.
  2. Разделяйте доли для разработки и продуктивной среды. В разработке отбор обычно не нужен, поскольку нагрузка мала.
  3. Учитывайте время буферизации в tail sampling. Трейс, не завершившийся за отведённое окно, может быть отброшен без решения.
  4. Сохраняйте трейсы с редкими операциями. Операция, выполняемая раз в сутки, при доле 1 процент может не попасть в хранилище ни разу за месяц.
  5. Пересматривайте долю при росте нагрузки. Настройка, подходящая для тысячи запросов в секунду, избыточна при десяти тысячах.

Практический сценарий: невозможность разобрать ошибку из-за случайного отбора

Контекст: сервис работал с head sampling на 1 процент. При разборе периодических ошибок оплаты нужный трейс отсутствовал в хранилище в четырёх случаях из пяти.

  1. Диагностика. Частота ошибок составляла 0,2 процента запросов. При доле отбора 1 процент вероятность сохранения ошибочного трейса была такой же, как для успешного, поэтому большинство инцидентов оставалось без данных.
  2. Причина. Семплирование настраивалось для снижения стоимости хранения, и критерий отбора не учитывал ценность трейса. Все трейсы считались одинаково полезными.
  3. Действия. (а) Добавили коллектор с tail sampling; (б) настроили три политики: все трейсы с ошибками, все трейсы дольше двух секунд, 3 процента остальных; (в) увеличили объём хранилища, поскольку доля сохраняемых трейсов с ошибками выросла; (г) уменьшили долю случайного отбора с 10 до 3 процентов, чтобы компенсировать рост объёма; (д) проверили на тестовой нагрузке, что ошибочные трейсы сохраняются.
  4. Результат. Все ошибочные трейсы стали доступны для разбора, а общий объём хранилища вырос на 20 процентов вместо ожидаемого кратного увеличения.

Вывод: доля отбора определяет не только стоимость, но и возможность разбора инцидентов. Head sampling экономит ресурсы, но теряет редкие события; tail sampling сохраняет ценные трейсы гарантированно ценой буферизации и дополнительной инфраструктуры.

FAQ

Какую долю отбора выбрать? Начните с 10 процентов и снижайте при росте нагрузки. Ошибочные и медленные трейсы сохраняйте полностью независимо от доли.

Можно ли использовать оба подхода одновременно? Да. Head sampling снижает объём данных на стороне приложения, а tail sampling в коллекторе отбирает ценные трейсы из оставшихся.

Почему в трейсе не хватает спанов? Вероятная причина — разная доля отбора в разных сервисах. Решение должно приниматься в первом сервисе и передаваться по цепочке.

Что дороже: head или tail sampling? Tail sampling требует коллектора с буферизацией, но может снизить объём хранилища за счёт сохранения только ценных трейсов. Общая стоимость зависит от политик отбора.

Источники: OpenTelemetry docs (Sampling, Tail Sampling), Grafana Tempo docs — ссылки в шапке.