DarkRiDDeR13 мин

Почему рост метрики не является решением: denominator, cohort и guardrail

МетрикиКачество

На отчёте treatment выглядит лучше control, но numerator и denominator собраны из разных наборов. Иногда это случается после невинной оптимизации: страница перестаёт перезагружаться, клиентский event теряется или cohort получает другое окно. Цена ошибки — false positive: команда объясняет пользователю эффект, которого не было, и выпускает изменение с неизвестным ущербом.

Причина не в самой дроби. Любая ratio скрывает состав числителя и знаменателя. Проверка — разложить metric на набор субъектов, события и период, затем убедиться, что treatment и control отвечают на один и тот же вопрос. Действие — сделать эти условия частью result; если хотя бы одно не выполнено, решение получает stop status.

Metric — это контракт, а не имя на графике

В fixed model conversion задан как unique subjects с checkout_confirmed, делённое на unique subjects с checkout_opened, внутри одного cohort и одного дня. Такой contract намеренно мал. Он не говорит, сколько ждать пользователя, как обрабатывать два устройства и что считать «успешным заказом». Но он не даёт случайно заменить denominator на all-events и выдать плотность telemetry за поведение людей.

Матрица fixed synthetic расчёта: local metric, success interpretation и guardrail разделены; строки missing attribution, wrong denominator и mixed period ведут к HOLD, а не к ship.
Матрица показывает границу: удачный local signal разрешает только human review, а любое нарушение измерительного контракта останавливает product decision.
Negative paths, которые нельзя сгладить
СбойПочему delta нельзя читатьМашинный resultРемонт
Нет attributionconfirm не связан с вариантомmissing-attribution-ruleдобавить ключ связи и test
Смешан periodгруппы не наблюдались в одном окнеmixed-cohort-or-periodзафиксировать окно до запроса
Неверный denominatorratio отвечает на другой вопросwrong-denominatorсчитать unique opened subjects
Guardrail деградируетлокальный выигрыш куплен отказамиeligible, но human holdразобрать error path

Проверить ratio до интерпретации

Numerator — число подтверждений, denominator — число открывших, но оба значения имеют смысл только вместе с правилом inclusion. Cohort здесь означает вариант сравнения, attribution связывает подтверждение с попыткой, а guardrail описывает недопустимое ухудшение рядом. Эти термины не доказывают причинность: они лишь делают видимыми условия, без которых ratio отвечает на другой вопрос.

import { createFixedProductMetricInput, inspectFixedProductMetric, prepareFixedProductDecision } from './upgrade-2025-07.mjs';

const report = inspectFixedProductMetric(
  createFixedProductMetricInput('fixed-wrong-denominator-v1'),
);
const decision = prepareFixedProductDecision(report);

console.log({ accepted: report.accepted, reasons: report.reasons, status: decision.status });
// Expected: wrong-denominator and stop-before-product-decision.
// The input is fixed synthetic data in memory; no metric is sent or published.

Этот пример не вычисляет «правильную conversion» задним числом. Он показывает, что имя метрики не переносится на другой denominator. Report с all-events получает stop до human decision, хотя набор событий внешне похож на valid case. Для реального расчёта отдельно нужны randomization, задержка доставки, политика идентификаторов и проверка pipeline.

Порядок проверки сравнения

  1. Назвать decision. Сформулировать, какое действие будет разрешено или остановлено, а не просто открыть dashboard.
  2. Зафиксировать population. До запроса записать cohort, period, inclusion и attribution.
  3. Разложить дробь. Показать numerator и denominator отдельно и проверить, что они относятся к одной задаче.
  4. Положить рядом guardrail. Сравнить его по тому же окну и назвать владельца порога.
  5. Вернуть HOLD при разрыве. Repair contract предшествует product discussion.

Все события, варианты, результаты и решения ниже — fixed synthetic JS literals. Модуль не читает файлы, сеть, clock, telemetry, Git, CI, production или user data и не выполняет side effect.

Почему guardrail живёт рядом, а не в конце отчёта

Guardrail не обязан быть «самой важной» метрикой. Его работа проще: заранее назвать ухудшение, которое делает локальный выигрыш недостаточным. В synthetic наборе один render_failed у двух opened в control не создаёт сравнения для реального продукта. Он показывает контракт: failure имеет тот же cohort и тот же denominator base, поэтому его нельзя потерять при смене панели. В реальном проекте порог и owner определяются до запуска, а не после удачного результата.

Работа Safe Velocity описывает guardrail как показатель, который не должен ухудшаться при rollout, и local metric как средство объяснить изменения. Нельзя перевернуть эту фразу в гарантию: если local metric вырос, значит outcome улучшился. Между ними остаются выборка, вариант, сезонность, качество событий и другие механизмы. Поэтому автор оставляет человеческое решение последним шагом и требует доказательства, достаточного для конкретного риска.

Разбор numerator и denominator

Работа Microsoft о metric pitfalls особенно полезна именно здесь: она показывает пример, где другой состав наблюдений делает delta ненадёжной, и предлагает декомпозицию numerator и denominator. Наше практическое следствие скромнее: вместе с числом хранить список правил, из которого оно получено. Если после изменения request path исчезла часть opened, alert должен говорить о denominator, а не радоваться conversion.

Проверка в модуле добавляет один confirm из следующего дня. Результат mixed-cohort-or-period останавливает расчёт до сравнения. Это не статистический тест и не защита от всех ошибок: код не проверяет рандомизацию, задержку доставки или личность subject. Зато он делает распространённую подмену видимой и не позволяет default-фильтру quietly собрать удобную выборку.

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

Не делайте из guardrail универсальный список. У одной операции критичен отказ, у другой — отмена, доступность или безопасность; метрика получает смысл только рядом с пользовательским решением и владельцем риска. Следующий шаг: возьмите одну ratio из своего dashboard, напишите её numerator и denominator словами, затем подайте в test события из другого периода. Ожидаемый результат — расчёт остановлен с причиной, которую может исправить конкретный owner.

Историческая граница июля 2025

Microsoft Research PDF 2017 года использован для риска sample/metric mismatch, а работа 2019 года — для ролей local, success и guardrail. OpenTelemetry v1.31.0 закреплён commit от марта 2025. Они не доказывают причинность fixed example и не задают пороги. Структура decision record и её stop reasons — ограниченный проектный выбор автора.

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

  • OpenTelemetry Semantic Conventions v1.31.0, events (immutable commit c01aa89, 11 March 2025) — версия: tag v1.31.0; immutable commit c01aa89d9a13042e56536c60975139c50e764796, 2025-03-11. Событие имеет уникальное имя; структура события и применимые attributes должны быть документированы, а dynamic values не должны становиться частью имени. Граница: Это соглашение о семантике telemetry. Оно не определяет продуктовую метрику, causal effect, выбор denominator или критерий ship.
  • Microsoft Research: Safe Velocity with Controlled Rollouts (ICSE-SEIP 2019) — версия: ICSE-SEIP 2019 author version, published 2019; HTTPS checked 2026-07-31. Работа различает local feature, success и guardrail metrics; guardrail нужен, чтобы выпуск не ухудшал важные показатели, а local metric помогает объяснить движение более общей метрики. Граница: Это описание controlled rollouts Microsoft. Оно не доказывает, что любое изменение local metric вызвало пользовательский результат в другом продукте.
  • Microsoft Research: A Dirty Dozen Metric Interpretation Pitfalls (KDD 2017) — версия: KDD 2017 author version, published 2017; HTTPS checked 2026-07-31. Работа показывает, что разные наборы наблюдений в treatment и control делают metric delta недостоверной; рекомендует разбирать numerator и denominator и отслеживать telemetry loss. Граница: Пример относится к controlled experiments. Он не заменяет дизайн эксперимента, расчёт мощности, privacy policy или проверку конкретного pipeline.