Наблюдаемость: узнать, что система делает
Логи, метрики и трейсы и что каждый из них отвечает такого, чего не могут остальные; структурное логирование; симптомы против причин; алерты на то, что чувствует пользователь; и SLI, SLO и бюджет ошибок простыми словами.
Прошлый урок закончился предупреждением, которое идеально подходит к этому: очередь прячет отказы. Если воркер рассылки умрёт, никакой ошибки не вернётся, и первым это заметит клиент — тот, от кого ты меньше всего хочешь это услышать. Всё в этом уроке и есть ответ на эту проблему: как работающая система сама рассказывает, что она делает, без того чтобы первым пожаловался пользователь.
Есть три вида телеметрии, и полезнее всего держать их по вопросу, на который каждый отвечает. Метрики — это числа, снятые во времени: запросов в секунду, доля ошибок, возраст очереди, занятая память. Их дёшево хранить и дёшево запрашивать, и только они масштабируются до ответа на вопрос «что-то сейчас не так?». Логи — это отдельные события с деталями: вот этот запрос упал с такой ошибкой, у такого пользователя, в такое время. Они дорогие и только они говорят, чем именно отличался тот единственный запрос, который сломался. Трейсы ведут один запрос через все сервисы, которых он коснулся, записывая, сколько занял каждый шаг, и только они отвечают, куда ушло время.
PILLAR SHAPE ANSWERS COST
metric number over time is it bad, and since when cheap
log event with fields what exactly happened here medium
trace spans with parents where did the 900 ms go sampledТри столпа, вопрос, на который каждый отвечает лучше всех, и цена их хранения.Причина, по которой одни логи не работают, — арифметика, и стоит посчитать её один раз, чтобы число запомнилось. Сорок подов приложения, каждый пишет пятьсот строк в секунду, — это двадцать тысяч строк в секунду. За один час это семьдесят два миллиона строк, а при двухстах байтах на строку — около четырнадцати гигабайт в час, то есть примерно триста гигабайт в сутки. Этого не читает никто. Найти иголку, читая стог, размер которого удваивается, пока ты читаешь, невозможно. Поэтому логи — это хранилище деталей, которое опрашивают с конкретным вопросом в голове, а не то, на что смотрят.
40 pods x 500 lines/s = 20000 lines/s
1 hour = 72 000 000 lines
at 200 bytes each = 14 GB per hour
reading by eye: never
grep across 40 files: minutesПочему никто не смотрит сырые логи и почему ответ — опрашивать их, а не листать.Лекарство для логов — перестать писать предложения и начать писать записи. Неструктурная строка вида «заказ 9001 упал у пользователя 42 через 903 мс» читается человеком и почти бесполезна для машины: чтобы извлечь id заказа, надо написать регулярное выражение, которое сломается в тот момент, когда кто-то поменяет формулировку. Структурная запись пишет каждое значение под именем, поэтому система логов умеет фильтровать по id заказа, группировать по типу ошибки и считать. Освоить это почти ничего не стоит, и это превращает логи из того, что ты читаешь, в то, что ты опрашиваешь. Единственная дисциплина, которая важна, — договориться об именах, потому что user_id в одном сервисе и uid в другом делают соединение невозможным ровно тогда, когда оно нужно.
{
"ts": "2026-10-13T09:14:22.481Z",
"level": "error",
"event": "payment_declined",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"user_id": 42,
"order_id": 9001,
"amount_cents": 1290,
"duration_ms": 903
}Одна строка структурного лога с полями, которые делают её опрашиваемой, и trace id, связывающим её со всем остальным.Различие, которое перестраивает мониторинг, — между симптомом и причиной. Симптом — то, что испытывает пользователь: оформление заказа идёт медленно, вход не работает, страница пустая. Причина — механизм внутри твоей системы: процессор занят на девяносто процентов, блокировка удерживается, пул соединений исчерпан. Причины — то, что можно починить, поэтому люди и ставят алерты на них. Этот инстинкт неверен, и причина в том, что большинство причин безвредны почти всегда. Процессор на девяносто процентов в загруженный день — это хорошо работающая система. Ожидание блокировки в шесть секунд — катастрофа. Числа тут одного рода; только видимый пользователю эффект говорит, на что именно ты смотришь. Алерти на симптом, а причину ищи как объяснение, когда симптом сработал.
Значит, правило такое: буди человека, когда пользователю наносят вред, а всё остальное пусть будет графиком на дашборде или тикетом. Конкретно это означает, что доля ошибок оформления заказа, перевалившая за два процента, стоит того, чтобы кого-то разбудить, а процессор на восьмидесяти процентах — нет, потому что второе может быть совершенно нормальным и уж точно само по себе не значит, что кто-то страдает. Это не вопрос вкуса. Пейджер — это утверждение, что сейчас что-то не так и нужен человек. Если алертить на причины, ты будешь будить людей из-за того, что не сломано, инженеры начнут игнорировать пейджер, и единственный важный алерт будет лежать непрочитанным, пока сайт лежит.
ALERT ON (symptom) DO NOT PAGE ON (cause)
checkout error rate > 2% cpu above 80 percent
p99 checkout latency > 2 s disk above 75 percent
queue age > 5 minutes one pod restarted
login success rate < 99% memory above 70 percent
a cause that hurts nobody pages nobodyЛевый столбец — то, ради чего стоит кого-то будить. Правый — то, что стоит графика на экране.Последняя мысль превращает всё это в число, с которым можно спорить. SLI — это индикатор: доля, которую можно измерить, выраженная как хорошие события, делённые на допустимые события, измеренная в той точке, где её испытывает пользователь. Для оформления заказа это успешные оформления, делённые на все попытки, посчитанные на краю системы, а не внутри какого-нибудь здорового внутреннего сервиса. Точка измерения значит очень много. Сервис может отчитываться о ста процентах успеха, пока балансировщик перед ним уводит в таймаут половину запросов, и увидит это только измерение на краю.
SLI good requests / valid requests
measured at the edge, not inside
SLO 99.9 percent over 30 days
BUDGET
30 days = 43200 minutes
allowed bad = 43.2 minutes
burn 10x = page now
burn 1x = ticket tomorrowАрифметика цели в 99,9 процента на тридцати днях и две скорости выгорания бюджета, на которые стоит реагировать.SLO — это цель для такого индикатора, например 99,9 процента за тридцать дней, а бюджет ошибок — то, что остаётся: количество отказов, которое ты решил терпеть. Тридцать дней — это 43 200 минут, поэтому 99,9 процента оставляют 43,2 минуты допустимой плохости, и это число, которое действительно можно потратить. Бюджет меняет разговоры. Пока он здоров, команда может деплоить быстро и рисковать, потому что бюджет для того и нужен, чтобы его тратили. Когда он почти исчерпан, деплои становятся осторожнее, а когда исчерпан совсем, стандартный ход — заморозить работу над фичами и потратить время на надёжность. Это и есть весь механизм, и он заменяет спор о чувствах решением о числе.
Это и есть ответ на самую старую фразу в программировании. «У меня работает» — это утверждение не про код, а про две разные среды. Продакшн-запрос идёт через другой сетевой путь, другой набор данных, другую конфигурацию и другую одновременную нагрузку. И это проблема измерения, потому что упавший запрос никогда не был зафиксирован с достаточным контекстом для сравнения: какой пользователь, какая версия кода, какая реплика, какая строка в базе. Ответ наблюдаемости — не спорить с этой фразой, а сделать её ненужной. Если каждый запрос несёт trace id и каждая строка лога несёт тот же id, то один пример упавшего запроса из продакшена стоит больше часа попыток воспроизведения, потому что содержит факты, а не гипотезу.
Одно практическое следствие стоит назвать, потому что оно меняет поведение во время инцидента. Первый полезный вопрос — никогда не «что нам изменить», а «что мы знаем». Trace id из жалобы, шаблон упавшего запроса, точный момент, когда это началось, и затрагивает ли это всех или часть: эти четыре факта обычно сужают поиск настолько, что починка становится очевидной. Команды, которые пропускают этот шаг, тратят инцидент на изменения, а это уничтожает улики для следующей попытки разобраться с той же проблемой, и через месяц инцидент повторяется, и никто не может сказать, тот же это или другой.
Практика
Инженер предлагает будить дежурного всякий раз, когда процессор любого сервиса превышает восемьдесят процентов. В чём главная проблема такого алерта?
Подсказки
- Спроси, страдает ли пользователь каждый раз, когда число высокое.
- Алерт, который обычно ни о чём, приучает игнорировать алерты.
- Буди по тому, что чувствует пользователь; разбирайся с тем, что делает машина.
Сопоставь каждый сигнал с тем, на что он хорошо отвечает, и с тем, на что ответить не может.
Подсказки
- Только один из них по средствам хранить для всего и всё время.
- Агрегаты не скажут, какой именно запрос сломался.
- Спроси, какой сигнал ведёт один запрос через границы сервисов.
Реши по одним только измерениям, должна ли эта минута будить человека. Возвращай true, только когда есть симптом, который чувствует пользователь.
Код выполняется у тебя, а не у нас — мы его не запускаем. Проверь решение по каждому требованию и отметь выполненные.
Подсказки
- Высокий процессор или диск сами по себе — причины, а по причинам не будят.
- Видимый пользователю симптом — это доля ошибок или задержка, перешедшая свою черту.
- Возраст очереди важен, только когда вырос за то, что ты обещал.
Вопросы по этому уроку
Это бесплатно?
Да. Первый уровень каждого предмета бесплатный и не требует аккаунта. Дальше уровни и старшие грейды платные — именно это позволяет проекту существовать.
На какой возраст рассчитано?
Для любознательных подростков примерно с 12 лет и для взрослых, начинающих с нуля. Опыт программирования не предполагается: уроки по сетям и физике не требуют математики сверх школьной.
Нужно ли уже уметь программировать?
Нет. Логика, физика и сети начинаются с нуля. Код ты пишешь в разделе языков — и он тоже начинается с самого начала.
Нужно что-то устанавливать?
Нет. Всё работает в браузере: теория, практика и интерактивные симуляции. Скачивать нечего и настраивать нечего.
Сколько времени занимает один предмет?
Урок — от 10 до 15 минут. Грейд «джун» это примерно 12–20 уроков, то есть несколько недель регулярных занятий, а не один вечер.
Обязательно идти по порядку?
Внутри грейда уровни открываются по очереди: каждый опирается на предыдущий. А между предметами ты свободен — начинай с логики, физики или сетей.