Проблема фразы «мы дали много запросов» в том, что она описывает объём шума, но не модель нагрузки. В ней не видно, когда возникал input, какой endpoint он представлял, какой набор данных использовался, что считалось завершением и кто наблюдал последствия. Цена — ложная причинность: aggregate меняется, а команда приписывает его очереди, базе или коду, хотя могла измениться сама среда или сценарий.
Для механизма достаточно одной строгой границы. В этой статье arrival означает намерение поставить planned request slot в сегмент профиля. Это не отправка запроса и не скорость. Fixture материализует slots в accepted/rejected synthetic units внутри local objects. Она не создаёт clock, HTTP, сеть, процесс, нагрузочный инструмент или telemetry. Поэтому слова latency-signal и error-signal ниже — диагностические ярлыки, а не измеренные метрики.
Модель начинается с формы входа
Полезная запись выглядит так: endpoint intent + data setup + environment constraint + ordered segments + stop criterion + evidence packet. Каждый элемент отвечает на отдельный вопрос. Endpoint ограничивает предмет. Data setup не даёт одному и тому же имени скрывать разные записи. Environment объясняет, при каком договоре существует наблюдение. Segments показывают переход. Criterion определяет, когда доказательство достаточно. Packet держит все поля рядом, чтобы вывод не зависел от памяти автора.
Если убрать любой элемент, получаем другой тип неопределённости. Без endpoint нельзя отличить чтение от изменения. Без данных нельзя повторить branch. Без среды невозможно увидеть drift. Без сегментов total не показывает порядок. Без criterion нельзя понять, почему модель закончилась именно здесь. Без packet остаётся пересказ, который невозможно проверить. Это не бюрократия вокруг теста: это минимальная структура причинной связи.
| Свойство | Профиль fixture | «Много запросов без сценария» | Инженерское последствие |
|---|---|---|---|
| Endpoint intent | один нейтральный путь и метод | не указан | нельзя проверить контракт входа |
| Arrival intent | slots принадлежат named segment | есть только total | нельзя увидеть переходы |
| Среда | identity и synthetic constraint записаны | не указана | любой drift маскируется под результат |
| Accepted / rejected | разложены по segment | не определены | неясно, что именно не прошло |
| Stop criterion | evidence после recovery | нет | конец наблюдения произволен |
| Interpretation | только training model | обычно звучит как verdict | риск выдать счётчик за throughput |
Arrival не равен completed work
В реальном инструменте способ моделировать arrival зависит от executor, версии и конфигурации. Нельзя переносить значение одного параметра между tool без чтения его документации. В k6 v0.35.0 release notes отдельно связывают stage tags с конкретными executors; это исторический факт о версии, а не лицензия назвать любой массив slots её сценарием. Наша fixture специально не повторяет API инструмента. Она показывает только вопрос, который нужно сформулировать до выбора API: что означает появление следующего planned slot и как эта попытка будет отделена от результата обработки.
Разделение полезно и для закрытой модели пользователей, и для открытой модели arrival. В первом случае нужно назвать, кто ждёт завершения предыдущей итерации. Во втором — как tool ведёт себя при невозможности начать следующую работу. Но оба случая остаются неполными без data setup и environment. Число на оси не заменяет эту информацию. Поэтому article не предлагает универсальный executor и не выдаёт synthetic acceptance limit за реальную настройку генератора.
Профиль хранит намерение и результат рядом
У каждого segment fixture есть именованные slots, accepted units, rejected units, synthetic bottleneck flag и boundary text. Наличие flag не превращает rejection в ошибку приложения. Это самопроверка модели: step был объявлен как учебная граница до materialization, а не задним числом назван узким местом после просмотра результата. Такая разница особенно важна в текстах про производительность, где красивый график часто даёт больше уверенности, чем его исходные условия.
Проверка reconciliation предельно простая: длина plannedRequestSlots должна равняться acceptedUnits + rejectedUnits. Она не измеряет полезную работу и не заменяет server-side evidence. Зато она ловит редакционную ошибку: если часть plan исчезла между профилем и таблицей, автор больше не может честно сказать, что сравнил одно и то же. Именно такие мелкие несовпадения потом превращают нагрузочную заметку в набор несвязанных сигналов.
Observability начинается с семантики данных
Наблюдаемость здесь не означает автоматически подключённый dashboard. Сначала нужны хорошо названные поля: endpoint intent, environment identity, data identity, segment name, planned slots, accepted/rejected units и stop state. Затем выбирается настоящий инструмент, который умеет сохранить требуемый raw signal и его контекст. OpenTelemetry Metrics API в historical tag v1.0.0 подчёркивает, что instrument задаёт смысл measurement, а не только форму числа. При этом документ помечен experimental; он не может быть основанием приписать старой системе готовую телеметрию.
Evidence packet полезен потому, что связывает две шкалы: plan и observation. План отвечает, что хотели проверить. Observation отвечает, какие учебные units были materialized. Если packet не содержит environment или criterion, визуализация всё равно может существовать, но reader уже не знает, какую именно гипотезу она проверяет. Поэтому packet не экспортируется как trace и не изображает работу настоящего мониторинга: это object для детерминированной проверки редакционной модели.
Synthetic bottleneck нужен для отрицательной проверки
Step в fixture получил пять slots при явном limit в три accepted synthetic units. Модель оставляет два rejected units и поднимает единственный syntheticBottleneckFlag. Это намеренно скучный результат. Его задача — проверить четыре свойства: rejected units видны, flag находится в правильном segment, recovery идёт после step, stop criterion не срабатывает раньше. Если бы модель всегда принимала всё, она не проверяла бы путь, в котором author обязан объяснить границу.
Неправильный вывод звучал бы так: «мы нашли bottleneck и latency выросла». У fixture нет времени, сервера или наблюдаемой очереди, поэтому такой вывод нельзя получить. Правильный вывод уже: «план содержит заранее отмеченную synthetic boundary; для реального расследования нужны environment manifest, raw output выбранного tool и отдельный источник latency-signal». Скромная формулировка оставляет место для следующего эксперимента, а не подменяет его.
Минимальный пример: проверить packet и отклонить bare count
Этот пример читает mechanism, а не запускает testing software. Он выводит путь как intent, явное ограничение среды и stop object. Последняя assertion возвращает false для aggregate, где есть только synthetic total. Так мы проверяем не способность «создать много», а способность не называть нагрузочной моделью то, что не содержит сценария.
const fixture = runLoadTestingFixture();
const packet = fixture.evidencePacket;
console.log(packet.endpoint.path);
// /fixture/neutral-resource — intent only; no HTTP call exists in the fixture
console.log(packet.environment.explicitConstraint);
// at most three accepted synthetic units in one planned segment
console.log(packet.stop);
// stopped-by-criterion after recovery evidence is present
if (!fixture.assertions.badAggregateRejected) {
throw new Error("a count without scenario was accepted as a model");
}
В коде нет fetch, http, setTimeout, файла или child process. Это не ограничение языка и не рекомендация для production. Это защита смысла fixture: добавление реального вызова сделало бы её зависимой от внешнего состояния и позволило бы принять случайный ответ за доказательство. Реальный инструмент нужно запускать отдельной операцией с отдельным пакетом условий, а не прятать в редакционный self-check.
Маршрут: симптом → причина → проверка → действие
- Симптом. В отчёте есть aggregate или один график, но невозможно назвать endpoint, среду, data setup и момент остановки.
- Причина. Total принят за workload model; intention, completed work и наблюдение смешаны в одном числе.
- Проверка. Разделите карточку на endpoint, данные, environment, named segments, accepted/rejected units и criterion. Проверьте порядок warm-up → steady → step → recovery.
- Проверка смысла. Для каждого поля назовите единицу и запрет. Если unit не имеет времени, не называйте его latency, throughput или RPS.
- Действие. Отклоните bare count, пока в нём нет scenario и evidence packet. Затем выберите historical version конкретного tool и сверяйте его semantics с его документацией.
- Ожидаемый результат. Следующая диаграмма объясняет не только, что было нарисовано, но и какой вопрос она вправе помогать расследовать.
Ограничения и следующий проверяемый шаг
Fixture не сообщает, как ведут себя executors k6, как рассчитываются thresholds, как именно агрегирует метрики OpenTelemetry или какие свойства имеет конкретный server. Ссылки на k6 v0.35.0 и его samples/thresholds.js зафиксированы, чтобы не ссылаться на mutable current documentation. Они нужны только для historical boundary и для требования называть metric вместе с порогом. Пакет не исполняет k6, не создаёт VU и не использует его API.
Не моделируются HTTP, сеть, TLS, DNS, scheduler, queue, CPU, память процесса, база, cache, browser, пользователь, latency, throughput, error rate, capacity, production incident или результат benchmark. RFC 2330 добавлен как внешняя рамка аккуратного определения метрик, но он относится к IP performance metrics и не определяет готовность application endpoint. Следующий шаг — описать один реальный tool-run отдельно, не смешивая его raw output с объектами этой учебной модели.
Проверяемые источники
- Grafana k6 v0.35.0: versioned release record — релиз опубликован 17 ноября 2021 года; он задаёт историческую верхнюю границу для упоминания инструмента и не является результатом прогона этой fixture
- Grafana k6 v0.35.0: fixed source snapshot samples/thresholds.js — точный commit, на который указывает тег v0.35.0; пример связывает порог с именованной метрикой, а пакет не импортирует k6 и не исполняет его
- OpenTelemetry Specification v1.0.0: fixed Metrics API snapshot — снимок от февраля 2021 года помечает Metrics API как experimental и отдельно описывает смысл измерения, instrument и aggregation; fixture не реализует OpenTelemetry
- OpenTelemetry Specification v1.0.0: fixed Trace API snapshot — исторический документ для терминов trace и span; evidence packet в этой статье является локальным object, а не экспортированной трассой
- RFC 2330: Framework for IP Performance Metrics — нормативная рамка для аккуратного определения измеряемого свойства; RFC относится к IP-метрикам и не превращает учебный endpoint в capacity benchmark