TL;DR:

Locust умеет автоинструментацию через OpenTelemetry (флаг --otel): нагрузочные запросы начинают отправлять метрики и трейсы и “склеиваются” с трейсами приложения через W3C Trace Context. Это упрощает разбор деградаций, помогает отделять трафик теста от фонового по service.name и явно показывает скрытую часть задержки — время установления соединения в первом спане, из-за которого «общая задержка» не совпадает с трейсом сервиса.

Locust — open-source инструмент, а OpenTelemetry — стандарт для сбора телеметрии. Интеграция OpenTelemetry с Locust позволяет передавать в observability-платформу трейсы и метрики нагрузочного теста, делая его наблюдаемым.

Проблема в том, что традиционное нагрузочное тестирование требует объёмной ручной корреляции на стороне бэкенда и часто упирается в тупики из-за «слепых зон» в коде приложения и распределённых системах. Встроенные средства мониторинга от вендоров дают отдельные подсказки, но цельной истории производительности «от начала до конца» нередко не хватает.

Решение: благодаря автоинструментации скриптов Locust через OpenTelemetry нагрузочные тесты теперь будут испускать сигналы OpenTelemetry. Эта телеметрия нагрузочного теста в реальном времени поступает в систему наблюдаемости, поддерживающую OpenTelemetry (через Collector/экспортёры), что даёт возможность связать запросы нагрузки с трассировками приложения и видеть путь запроса по сервисам.

Этот подход, основанный на наблюдаемости, упрощает анализ результатов и корреляцию причин: он даёт инженерам возможность точно связывать моделируемую нагрузку с теми особенностями поведения приложений, которые становятся ограничивающим фактором. Это упрощает поиск узких мест: нагрузочные запросы можно сопоставлять с конкретными участками кода/инфраструктуры по трейсам.

А как быть с теми сбивающими с толк�� ситуациями, когда бизнес-транзакции показывают общее время отклика, которое не совпадает с полным распределённым трейcом? 

Влияет ли на пользовательский опыт неучтённая или скрытая задержка? Да. Давайте посмотрим, где именно искать.

Locust написан на Python

Open-source Locust широко используется для нагрузочного тестирования: он построен на простом и удобном Python, позволяет гибко имитировать реалистичное поведение пользователей и моделировать правдоподобные нагрузки. Дополнительный плюс Locust в том, что он написан на Python — языке, который уже поддерживается OpenTelemetry.

Инструментируя open-source скрипты Locust с помощью OpenTelemetry, инженеры теперь могут получить полную сквозную наблюдаемость нагрузочного теста «от начала до конца».

Locust поддерживает интеграцию с OpenTelemetry.

Добавлен флаг --otel

Команда разработчиков Locust добавила возможность автоинструментации нагрузочных скриптов, которая позволяет им испускать стандартизованную телеметрию — включается флагом --otel.

OTel — необязательная зависимость Locust, доступная начиная с версии 2.42.4. Установите так, или прочитайте полную документацию.

pip install -U locust[otel]

Как это всё работает…

Как и в любом приложении, использующем OTel, вам нужно будет экспортировать соответствующие переменные окружения. У каждой платформы наблюдаемости свои особенности — ориентируйтесь на инструкции вашего вендора.

export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_ENDPOINT=https://...
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

Далее используйте новый флаг --otel и позвольте Locust выполнить автоинструментацию. Каждый HTTP/S-запрос, выполненный через HttpUser, будет испускать сигналы OpenTelemetry — в частности, размерные метрики и трейсы с контекстом.

Ниже — обычный нагрузочный тест Locust. Его легко написать, легко поддерживать и легко настраивать.

class MockTarget(HttpUser):
    @task
    def t(self):
        self.client.post("/authenticate", json={"user": "foo", "password": "bar"})

        for product_id in [1, 2, 42, 4711]:
            self.client.get(f"/product/{product_id}", name="/product/{product_id}")
            self.client.post("/cart/add", json={"productId": product_id})

        self.client.post("/checkout/confirm")

Этот конкретный скрипт выполняет следующие шаги: входит в веб-приложение, просматривает четыре разных товара, добавляет их в корзину и оформляет покупку.

Типичное место назначения сигналов OpenTelemetry по умолчанию — локальный Collector. В данном случае, в первом релизе Locust с OTel, скрипт инициализирует экспортёры метрик и трейсов, использует RequestsInstrumentor из OTel-инструментации requests для автоинструментации и отправляет телеметрию в платформу наблюдаемости — напрямую с генераторов нагрузки.

Автоинструментация запускается при старте нагрузочного теста — как показано в командной строке ниже.

locust -f ecommerce_shopper.py --otel --users 500 --spawn-rate .5 
--run-time 1h --cloud

Эта команда запускает нагрузочный тест со скриптом ecommerce_shopper.py. Флаг --otel включает авто-инструментацию OTel. Пиковая нагрузка — 500 одновременных пользователей, скорость наращивания — 1 пользователь каждые 2 секунды, длительность выполнения — 1 час.

Флаг --cloud использует размещённые в Locust Cloud раннеры тестов и требует аккаунта, но OTel работает и при локальном запуске.

Обратите внимание: Locust уже готов к нагрузочным тестам с OpenTelemetry-инструментацией на HttpUser, а поддержка FastHttpUser появится в ближайшее время.

За более продвинутыми сценариями нагрузки — например, запуском нескольких скриптов и пользовательскими кривыми/формами нагрузки — можно обратиться к нашей документации.

Когда OTel включён, Locust также покажет это в выводе:

locust --users 500 --otel --spawn-rate '.883' --run-time 2h --cloud
locust --users 500 --otel --spawn-rate '.883' --run-time 2h --cloud

После инициализации нагрузочного теста и готовности генераторов нагрузки нажмите ENTER, чтобы открыть браузер, запустить тест и следить за результатами в реальном времени. Либо используйте --headless, чтобы тест стартовал сразу — это также удобно для автоматизированных CI/CD-конвейеров.

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

Locust cloud dashboard showing two graphs; throughput / active users and average response times for each request url
Панель мониторинга Locust Cloud отображает два графика: пропускная способность / количество активных пользователей и среднее время ответа для каждого URL-адреса запроса.

Наблюдаемый нагрузочный тест (размерностные метрики) в платформе Splunk Observability.

Splunk observability platform showing dimensional metric graphs
Платформа мониторинга Splunk, отображающая многомерные метрические графики.

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

Splunk dashboard showing load request traces
Панель мониторинга Splunk, отображающая трассировку запросов на загрузку.

Ниже — детали механики propagation/parent-child спанов; для использования фичи знать это необязательно.

Объяснение, как работают распространение контекста OTel и связывание спанов:

Один сквозной трейс «от начала до конца»: Locust HttpUser → микросервис → база данных → нижестоящие (зависимые) сервисы

Когда вы запускаете нагрузочный тест Locust с включённым OpenTelemetry, каждый запрос HttpUser создаёт исходящий клиентский спан — корневой спан. OpenTelemetry автоматически добавляет к каждому запросу W3C-заголовки Trace Context (например, traceparent). Если ваше целевое приложение тоже инструментировано OpenTelemetry — или любым APM, который поддерживает W3C Trace Context, — оно читает эти заголовки, продолжает тот же Trace ID и создаёт серверный спан как дочерний по отношению к спану Locust. Так трафик вашего нагрузочного теста «бесшовно» связывается с трейсами приложения, обеспечивая полную сквозную видимость без какой-либо ручной работы.

В результате вы получаете полную сквозную видимость транзакций в выбранной вами платформе наблюдаемости.

Полный трейс, который начинается со спана Locust: обратите внимание, что имя спана — это полный URL HTTP-запроса; это может быть веб-страница или вызов API-сервиса.

Splunk dashboard showing 6 spans measured starting from locust
Панель мониторинга Splunk, отображающая 6 измеренных диапазонов, начиная с Locust

Результаты можно анализировать через трейсы и метрики.

Анализ производительности может стать проще. 

Недостающий элемент: самый первый спан

Одно из интересных открытий, которое вы наверняка сделаете, — это самый первый спан в трейсе: он включает время установления соединения от генератора нагрузки Locust (worker) до вашего целевого приложения.

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

Этот первый (1-й) спан Locust — важный отличительный признак, потому что в традиционных нагрузочных тестах время соединения «прячутся» внутри общих результатов теста, а именно — в метриках времени ответа. В наблюдаемых нагрузочных тестах следующий спан (2-й) в полном трейсе показывает «реальное» время ответа приложения. Между двумя спанами легко увидеть накладные расходы, связанные с задержкой соединения.

Когда спаны соединения видны, вы наконец сможете объяснить эти «пропавшие» куски времени — а когда вы можете их измерить, вы можете их и оптимизировать.

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

Splunk dashboard showing root span
Панель мониторинга Splunk, отображающая корневой сегмент.

Анализ нагрузочных тестов без «шума» в общих средах

Уверен, всем хотелось бы запускать нагрузочные тесты в тихих, максимально похожих на продакшен средах — но так бывает редко. Эх, если бы, да?

Большинство нижестоящих окружений и сам продакшен сильно «шумят» из-за фонового трафика. В таких средах, как CI/CD-пайплайны, QA или стейджинг, и, конечно же, продакшен, почти всегда параллельно происходит что-то ещё — и это создаёт «шум». В такой типичной ситуации сложно понять, какие транзакции пришли именно от виртуальных пользователей вашего нагрузочного теста, а иногда даже — когда тест начался и когда закончился.

В таких условиях сложно отделить трафик теста от фонового и определить границы тестового окна.

С OpenTelemetry в Locust все нагрузочные тесты будут автоматически изолироваться по имени сервиса (Service Name). Благодаря этому можно точно увидеть, когда тест стартовал, когда завершился, ясно смотреть метрики и тренды и анализировать только релевантные транзакции.

Фильтрация по service.name позволяет отделять данные теста от фонового трафика и анализировать их отдельно.

По умолчанию имя сервиса — locust, но вы можете изменить его, экспортировав переменную окружения ниже.

OTEL_SERVICE_NAME=locust-loadtest

Обратите внимание на изолированный сервис нагрузочного тестирования в платформе наблюдаемости Splunk.

Splunk dashboard filtered by metrics and traces from locust-loadtest
Панель мониторинга Splunk, отфильтрованная по метрикам и трассировкам из locust-loadtest.

Становится проще отфильтровать и интерпретировать данные теста

Вот более полный пример необходимых переменных окружения Splunk OTEL

OTEL_EXPORTER_OTLP_HEADERS=X-SF-TOKEN="..."
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://ingest.us1.signalfx.com/v2/trace/otlp"
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT="https://ingest.us1.signalfx.com/v2/datapoint/otlp"
OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http

Имейте в виду: отправка телеметрии нагрузочного теста OTel в вашу платформу наблюдаемости увеличит объём приёма д��нных (ingest), и со стороны вендора могут применяться дополнительные сборы. Также проверьте параметр time-to-glass в вашей платформе наблюдаемости — то есть задержку между поступлением данных и их отображением в интерфейсе; «реальное время» может ощущаться по-разному на разных платформах.

Что это даёт на практике

  • Изоляция от фонового «шума» — нагрузки ваших тестов отделяются от фонового трафика.

  • Ясность от старта до финиша — вы точно знаете, когда тест начался, как наращивалась нагрузка и когда он завершился, во всех распределённых сервисах.

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

  • Настоящее сквозное понимание «от начала до конца» — связывайте время ответа с инфраструктурными метриками вроде состояния K8s, CPU, памяти и облачных ресурсов в одном представлении.

Преимущества наблюдаемости: анализ на основе ИИ

Загадка: когда телеметрия нагрузочного теста попадает в современные платформы наблюдаемости, что вдруг становится умнее обычного дашборда?

Подсказка: оно автоматически коррелирует все OTel-сигналы, анализирует спаны с данными о нижележащей (hosted) инфраструктуре, и замечает узкие места быстрее ручного анализа.

Ответ: конечно же, функции AI/ML-аналитики в платформе наблюдаемости.

Эти платформы наблюдаемости развиваются очень быстро. Большинство из них уже могут сказать вам, почему деградировала производительность — или хотя бы предложить вероятные первопричины — даже без вашего расследования. Да, навыки инженерии производительности всё равно нужны; однако ИИ-функции способны заметно сократить время анализа. Так почему бы этим не воспользоваться?

Заключительная мысль

Open-source Locust и OpenTelemetry делают нагрузочное тестирование более “observability-driven” (с опорой на телеметрию): метрики показывают, когда производительность начинает ухудшаться, трейсы — где и почему происходит замедление (в коде или в инфраструктуре), а логи дают ещё более высокий уровень детализации (verbosity).

Подробнее можно узнать в документации.


Если хотите расти в performance-инженерию, курс «Нагрузочное тестирование» закрывает весь цикл: методика, скрипты (JMeter/Gatling/k6, Performance Center), CI/CD и мониторинг в Grafana. В итоге сможете не просто «гонять нагрузку», а уверенно разбирать результаты и находить узкие места по данным. Готовы к обучению? Пройдите вступительный тест.

Для знакомства с форматом обучения и экспертами приходите на бесплатные демо-уроки:

  • 27 января, 20:00. «Wireshark 1/2: интерфейс и возможности». Записаться

  • 10 февраля, 20:00. «Wireshark 2/2: ищем узкие места». Записаться

  • 17 февраля, 20:00. «Стенды для нагрузочного тестирования». Записаться