Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

Урок 8 из 25 ~16 мин +20 XP

Summary против Histogram

Summary в prometheus считает квантили в самом приложении — задал Objectives, наблюдаешь, получаешь готовые p50, p90, p99 в экспозиции. Звучит как идеал, поэтому summary vs histogram в реальных системах почти всегда заканчивается гистограммой: разбор устройства, погрешности и границы применимости — в этом уроке.

Содержание урока · 10 разделов

Квантиль — это значение, ниже которого лежит заданная доля наблюдений: медиана 0.5 описывает типового пользователя, p99 — худший случай из ста, на котором держатся SLO. Гистограмма из прошлого урока хранит счётчики по бакетам и доверяет подсчёт квантиля серверу Prometheus. Summary переворачивает схему: приложение само ведёт потоковое приближение квантилей и отдаёт в экспозицию готовые числа. Взамен теряет то, за что любят гистограммы, — агрегацию. Квантиль нелинейна: медиана суммы никогда не равна сумме медиан, поэтому две summary с двух инстансов математически нельзя сложить ни в PromQL, ни на бумажке. У каждого типа своя ниша, и пересекаются они меньше, чем кажется на первый взгляд: summary — про точный квантиль одного процесса, histogram — про любой срез по ферме процессов. Отсюда и правило выбора, к которому урок придёт в конце: для HTTP-латентности берут гистограмму почти всегда.

Summary в prometheus: Objectives и экспозиция#

NewSummary принимает SummaryOpts; ключевой параметр — Objectives, карта вида map[float64]float64{0.99: 0.001}. Ключ — целевой квантиль, значение — допустимая погрешность: 0.001 означает, что заявленное число лежит в интервале шириной в две тысячные вокруг истинного квантиля. Чем строже погрешность и больше целей, тем больше памяти на потоковые структуры в процессе — подробнее чуть ниже. Обязательно учитывайте версию библиотеки: в современных client_golang квантили задаются явно, дефолтного набора 0.5, 0.9 и 0.99 давно нет — summary без Objectives экспортирует только sum и count. В экспозиции каждый квантиль выглядит отдельной серией с лейблом quantile="0.99"; сумма и счётчик идут рядом, как у гистограммы, поэтому среднее тоже доступно. Внешне summary почти неотличим от гистограммы без бакетов — различие прячется в том, кто и когда считает квантиль.

Summary с тремя целями

GO
var requestDuration = prometheus.NewSummary(
        prometheus.SummaryOpts{
                Name: "http_request_duration_seconds",
                Help: "Время ответа",
                Objectives: map[float64]float64{
                        0.5:  0.05,
                        0.9:  0.01,
                        0.99: 0.001,
                },
        },
)

// в хендлере или middleware
requestDuration.Observe(elapsed)

Objectives запрашивает три квантиля с разной строгостью: медиане допускаем пять процентов, а p99 — уже тысячную. Погрешность — это ваш выбор и ваше обещание: цифра из дашборда честна только в пределах заявленного интервала. Observe сигнатурно совпадает с гистограммой, поэтому при переезде между типами меняется только объявление метрики.

Экспозиция summary

GO
http_request_duration_seconds{quantile="0.5"} 0.031
http_request_duration_seconds{quantile="0.9"} 0.148
http_request_duration_seconds{quantile="0.99"} 0.402
http_request_duration_seconds_sum 61.8
http_request_duration_seconds_count 2000

Квантили посчитаны на стороне клиента и отдаются готовыми числами; quantile — обычный лейбл, как route у векторов из шестого урока. Сумма 61.8 секунды и 2000 наблюдений дают среднюю 31 мс — sum и count экспортируются всегда, даже без единой цели в Objectives.

Погрешность Objectives и цена точности#

Значение в карте Objectives — это обещание точности, и за него платят памятью процесса. Погрешность 0.05 у медианы означает: заявленное число лежит в интервале плюс-минус пять процентов от истинного квантиля; для p99 те же пять процентов — слишком щедро, поэтому цели обычно сужают с ростом квантиля. Чем больше целей и строже погрешности, тем крупнее внутренние буферы наблюдений, которые summary держит на каждую цель. Практическое правило: не больше трёх-четырёх целей на метрику и только те квантили, что реально рисуются на дашбордах. Квантиль, который никто не смотрит, — это память процесса, потраченная впустую. И помните про версионность: если после обновления client_golang из экспозиции внезапно пропали квантили, проверьте, заданы ли Objectives явно — дефолтного набора в свежих версиях больше нет, а старые туториалы могут показывать иное.

Инцидент: квантиль исчез после обновления#

Инцидент на обновлении зависимости. Команда подняла версию client_golang, сервис перезапустился, панель p99 замолчала: ряды исчезли, алерт по квантилю перестал существовать. Виноват не Prometheus: summary после обновления отдал только sum и count, потому что Objectives в этой версии задаётся явно, а код создавал метрику без карты целей. Никакой ошибки в логах: квантиль, о котором не попросили, не считается — это документированное поведение, а не регресс. Урок шире библиотеки: зависимость от клиентских квантилей — зависимость от настроек кода, которые меняются молча. У гистограммы схожий риск — смена сетки — но разрыв виден на графике, а исчезновение серии — нет. После обновлений клиентских библиотек прогоняйте короткую проверку: имя метрики существует, нужный лейбл quantile на месте, значение не пусто. Такая проверка вообще полезна в CI: экспозиция сервиса сверяется со списком ожидаемых имён, и любое исчезновение ловится до выката.

Summary против histogram: где считаются квантили#

Практическая разница сводится к четырём пунктам. Агрегация: бакеты гистограммы — обычные счётчики, их суммируют sum by (le) и подают в histogram_quantile, получая честный p99 фермы или срез по конкретному маршруту; квантили summary суммировать нельзя — у каждого инстанса свой ряд quantile="0.99", и никакой запрос не соберёт их в общий. Новые квантили: гистограмма отдаёт любой перцентиль из имеющейся сетки — захотелось p95, меняется запрос без релиза; summary считает только то, что зашито в Objectives, новый квантиль — это релиз. Точность: summary гарантирует заявленную погрешность на потоке наблюдений; гистограмма ограничена сеткой бакетов и может быть грубее. Стоимость: summary тяжелеет от строгих погрешностей, гистограмма — фиксированные бакеты. Отсюда правило по умолчанию: HTTP-латентность и всё, что агрегируется, — гистограмма; summary — точечный инструмент одиночного процесса.

Один инстанс врал за весь кластер#

Ошибка интерпретации, характерная именно для summary: p99 одного инстанса читают как p99 сервиса. История: восемь подов, на дашборде ряд без агрегации — Prometheus показывал первый попавшийся. Половина трафика шла на новый релиз, у него квантиль был в пять раз выше, но на графике это смешивалось с семью зелёными подами и выглядело шумом. Честный срез по релизу построить нельзя: квантили не суммируются, а записи вида «по инстансу» — молитва на балансировщик, который раскладывает трафик как захочет. Правило для дежурного: если на панели латентности нет агрегации и рядов по подам, панель отвечает не на вопрос «как сервис», а на вопрос «как повезло инстансу, который попал в выборку». Для summary это не лечится запросом — лечится заменой типа, и этот аргумент в споре с гистограммой обычно решающий. Ту же ошибку делают с двумя регионами: p99 региона живёт своей жизнью.

Summary и Histogram рядом#

КритерийSummaryHistogram
Где считается квантильв приложении, на потоке наблюденийна сервере Prometheus, из бакетов
Агрегация по инстансамневозможна: квантили не складываютсяsum by (le) плюс histogram_quantile
Новый квантильтолько с релизом, через Objectivesлюбой, правкой запроса
Погрешностьзадаётся явно, например 0.001ограничена сеткой бакетов
Серии на метрикупо одной на цель, плюс sum и countбакеты с +Inf, плюс sum и count
Типичное применениеточный квантиль одного процессаHTTP-латентность и любые срезы

Вариация: MaxAge для фоновой задачи#

Вариация примера, где summary действительно хорош: длительность ночной фоновой задачи. Наблюдений мало — сотни за сутки, квантиль один, агрегировать не с чем: p99 задачи интересен там же, где она выполняется. Objectives с единственной целью 0.99 и погрешностью 0.001 стоит недорого, а MaxAge в сутки отсекает древнюю историю: без него после недели апгрейдов квантиль помнит времена старой версии кода и ползёт вниз неделями — улучшение, которого нет. Подводный камень окна: при малом числе наблюдений квантиль дёргается от каждой задачи, и график превращается в пилу. Для ночных задач с сотней запусков окно в сутки достаточно; для задачи раз в час — мало, и честнее отказаться от квантиля в пользу гистограммы с несколькими бакетами. MaxAge — единственный способ заставить клиентские квантили забывать прошлое.

Проверка: сторона подсчёта

Где считается квантиль у summary?

Проверка: экспозиция

Сколько серий экспортирует summary с Objectives {0.9: 0.01, 0.99: 0.001}?

Проверка: выбор типа

Нужен p99 по всем 20 инстансам и по каждому отдельно. Что берёте?

Summary без целей

Прочитайте код и выберите, что он выведет:

var opDuration = prometheus.NewSummary(
        prometheus.SummaryOpts{
                Name: "op_duration_seconds",
                Help: "Длительность операции",
        },
)

opDuration.Observe(0.2)
opDuration.Observe(0.4)

Соберите summary

Допишите создание summary, строгую погрешность для p99 и наблюдение значения.

var opDuration = prometheus.( prometheus.SummaryOpts{ Name: "op_duration_seconds", Help: "Длительность операции", Objectives: map[float64]float64{0.99: }, }, ) opDuration.(elapsed)

Соберите summary для фоновой задачи

Расставьте строки объявления summary с квантилем 0.99 и его регистрации.

Строки

Ваша программа

Нажимайте на строки слева, чтобы собрать программу

Карточки: summary

Термин

Summary

нажмите, чтобы перевернуть
Определение

Метрика с клиентскими квантилями: приложение ведёт потоковое приближение и отдаёт готовые числа с лейблом quantile, плюс _sum и _count.

1 / 6

Теперь у вас есть оба типа для распределений, и выбор между ними сводится к одному вопросу: будете ли вы агрегировать. Для HTTP-метрик ответ почти всегда «да», и в следующем уроке мы уже не будем выбирать типы руками: promhttp даёт готовые обёртки InstrumentHandlerDuration и InstrumentHandlerCounter, которые заводят латентность и статусы для всех маршрутов одним middleware. Если гистограмма из прошлого урока осталась туманной — вернитесь к нему: summary опирается на те же sum и count. Формулы с histogram_quantile и агрегацией бакетов разобраны в уроке про PromQL. Полный план — на странице курса Prometheus. Привычная оговорка про окружение: client_golang запускается только локальным Go — песочница сайта библиотечные пакеты не исполняет, зато экспозицию из этого урока можно читать curl-ом и сравнивать с гистограммой из прошлого урока глазами.

Песочница урока

Редактируйте код и запускайте его прямо здесь — интерпретатор работает в браузере, ничего устанавливать не нужно. За каждый запуск — +2 XP.

Вывод

Запустите код, чтобы увидеть вывод.

Коротко: что запомнить

  • Summary считает квантили в приложении: готовые числа с лейблом quantile в экспозиции.
  • Objectives — карта квантиль-погрешность; в свежих client_golang задаётся явно, дефолта больше нет.
  • sum и count экспортируются всегда: средняя доступна без целей и без бакетов.
  • Квантили не агрегируются: медианы не складываются, поэтому p99 фермы — только через гистограмму.
  • Новый квантиль у summary — релиз; у гистограммы — правка запроса.
  • Правило: HTTP-латентность — histogram; summary — точный квантиль одиночного процесса.

Домашнее задание

Заведите в учебном сервисе одну и ту же метрику дважды: histogram и summary с парой целей — на время выведите обе в /metrics. Сравните экспозиции глазами: где какие серии, сколько их, что доступно без запросов. Затем попытайтесь написать PromQL-запрос общего p99 для двух инстансов и убедитесь, что для summary такой запрос невозможен — это лучший способ запомнить главное отличие. Нужен локальный Go.

Личные заметкиПусто
Хранятся только в вашем браузере (Prometheus · Summary против Histogram)

Вопросы и ответы по уроку

Почему в свежих версиях client_golang у summary пропали квантили?

Дефолтный набор целей 0.5, 0.9, 0.99 убрали: Objectives задаётся явно в SummaryOpts. Summary без целей экспортирует только sum и count — добавьте карту Objectives, и квантили вернутся.

Можно ли summary с двух инстансов усреднить хотя бы примерно?

Нет: среднее квантилей — не квантиль среднего, и ошибку не ограничить никакой погрешностью из Objectives. Распределение фермы собирается из гистограммы; summary оставьте метрикой одного процесса.

Что даёт MaxAge в SummaryOpts?

Длину скользящего окна: наблюдения старше окна перестают влиять на квантиль, и метрика отражает недавнее поведение, а не всю историю процесса с момента старта. По умолчанию окно отключено.

Термины урока

Ключевые понятия из этого урока — короткие определения в глоссарии. Наведите на термин, чтобы вспомнить, откройте карточку для подробностей и ссылки на практику.

Следующая ступень учебного пути

WebSocket25 уроков~13 чпрактика25 уроков уже доступны

WebSocket в Go: real-time чаты и уведомления

Курс WebSocket на Go: gorilla/websocket, эхо-сервер, hub-паттерн, комнаты, авторизация соединений, ping/pong, reconnect и масштабирование. 25 уроков.

  • Поднимать WS-сервер и апгрейдить HTTP-соединения
  • Писать readPump/writePump без гонок на каждое соединение
  • Строить hub: регистрацию, рассылку и комнаты
  • Авторизовывать соединения и ограничивать сообщения