DarkRiDDeR17 мин

Августовский план сквозной наблюдаемости: карта сигналов от UI до worker без лишних данных

АрхитектураНаблюдаемость

В августе 2026 я бы начал не с выбора панели, а с потери одного correlation context на границе API и worker. UI ещё показывает запрос, API уже пишет строку, worker считает задачу, но три сигнала нельзя собрать в один вопрос. Цена не в отсутствии красивого trace: инженер получает три правдоподобных фрагмента и не может отделить задержку очереди от ошибки API или повторной работы worker.

Вторая цена появляется, когда для склейки начинают добавлять email, полный URL, текст формы или сырой user id. Такой label помогает ровно до первого масштабирования: он расширяет поверхность данных и дробит series. Поэтому это не отчёт об уже выполненной августовской работе. Это датированный план: состояние источников на 31.07.2026, один fixed UI → API → worker сценарий и ограничение, что положительный результат бывает только bounded-observability-handoff.

Сначала назвать путь, затем три разных сигнала

Для планирования достаточно одной операции с нейтральным именем ui.checkout.submit. UI создаёт span, API пишет структурированный log о принятом действии, worker увеличивает счётчик jobs. Эти сигналы не взаимозаменяемы. Span отвечает на вопрос о последовательности и длительности. Log хранит объяснение одной именованной ветки. Metric пригодна для агрегированного числа однотипных работ. Если у всех один и тот же набор полей и один и тот же смысл, команда не получила три сигнала, а три хрупкие копии.

W3C Trace Context задаёт переносимый traceparent и отдельно предупреждает о privacy considerations. Спецификация не говорит, что у нас есть реальная трасса, и не разрешает класть туда пользовательские значения. В августовском плане это переводится в узкое правило: переносится технический context, а бизнес-идентификатор остаётся вне него, пока не определены полномочия, срок хранения и отдельная модель доступа.

Карта границ сигнала: UI создаёт trace context и span, API переносит context и пишет структурированный log, worker получает context и создаёт агрегированную metric; рядом показаны запрещённые персональные и высококардинальные поля.
Карта не изображает работающую систему. Она показывает, где в августовском плане владелец каждого перехода обязан назвать контекст, тип сигнала и запрещённые поля.
Плановая карточка одного пути
ГраницаСигналБезопасные классы полейНе делать вывод
UI → APIspanroute-template, request-kindчто пользователь завершил действие
APIstructured logoperation-name, outcome-classчто ответ был доставлен
API → workerpropagation contracttrace context, job-kindчто задача выполнена
workermetricjob-kind, outcome-classчто известна причина каждой серии
общаяsampling rulefixed error-or-1-of-20 planчто измерена доля или стоимость

Correlation context — ключ к вопросу, не контейнер для данных

Нужно различать correlation и identity. Correlation говорит: эти три synthetic записи относятся к одному named path. Identity говорит: кто именно совершил действие. Первое необходимо для исследования границы; второе часто лишнее и требует отдельной правовой и технической оценки. В fixed literal используется fixed-trace-7f. Он не выглядит как настоящий trace-id и не проверяет формат заголовка: его задача — сделать связь видимой, а не имитировать сетевой протокол.

Владелец API не должен «просто пробросить всё». Он принимает контекст, создаёт дочернюю операцию или точный stop, если правила границы не описаны. Владелец worker не должен строить metric из произвольного поля очереди: он получает job-kind и outcome-class, а не payload. Владелец UI не пишет текст формы в атрибуты только потому, что он уже есть в памяти браузера. Такая дисциплина уменьшает число мест, где случайный diagnostic payload может пережить полезный срок.

Буквально исполнимый плановый validator

import { createFixedObservabilityPlan, reviewFixedObservabilityHandOff } from './upgrade-2026-08.mjs';

const plan = createFixedObservabilityPlan('ui-api-worker-plan-v1');
const result = reviewFixedObservabilityHandOff(plan);
console.log({ status: result.status, context: result.signalMap.context, effect: result.effect });
// { status: 'bounded-observability-handoff', context: 'fixed-trace-7f', effect: 'no-system-change' }

Этот код читает JSON-cloned и deeply frozen literal. Он не создаёт header, не вызывает SDK, не пишет log, не отправляет metric и не читает сеть. Его полезный эффект намного скромнее: validator не разрешит назвать hand-off, если пропал worker context, встречается заранее запрещённое поле или positive branch стала похожа на deployment. Для плана это лучше «успешной» демонстрации, которая молча получает доступ к окружению.

High cardinality лечат проектированием вопроса

Высокая кардинальность — не свойство «плохой метрики», а следствие вопроса, который пытаются задать без группировки. job-kind может быть классом работ; raw-user-id почти всегда превращает счётчик в журнал идентификаторов. outcome-class годится для небольшого списка исходов; текст исключения и URL с query образуют бесконечный словарь. Если расследованию нужен индивидуальный след, в августовском плане он не подменяется metric label: ему нужен отдельный ограниченный канал и отдельная policy.

OpenTelemetry metrics data model описывает re-aggregation и уменьшение набора attributes как способы работать с нежелательными attributes. Из этого не следует готовый лимит для конкретной команды. Наше правило консервативнее: до появления доказанного потребителя оставить только classes, а каждое новое поле связывать с вопросом, сроком хранения и местом, где оно может быть удалено. Нет вопроса — нет поля.

Порядок действий на август

  1. Выбрать один пользовательский путь и записать UI, API и worker как три именованные границы.
  2. Для каждой границы выбрать один главный сигнал и вопрос, на который он отвечает.
  3. Записать один технический correlation context и явный список полей, которые в него не попадают.
  4. Назвать низкокардинальные classes для logs и metrics; свободный текст, идентификаторы и query сразу вынести в запрет.
  5. Сформулировать synthetic sampling rule как план, не как измеренный процент и не как обещание экономии.
  6. Прогнать fixed validator и передать только plan hand-off либо точный stop следующему review.

Sampling не равен отсутствию наблюдаемости

Семплирование отвечает на вопрос, какие synthetic traces будут сохранены в плановой модели; оно не делает log и metric автоматически согласованными. Ошибка может требовать отдельного правила, а обычная ветка — детерминированного отбора. Но даже фраза «error-or-1-of-20» здесь не является production configuration: это именованная гипотеза для review. До августа не было запуска, не было доли отбора, не было стоимости хранения и не было результата расследования.

Полезная граница — хранить в hand-off причину rule: она создана для ограничения объёма fixed model, а не для потери неприятных данных. Если позднее появится отдельная эксплуатационная работа, ей придётся показать реальные требования к ошибкам, privacy, capacity и collector. Нельзя перескочить через эту работу, сославшись на сработавший local snippet.

Кому принадлежит граница сигнала

У сквозного пути нет одного технического владельца, но у каждого перехода должен быть владелец вопроса. UI-владелец отвечает за то, что route-template не превращается в полный адрес и что отправляемый context не получает данные формы. API-владелец отвечает за разбор, создание и передачу контекста, а также за словарь outcome-class. Владелец worker определяет, какие job-kind вообще существуют и почему его metric не содержит payload. Платформенный reviewer проверяет только совместимость этих решений, а не подменяет их одной общей библиотекой. Такой разбор предотвращает типичную ошибку: SDK установлен, поэтому будто бы кто-то уже отвечает за смысл атрибутов.

Для каждой boundary полезно оставить два явных решения: кто имеет право предложить новое поле и кто обязан отклонить его без evidence. Предложение «добавим request id в metric, чтобы было проще» должно отвечать на четыре вопроса: это correlation или identity, каков допустимый словарь, как будет удалено значение и почему log или trace не решают задачу точнее. Если ответа нет, это не технический долг на будущее, а текущий запрет. Он не замедляет разработку: наоборот, не даёт перенести последствия плохой схемы на storage и людей, которые будут потом разбирать данные.

Как отличить schema от названия поля

Название outcome ещё не делает поле безопасным. Schema появляется, когда перечислены допустимые values, граница их происхождения и реакция на неизвестное значение. В плановом контуре неизвестный outcome не надо записывать как исходный текст: он должен стать named class unknown вместе с отдельным вопросом к владельцу taxonomy. То же относится к job-kind: новая работа не дописывает произвольное имя из сообщения, а проходит новый review. Это немного менее удобно при первом прототипе, зато не позволяет случайному input расширить число series и семантику отчёта.

Trace attributes требуют той же строгости, хотя не являются metric dimensions. У поля должна быть техническая причина: помогает ли оно различить границу, класс операции или договорённость propagation. «Может пригодиться в расследовании» не является причиной, потому что это фраза без времени, consumer и limits. В августовском плане достаточно schema note возле каждого allowed field. Когда появится отдельная authorisation на реальный pilot, именно эти notes станут входом для review, а не воспоминания автора о том, что он имел в виду под коротким именем.

Ограничения и следующий шаг

Этот августовский план не доказывает propagation библиотек, формат queue message, доступность backend, качество trace, стоимость кардинальности или отсутствие персональных данных в существующих системах. W3C и OpenTelemetry здесь служат словарём для context, spans и attributes; они не подтверждают наш synthetic маршрут. Таблица и SVG также не являются architecture decision или политикой хранения.

Следующий шаг — провести узкий design review одной карточки: у каждого поля спросить «какой вопрос, где владелец, какой срок и почему это не идентификатор». Если worker не может получить тот же named context, вернуть stop-broken-correlation-context. Если поле нельзя объяснить без «на всякий случай», убрать его. Только после этого имеет смысл планировать отдельный authorised discovery вне данного пакета.

Проверяемые источники

  • OpenTelemetry Specification, trace API and metrics data model — версия: immutable commit c6520a73287040ca16499cba62cea1b3508dc4da, Release 1.29.0, 11 January 2024. Pinned OpenTelemetry source задаёт терминологию SpanContext, TraceId и attributes, а также описывает уменьшение нежелательных metric attributes. Граница: Source не подтверждает наличие SDK, collector или telemetry data в этой будущей работе.
  • W3C Trace Context — версия: W3C Recommendation, dated 23 November 2021. W3C Recommendation описывает перенос traceparent/tracestate и содержит privacy considerations. Граница: Стандарт не делает synthetic fixed context реальным заголовком и не разрешает передавать персональные данные.