DarkRiDDeR12 мин

SLI без декоративной метрики: минимальный договор пути пользователя

НадёжностьНаблюдаемость

Проблема начинается не с отсутствия графика. График обычно уже есть: процесс отвечает, балансировщик отдаёт коды, на панели горит хороший процент. Но пользовательский путь «отправить заказ» может останавливаться после принятого HTTP-запроса, а этот процент продолжает выглядеть спокойно. Команда видит число, но не знает, чью работу оно представляет. Цена ошибки — релизное решение принимают по декоративной метрике: исправляют не тот участок, спорят о «доступности» и не могут показать, какое условие действительно важно пользователю.

Быстрый ремонт обычно звучит так: возьмём все ответы без 5xx, назовём их успехом и поставим цель 99,9%. Это не договор, пока не названы путь, знаменатель, исключения, окно и владелец. Одно и то же значение будет честным для API-приёма заказа и бесполезным для завершённого checkout. Цена второй ошибки — не выдуманный инцидент и не обещанный downtime. Это потеря причины: в следующий раз команда снова будет выяснять, какие события вообще считает и почему один участник исключил отмену клиента, а другой — нет.

Сначала вопрос пользователя, затем SLI

SLI — service level indicator, количественная мера выбранного свойства сервиса. SLO — цель этой меры в оговорённых условиях. Эти определения были опубликованы в Google SRE Book в 2017 году. Для практики важнее порядок: не спрашивать «какие метрики уже экспортируются», а закончить фразу от имени пользователя. Например: «после подтверждения формы checkout получает осмысленный ответ о приёме запроса». Это ещё не готовый SLI, но уже ограничивает маршрут, а не весь набор сервисных счётчиков.

Дальше разбираем путь на события, которые можно проверить. В знаменатель входят только завершённые попытки выбранного маршрута. Числитель — подмножество этих попыток, для которых заранее назван хороший результат. Событие, которое не дошло до точки измерения, нельзя бесшумно считать и успехом, и ошибкой: его правило должно быть записано отдельно. В учебном контракте ниже отмена до отправки запроса исключена. Это не рекомендация для каждого продукта, а пример того, как исключение перестаёт быть скрытым допущением.

Минимальный договор для одного учебного пути
Часть договораТочное значение в учебной моделиЗачем это нужноЧего из этого нельзя вывести
Путьsynthetic-checkout-submitне смешивать checkout с любым HTTP-трафикомчто такой маршрут есть в production
Знаменательsynthetic-checkout-request-finishedвидеть все завершённые попытки выбранной границыреальное число запросов или пользователей
Хороший исходsynthetic-checkout-response-non-5xxотделить правило успеха от кода графикафактическую доступность или корректность заказа
Исключениеsynthetic-client-cancel-before-requestсделать границу спора явнойчто отмены можно не учитывать в чужом сервисе
Окно и владелецsynthetic-four-week-window-A; synthetic-checkout-ownerназвать срок сравнения и того, кто принимает решениеправо автоматически выпускать или блокировать изменение
Учебный SLI-контракт: путь synthetic checkout ограничивает множество eligible событий; good events являются его подмножеством, а отдельное исключение названо явно. Рядом стоят окно, целевое значение и synthetic owner.
Схема показывает структуру договора до запроса к мониторингу. Это не дашборд, не реальный SLI и не измерение доступности, инцидента или burn rate.

Почему uptime процесса часто декоративен

Процесс может быть жив, а пользовательская операция — нет. Обратная ситуация тоже возможна: один backend ответил ошибкой, но продукт показал пользователю допустимый fallback. Поэтому «uptime» без объекта измерения нельзя автоматически переименовать в SLI. Он может быть полезен для диагностики конкретного компонента, но вопрос «успел ли пользователь сделать нужное действие?» остаётся отдельным. В Google SRE Book прямо различаются пользовательски важная мера и доступный proxy; proxy надо называть proxy, а не выдавать за прямой пользовательский результат.

Окно и цель принадлежат договору

Окно измерения не является оформлением графика. В Example SLO Document Google SRE Workbook от 19 февраля 2018 года показано четырёхнедельное rolling window; это хороший пример того, что окно записывают вместе с SLI. В нашем fixture есть другое, намеренно фиксированное учебное окно 28 дней. Не переносите его в проект автоматически: для редких операций, сезонного трафика, пакетной обработки или юридического SLA могут понадобиться другая граница и отдельное решение владельцев.

Цель также не берут из текущего красивого значения. Сначала продукт, разработка и эксплуатация называют ожидаемую ценность пути, стоимость деградации и границу измерения. Затем выбирают достижимый target и правило пересмотра. Цель 100% fixture отвергает не потому, что любая система не может иметь жёсткого требования, а потому, что этот маленький пример учит явно отличать цель от бесконечного обещания. Реальный выбор всё равно требует контекста и согласования.

Исполнимый synthetic fixture проверяет форму, а не систему

Fixture хранит входные объекты прямо в модуле и принимает только полный явно названный набор synthetic полей. Он собирает один договор: путь, окно, определение good/eligible, target, owner и две synthetic счётные величины. Затем он отвергает неотмеченный вход, лишнее или пропущенное поле, чужую область, другое окно, размытый индикатор, невозможную цель и отсутствующий знаменатель. Так можно проверить, что review не потерял поле договора ещё до настройки реального monitoring.

import { runSloFixture } from './upgrade-2023-10.mjs';

const report = runSloFixture();
if (!Object.values(report.assertions).every(Boolean)) throw new Error('fixture failed');

console.log(report.samples.valid.decision.releaseAuthority); // not-granted
console.log(report.samples.valid.calculation.observed); // not-observed

// Полный synthetic вход и отрицательные ветки находятся в этом же модуле.
// Нет чтения проекта, monitoring, CI, сети, real SLI, incident, burn rate или availability.

node web/scripts/upgrade-2023-10.mjs --verify-fixture

# PASS подтверждает только согласованность synthetic договора и его отрицательных веток.

PASS здесь означает только: учебный объект непротиворечив и отрицательные ветки сработали. Он не читает репозиторий, не подключается к monitoring, не запускает CI, не вызывает сеть и не знает, существуют ли реальные события. `syntheticGoodCount=994` и `syntheticEligibleCount=1000` — числа для арифметики fixture, не измерение traffic, availability, SLI, incident или burn rate. Поле `releaseAuthority=not-granted` специально не позволяет прочитать вывод как разрешение на изменение.

Маршрут: симптом → причина → проверка → действие

  1. Симптом. На панели есть процент, но при вопросе «какой пользовательский путь он покрывает?» команда называет разные ответы.
  2. Причина. Источник событий, знаменатель, good outcome, исключения, окно и owner появились в разных местах: запросе, dashboard и устной договорённости.
  3. Проверка. На одном пути составьте таблицу из пяти строк. Для одного good, одного bad и одного спорного события укажите: входит ли оно в знаменатель, почему и где это можно проверить.
  4. Проверка границы. Отдельно назовите proxy. Если measure стоит на backend, а ценность происходит в клиентском сценарии, запишите расхождение и не называйте proxy прямой доступностью пользователя.
  5. Действие. Сохраните короткий SLI-contract рядом с owner, window, target и методом пересмотра. Сначала стабилизируйте определения, затем строите query и alert.
  6. Следующий контроль. В разрешённой среде получите evidence для трёх примеров и проверьте, что одинаковая формула используется в отчёте и в релизном обсуждении.

Rollback возвращает текст договора, не данные

Если формула оказалась неверной, первым обратимым действием будет вернуть предыдущую версию договора и пометить новую как неутверждённую. Это не значит «удалить метрики»: до такой команды надо знать backend, retention, права, потребителей alert и факт уже выполненного rollout. Учебный `rollbackSyntheticSloContract()` возвращает только snapshot пяти полей и прямо сообщает `monitoring=not-touched`, `ci=not-touched`, `network=not-used`. Он полезен тем, что не маскирует отсутствие операционного плана.

В настоящем изменении rollback должен содержать версию правила, владельца, условие возврата и способ проверить, что новый расчёт больше не используется. Если этого нет, не добавляйте к дашборду ещё один процент. Сначала сузьте изменение до одного пути и одного места измерения. Для автора уровня M6 это не бюрократия: это способ не выдать красивую визуализацию за доказательство пользовательского результата.

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

В статье нет production-данных, настоящего SLI, availability, incident, burn rate, alert, dashboard, SLO compliance, traffic или реальной стоимости простоя. Нет чтения проекта, файлов, часов, monitoring, CI, сети, HTTP, SDK и конфигурации. Внешние источники объясняют исторические термины и форму документов, но не назначают формулу, target или policy конкретной команде. Даже корректный SLI-contract не показывает причину ухудшения: для этого понадобится отдельный диагностический сигнал.

Следующий шаг — выбрать один действительно ценный путь и провести короткий review с его владельцем. Результатом должен стать не скриншот, а запись: scope, eligible event, good event, исключения, окно, источник, target, owner, способ пересмотра и известный proxy-gap. Только после этого имеет смысл обсуждать dashboard и error budget. Если любой из пунктов неизвестен, честный статус — «договор не готов», а не «метрика зелёная».

Историческая граница октября 2023

К концу октября 2023 уже существовали использованные здесь первичные материалы Google: SRE Book с copyright 2017 и SRE Workbook с документами 2018 года. Они обосновывают термины SLI, SLO, окно и policy, но не делают эту учебную схему историческим production-кейсом автора. В тексте нет более позднего инструмента и нет утверждения, что любой backend уже реализует эти правила.

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

  • Google SRE Book: Service Level Objectives, copyright 2017 — Первичный материал Google SRE: определяет SLI как количественную меру, SLO как целевое значение или диапазон и связывает error budget с решением о риске. Он не задаёт порог, окно, формулу или владельца для конкретного проекта.
  • Google SRE Workbook: Example SLO Document, 19.02.2018 — Официальный пример документа с датой 19.02.2018: в нём есть scope, SLI, SLO и четырёхнедельное rolling window. Это пример формы, а не обязательное окно для любого сервиса.
  • Google SRE Workbook: Example Error Budget Policy, 19.02.2018 — Официальный пример policy: расход бюджета служит правилом приоритизации и не должен быть наказанием. Он не разрешает автоматически блокировать или выпускать чужие изменения.
  • Google SRE Workbook: Alerting on SLOs, copyright 2018 — Официальная глава о том, что alert должен относиться к действенной угрозе бюджету; отдельно разбираются ограничения low-traffic систем. Она не подтверждает реальный burn rate, alert или incident этого учебного пакета.