Интервалы гистограммы Prometheus для API, которые может прочитать команда
Бакеты гистограммы Prometheus для API работают лучше всего, когда они совпадают с ожиданием пользователей, а каждый график отвечает на один понятный вопрос.

Почему графики задержки API путают команды
Большинство графиков задержки API выглядят перегруженно, но говорят очень мало. Во время инцидента кто-то открывает дашборд, видит скачущие столбики и процентили и всё равно не может ответить на простой вопрос: ждут ли пользователи уже достаточно долго, чтобы это заметить? Если график не может ответить быстро, он добавляет стресс вместо пользы.
Обычно проблема проста. Команды оставляют стандартные бакеты гистограммы Prometheus, даже когда их границы не совпадают с реальным терпением пользователей. Человек, который пользуется поиском, часто начинает замечать задержку где-то на 300–500 мс. Пользователь, который ждёт оформления заказа или входа, может потерпеть чуть дольше, но 2 секунды всё равно ощущаются медленно. Если ваши бакеты прыгают с 1 секунды сразу на 2,5 секунды, вы теряете разницу между «чуть медленно» и «люди могут уйти».
Становится ещё хуже, когда один бакет поглощает слишком много запросов. Представьте API, где большинство медленных вызовов попадает в диапазон от 1 до 2,5 секунды. На графике виден один большой бакет, но он скрывает историю. Задержка сместилась с 1,1 секунды до 1,4? Неприятно, но, возможно, не срочно. Она сдвинулась с 1,8 до 2,4? Это уже может ударить по конверсии. График делает оба случая одинаковыми.
После этого начинаются догадки. Люди говорят, что API «кажется медленнее», и начинают проверять случайные сервисы, кеши или базы данных.
Читаемый график подсказывает одно действие:
- «Поиск превысил 500 мс для многих пользователей после последнего деплоя. Проверьте новый путь запроса».
- «Оформление заказа остаётся ниже 1 секунды, значит, замедление, скорее всего, не в этом API».
В этом и есть задача графика. Под давлением никто не хочет разбирать математику бакетов или спорить о том, важен ли всплеск p95. Нужна картинка, которая соответствует времени ожидания пользователя и подсказывает следующую проверку.
Хорошие графики задержки специально остаются простыми. Они не пытаются показать всю правду о системе. Они отвечают на один операционный вопрос за раз и делают замедление очевидным ещё до того, как команда потеряет час, гоняясь за не той проблемой.
Начните с ожидания, которое пользователь может почувствовать
Пользователям не важны ваши бакеты. Им важно, сколько времени ощущается действие. Запрос на поиск и ежемесячный экспорт могут оба возвращать 200 OK, но люди оценивают их по разным часам.
Начните с группировки эндпоинтов по действию, которое за ними стоит. Вход, живой поиск и шаги оформления заказа находятся в одной ментальной зоне с нажатием кнопки. Пользователи ожидают, что они будут быстрыми. Экспорт отчёта, импорт файла или синхронизация счёта ощущаются тяжелее, особенно если продукт показывает прогресс.
Простая сетка временных порогов работает лучше, чем копировать пример бакетов Prometheus из статьи:
- мгновенно
- нормально
- раздражает
- слишком медленно
Точные числа зависят от продукта. Для поиска «раздражает» может начинаться примерно с 300 мс. Для оформления заказа — ближе к 1 секунде. Смысл не в том, чтобы найти идеальные универсальные значения. Смысл в том, чтобы привязать границы бакетов к ожиданиям, которые реальные пользователи действительно замечают.
Выбирайте границы бакетов по шагам
Начните с одной группы эндпоинтов, а не со всего API. Объединяйте маршруты по тому, что чувствует пользователь. Запросы поиска могут использовать один набор бакетов, а оформление заказа или экспорт файла — другой.
Определите самое медленное время ответа, которое вы всё ещё готовы принять для этой группы. Пусть это будет число, которое человек действительно заметит, а не просто красивое значение на графике. Для поиска комфортным пределом может быть 300 мс. Для шага оплаты — 1,5 секунды.
Это число и есть ваша опора. Оно даёт бакетам гистограммы Prometheus понятную задачу: показать, сколько трафика остаётся ниже порога, как часто запросы к нему приближаются и сколько из них его превышают.
Расставьте бакеты вокруг этой опоры простым способом. Поставьте несколько более плотных бакетов ниже порога, чтобы небольшие регрессии не исчезали. Если опора — 300 мс, хорошо работают бакеты 50, 100, 150, 200 и 300 мс. Затем добавьте несколько более широких бакетов выше, чтобы показать длинный хвост. Для того же эндпоинта 500 мс, 1 секунда и 2 секунды часто рассказывают гораздо более понятную историю, чем дюжина крошечных делений.
Общее количество держите умеренным. Обычно 7–10 бакетов на группу эндпоинтов вполне достаточно. Больше — и график начинает превращаться в шум.
Меньшие бакеты ниже опоры помогают заметить дрейф заранее. Если поиск раньше собирался в районе 80–120 мс, а теперь всё больше запросов попадает в диапазон 150–200 мс, вы увидите это ещё до жалоб пользователей.
Более широкие бакеты выше опоры отвечают на другой вопрос. Они показывают, есть ли у вас редкие, но болезненные медленные запросы. Резкий рост трафика с 1 секунды до 2 секунд часто указывает на таймаут, проблему зависимого сервиса или запрос, который нужно доработать.
Не пытайтесь всё переоптимизировать в первый день. Погоняйте бакеты неделю, а потом снова посмотрите на форму. Если почти каждый запрос попадает в один или два бакета, раздвиньте их. Если несколько бакетов пустуют всю неделю, уберите их. Хорошие границы бакетов должны делать график читаемым за десять секунд, даже во время инцидента.
Сделайте так, чтобы каждый график отвечал на один вопрос
График не работает, когда людям нужна длинная лекция, прежде чем они смогут его использовать. Если одна панель смешивает эндпоинты, процентили и заметки о деплое, никто не понимает, что делать дальше. Хорошие бакеты гистограммы Prometheus помогают, но у графика всё равно должна быть одна понятная задача.
Ждут ли пользователи слишком долго прямо сейчас?
Одна панель должна отвечать именно на этот вопрос и ни на какой другой. Выберите пользовательский порог и покажите, сколько запросов остаётся ниже него. Для поиска это может быть 300 мс. Для оформления заказа — 1 секунда.
Такой вид показывает команде, чувствуют ли люди задержку прямо сейчас. На него проще реагировать, чем на панель, перегруженную средними значениями и линиями p95. Среднее может выглядеть нормально, пока болезненный длинный хвост растёт на заднем плане.
Держите эту панель узкой. Используйте одну группу эндпоинтов, один порог и короткий временной интервал. Если после обеда линия падает, дежурный должен за несколько секунд понять, что пользователи теперь ждут слишком долго.
Изменил ли деплой форму?
Для этого нужен другой график. Сравните одну и ту же группу эндпоинтов до и после релиза. Если больше запросов переходит в более медленные бакеты гистограммы, деплой, скорее всего, изменил поведение, даже если среднее почти не сдвинулось.
Затем используйте ещё одну панель, чтобы понять, какая группа эндпоинтов не уложилась в порог. Не смешивайте поиск, вход, оформление заказа и загрузки в одну линию, если команда не будет реагировать на них как на единое целое. Большинство команд так не работает. Им нужно видеть, какая группа сломалась первой.
Именно здесь многие графики задержки в Prometheus идут не туда. Одна панель пытается ответить сразу на три вопроса: видят ли пользователи задержку, вызвал ли её деплой и какой участок API сломался. В итоге это обычно превращается в шум.
Разделяйте панель, когда это происходит. Небольшие графики с одной задачей проще читать, проще обсуждать и гораздо быстрее использовать во время инцидента. Если график не ведёт к следующему шагу, ему нужен меньший охват.
Простой пример с checkout и search
Search и checkout почти никогда не требуют одинакового взгляда на задержку. От поиска пользователи ждут почти мгновенной реакции. Checkout получает немного больше времени, потому что там часто загружаются цены, остатки, адреса, налоги и шаги оплаты.
Эта разница должна влиять на ваши бакеты гистограммы Prometheus. Если использовать один набор бакетов для обоих случаев, график перестанет помогать. Search будет выглядеть нормально, хотя уже раздражает, а checkout будет шумным, не показывая, где именно начинается реальная задержка.
Для search держите большинство бакетов в первой половине секунды. Набор вроде 50 мс, 100 мс, 200 мс, 300 мс, 500 мс, 750 мс, 1 секунда и 2 секунды даёт команде понятный обзор диапазона, который люди действительно чувствуют. Если бакеты 300–500 мс начинают заполняться, следующий шаг очевиден: проверьте время запроса, промахи кеша или медленный вызов во внешний сервис.
Checkout нужно больше пространства. Набор вроде 200 мс, 500 мс, 1 секунда, 1,5 секунды, 2 секунды, 3 секунды, 5 секунд и 8 секунд работает лучше, потому что показывает, остаётся ли поток комфортно ниже 2 секунд или уходит в более медленные диапазоны. Когда растут бакеты 3 и 5 секунд, команда понимает, куда смотреть дальше: задержка платёжного провайдера, расчёт налогов, проверка остатков или медленная запись в базу.
Теперь сравните это с общим набором бакетов вроде 100 мс, 500 мс, 1 секунда, 2 секунды и 5 секунд. Он размывает обе истории. Search теряет детали как раз там, где люди замечают лаг. Скачок с 120 мс до 420 мс ощущается плохо, но график прячет его внутри одного широкого бакета. У checkout противоположная проблема. Всё, что дольше 2 секунд, попадает в широкий хвост, и вы не понимаете, ждут пользователи 2,2 секунды или 4,8.
Каждый график должен отвечать на один операционный вопрос:
- Search: «Не ушёл ли search за тот момент, когда пользователи начинают чувствовать задержку?»
- Checkout: «Какая часть checkout загоняет запросы за допустимое время ожидания?»
Если график не подсказывает следующий шаг, это просто украшение. Хорошие бакеты задержки API не только описывают время. Они говорят команде, что проверять дальше.
Что строить в повседневной работе
Ежедневный дашборд должен быстро отвечать на несколько простых вопросов. Пользователи ждут дольше? Изменился ли трафик? Запросы медленные или они падают с ошибкой? Если один график не отвечает на понятный операционный вопрос, он обычно становится просто картинкой на стене.
Начните с процентилей для пользовательской задержки во времени. Используйте p50, чтобы увидеть обычный случай, p95 — чтобы следить за более медленным краем, которого ещё достигает большинство пользователей, и p99 — чтобы поймать неприятный хвост. Средние значения скрывают слишком много. Они остаются спокойными, пока небольшая доля запросов становится мучительно медленной.
Держите эти процентили отдельно по группам эндпоинтов. Сравнивайте search с search, checkout с checkout, login с login. Если вы строите график всего API сразу, быстрые и шумные эндпоинты могут скрыть меньшую, но более болезненную задержку где-то ещё.
Поставьте частоту запросов рядом с задержкой, а не на другом экране. Когда p95 скачет одновременно с удвоением трафика, первая догадка — нагрузка, а не плохой код. Если частота запросов стоит на месте, а задержка растёт, вероятнее деплой, изменение запроса или медленная зависимость.
Разделяйте ошибки и медленные успешные запросы. Это важнее, чем думают многие команды. Всплеск быстрых 500-х может сделать задержку лучше на вид, потому что упавшие запросы завершаются быстро. Держите один график задержки для успешных ответов и отдельный график ошибок.
Когда процентиль выглядит странно, откройте бакеты гистограммы Prometheus, которые за ним стоят. По счётчикам бакетов видно, где запросы начали скапливаться. Если p95 checkout смещается с 400 мс до 1 секунды, посмотрите на значения около 500 мс и 1 секунды. Так можно понять, сдвинулась ли большая часть трафика немного или меньшая группа застряла далеко в хвосте.
Для повседневной работы достаточно небольшого набора графиков:
- p50, p95 и p99 для успешных запросов по группам эндпоинтов
- частота запросов для той же группы эндпоинтов
- уровень ошибок, разделённый по классу статуса или типу таймаута
- один вид бакетов для самого загруженного или самого чувствительного эндпоинта
Такой набор остаётся читаемым. Он также делает бакеты задержки API более надёжными, потому что каждый график отвечает на один вопрос и подсказывает, куда смотреть дальше.
Ошибки, которые тратят время впустую
Частая ошибка — скопировать значения бакетов у другой команды и считать, что они подходят вашему API. Обычно это не так. График, который имеет смысл для высоконагруженного сервиса входа, может быть бесполезен для более медленного админского эндпоинта или API поиска с другими ожиданиями пользователей.
Границы бакетов должны соответствовать задержкам, которые люди действительно чувствуют в вашем приложении. Если пользователи замечают паузу примерно на 300 мс, а ваш график прыгает с 100 мс сразу на 1 секунду, вы теряете важную детализацию.
Команды также тратят время, когда навязывают один набор бакетов всем эндпоинтам. Поиск, checkout, загрузка файлов и фоновая синхронизация живут на разных часах.
Слишком много крошечных бакетов тоже создают проблемы, особенно при низком трафике. Набор вроде 5 мс, 10 мс, 15 мс и 20 мс выглядит точным, но низкий объём превращает эту точность в шум. В итоге вы смотрите на пустые или почти не меняющиеся бакеты и пытаетесь прочитать историю, которой там нет.
Интервал опроса Prometheus и объём выборки важнее, чем думают многие команды. Если Prometheus собирает метрики каждые 30 секунд, а эндпоинт получает всего несколько запросов в минуту, короткие временные окна могут ввести в заблуждение. График может выглядеть чётким и подробным, но опираться будет на очень маленькое число запросов.
Проверьте количество запросов, прежде чем доверять форме графика задержки. Если за окно попало лишь несколько запросов, более широкие бакеты и более длинный диапазон обычно показывают правду лучше.
Средние значения тратят ваше время, когда длинный хвост задержки бьёт по пользователям. Эндпоинт может показывать спокойное среднее, а небольшая доля запросов будет сильно тормозить из-за медленного запроса, холодного старта или цикла повторных попыток. Пользователи не живут в среднем значении. Они чувствуют тот запрос, который заставил их ждать.
Если checkout в среднем занимает 180 мс, но каждый двадцатый запрос длится 2,5 секунды, среднее создаёт ложное чувство спокойствия. Более полезный график показывает, где скапливаются эти медленные запросы и растёт ли эта куча.
Полезное правило простое: каждый график задержки должен отвечать на один операционный вопрос. Если график не может сказать вашей команде, ждут ли пользователи слишком долго именно на этом эндпоинте прямо сейчас, измените бакеты или уберите график.
Быстрые проверки перед тем, как оставить график
Оставляйте панель только если кто-то в команде может быстро её прочитать и действовать по ней. Если людям нужна пяти минутная лекция, график ещё не готов для дашборда.
Панель, построенная на бакетах гистограммы Prometheus, должна пройти короткий тест за столом. Откройте её, покажите на неё и спросите коллегу: «На какой вопрос отвечает этот график?» Если он отвечает «общая задержка» или «состояние системы», это слишком расплывчато. Хороший ответ звучит скорее так: «Удерживаются ли запросы checkout ниже 1 секунды для большинства пользователей?» или «Усложнился ли search настолько, что пользователи это заметят?»
Границы бакетов должны совпадать с реальным терпением, а не с какими-то значениями, которые когда-то стояли в старой конфигурации. Если пользователи начинают чувствовать задержку около 300 мс, 1 секунды и 2 секунд, именно эти пороги и должны быть на графике. Если ваша цель по сервису — 500 мс для p95, покажите бакет рядом с этой линией. График с подписями вроде 0,384 или 6,144 секунды математически может быть корректным, но большинство команд всё равно будет гадать.
Есть ещё один очень важный тест: график должен меняться ещё до того, как всё станет явно плохо. Если задержка выросла с 220 мс до 350 мс, а график почти не изменился, ваши бакеты слишком широкие. Нужен ранний сигнал, а не всплеск уже после того, как пользователи начали раздражаться.
Короткая проверка обычно быстро показывает слабые панели:
- Спросите одного коллегу, какое решение поддерживает эта панель.
- Проверьте, совпадает ли каждый порог с временем ожидания пользователя или целевым SLO.
- Повторите недавнее замедление и посмотрите, меняется ли график достаточно заметно.
- Посмотрите на подписи и спросите не специалиста, что они значат.
- После одного взгляда назовите следующий сервис или эндпоинт, который вы бы проверили.
Последний пункт особенно важен. Полезный график сужает поиск. Если панель говорит «search стал медленным для запросов длиннее 1 секунды», следующий шаг очевиден. Если она говорит только «задержка какая-то странная», это просто шум.
Оставляйте тот график, который помогает уставшему коллеге сделать следующий шаг за десять секунд.
Что делать дальше
Выберите одну загруженную группу эндпоинтов и исправьте её первой. Search, login и checkout обычно хорошо подходят, потому что ими пользуются весь день и задержку там чувствуют быстро. Если ваши бакеты гистограммы Prometheus всё ещё взяты из шаблона по умолчанию, перестройте их от времени ожидания, которое человек может заметить, а не от круглых чисел, которые просто хорошо смотрелись в конфиге.
Хорошая отправная точка — поставить больше бакетов там, где люди начинают чувствовать трение. Для многих API это означает более плотные шаги ниже 1 секунды и меньше шагов после неё. Практичный набор может выглядеть так:
- 100 мс, 200 мс, 300 мс, 500 мс
- 750 мс, 1 секунда, 1,5 секунды, 2 секунды
- 3 секунды и 5 секунд только если пользователи действительно так долго ждут
Потом посмотрите на полный объём трафика за неделю. Не делайте выводы по одному загруженному часу. Если несколько бакетов всю неделю пустуют, уберите их. Если два соседних бакета всегда двигаются вместе, оставьте один, а второй удалите. График должен читаться за несколько секунд.
У каждой панели должна быть одна задача. Запишите эту задачу в заголовок или описание дашборда в виде простого вопроса. «Удерживаются ли запросы checkout ниже 1 секунды почти для всех?» — хороший вариант. «Замедлился ли search после последнего деплоя?» — тоже хороший. Это маленькое изменение помогает людям перестать смотреть на графики задержки в Prometheus и спорить о том, что они значат.
Одна привычка помогает сильнее, чем ожидают многие команды: связывайте график с решением, которое он должен запустить. Если ответ «нет», кто-то должен понимать, что проверять дальше — например, медленный запрос в базу, промах кеша или шумный downstream-сервис.
Если вам нужен внешний взгляд, Oleg Sotnikov на oleg.is работает со стартапами и небольшими командами над наблюдаемостью API, инфраструктурой и поддержкой Fractional CTO. За годы он строил лёгкие production-системы, поэтому советы обычно остаются практичными и близкими к тому, что команда действительно может поддерживать.
Часто задаваемые вопросы
Почему стандартные бакеты Prometheus путают команды?
Бакеты по умолчанию редко совпадают с тем, как долго пользователи готовы ждать. Когда один широкий бакет охватывает 1–2,5 секунды, график скрывает, стала ли задержка немного хуже или уже дошла до уровня, который люди замечают. Из-за этого инциденты разбираются медленнее, а команда смотрит не туда.
Как выбрать первую границу бакета?
Начните с самого медленного времени ответа, которое вы всё ещё считаете приемлемым для этой группы эндпоинтов. Если поиск должен ощущаться нормальным до 300 мс, поставьте несколько бакетов ниже 300 мс и несколько более широких выше, чтобы видеть и маленький дрейф, и неприятный длинный хвост.
Нужно ли всем эндпоинтам использовать одни и те же бакеты?
Нет. Поиск, вход, оформление заказа и экспорт работают по разным ожиданиям пользователей. Дайте каждой группе эндпоинтов бакеты, которые соответствуют самому действию, иначе график размоет именно ту часть, которую люди действительно чувствуют.
Сколько бакетов мне нужно?
Лучше ориентироваться примерно на 7–10 бакетов для одной группы эндпоинтов. Обычно этого достаточно, чтобы заметить дрейф, и при этом панель не превращается в шум.
Что должен показывать один график задержки?
Сделайте так, чтобы каждая панель отвечала на один вопрос, например: «Удерживается ли время ответа поиска ниже 300 мс прямо сейчас?». Когда один график пытается одновременно объяснить задержку, влияние деплоя и проблемные области, люди только теряют время на споры.
Достаточно ли одних процентилей?
Нет. Для быстрого просмотра используйте p50, p95 и p99, а когда процентиль резко меняется, открывайте бакеты гистограммы. По ним видно, где начали скапливаться запросы, а значит, это были либо общие небольшие сдвиги, либо небольшой кусок трафика, который сильно замедлился.
Стоит ли строить графики и по средним значениям?
Не стоит полагаться на средние значения, когда пользователям больно. API может показывать среднее 180 мс, но каждый двадцатый запрос будет идти 2,5 секунды, и именно такие запросы люди запоминают.
Что делать с эндпоинтами с низким трафиком?
Сначала проверьте количество запросов, прежде чем доверять форме графика. Когда трафика мало, а Prometheus опрашивает метрики каждые 30 секунд, маленькие бакеты и короткие окна создают ложную точность. Лучше использовать более широкие бакеты и более длинный диапазон, чтобы график отражал реальный трафик.
Как понять, что настройка бакетов работает?
Погоняйте бакеты примерно неделю и посмотрите на форму. Если почти всё попадает в один или два бакета, раздвиньте их. Если несколько бакетов всю неделю пустуют, уберите их, чтобы график оставался простым для чтения.
Что исправить первым, если графики выглядят беспорядочно?
Сначала выберите одну загруженную группу эндпоинтов, например search или checkout, и перестройте бакеты от времени ожидания пользователей, а не от шаблонных значений. Потом переименуйте панель в простой вопрос и привяжите её к следующей проверке, например к времени запроса, промахам кеша или задержке платежа. Если нужен второй взгляд, можно записаться на консультацию к Oleg Sotnikov.