Обычно мы подключаем сбор метрик в prometheus к нашим web‑приложениям с помощью каких‑то клиентских библиотек, которые отдают метрики на /metrics. В этой статье я хочу рассказать как визуализировать Latency с помощью Histogram метрики. Будет полезно тем, кто еще не строил метрики из Prometheus, а так же тем, кто хочет понять как их интерпретировать.

4 golden signals - https://www.ibm.com/garage/method/practices/manage/golden-signals/

На картинке «четыре золотых сигнала» (four golden signals) показан набор метрик, которые Google рекомендует отслеживать в SRE (Site Reliability Engineering) подходе. Это latency, traffic, errors и saturation. Мониторинг этих «четырех золотых сигналов» может помочь инженерам оперативно реагировать на проблемы, связанные с производительностью и надежностью системы, а также помочь в определении бутылочных горлышек и планировании масштабирования.

Prometheus

Prometheus — это открытая система мониторинга и оповещения, которая была разработана SoundCloud. В среде распределенных систем Prometheus широко используется для сбора и визуализации метрик в реальном времени.

Архитектура Prometheus - https://prometheus.io/docs/introduction/overview/
Архитектура Prometheus - https://prometheus.io/docs/introduction/overview/

Prometheus собирает и хранит метрики в виде данных временных рядов, каждый временной ряд идентифицируется именем и набором лейблов (пары, ключ, значение и т. д.).

# Пример метрики с /metrics
request_latency_seconds_bucket{le="0.1"} 32.0
Что такое метрика

Метрика — количественный показатель, используемый для измерения и оценки работы системы.

Сбор метрик. Prometheus использует pull‑модель для сбора метрик, которая предполагает, что Prometheus сам инициирует процесс сбора информации с сервисов, которые мониторит. Это отличает его от push‑модели, где сервисы самостоятельно отправляют свои метрики на сервер мониторинга. Однако у prometheus есть push‑gateway.

Latency (или задержка) — время, которое требуется для обработки запроса. В контексте веб‑сервисов, это обычно время, затраченное на обработку HTTP‑запроса. Мониторинг latency важен, так как он напрямую влияет на пользовательский опыт. Важно не просто отслеживать среднее время задержки, но и изучать его распределение, чтобы понять, как ведет себя система в условиях различной нагрузки.

Web-приложение на fast-api

Для демонстрации создадим простое приложение, Grafana находится на 3000 порту, логин/пароль — admin/admin. Нужно добавить источник данных — http://prometheus:9090.

Код приложения на 28 строк :)
import time
from typing import Union

from prometheus_client import Histogram, make_asgi_app
from fastapi import FastAPI

app = FastAPI()

metrics_app = make_asgi_app()
app.mount("/metrics", metrics_app)

REQUEST_LATENCY = Histogram(
    name='request_latency_seconds',
    documentation='Time spent processing a request',
    buckets=(.1, .2, .3, .4, .5)
)


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
@REQUEST_LATENCY.time()
def read_item(item_id: int, q: Union[str, None] = None):
    time.sleep(item_id / 100)
    return {"item_id": item_id, "q": q}

Dockerfile для приложения
FROM python:3.10

WORKDIR /code

COPY ./requirements.txt /code/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY ./app /code/app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

Docker-compose
version: '3.9'

services:
  web:
    build: .
    ports:
      - 8000:8000

  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - 9090:9090
    depends_on:
      - web

  grafana:
    image: grafana/grafana
    ports:
      - 3000:3000
    depends_on:
      - prometheus

Как собирать метрики для построения Latency

Prometheus собирает данные по latency при помощи наблюдателей (observers) в клиентских библиотеках. В мире Prometheus существует четыре основных типа наблюдателей: Counter, Gauge, Summary и Histogram. Для измерения задержки обычно используется Histogram.

Histogram подсчитывает наблюдения (samples), например, HTTP‑запросы, которые он сортирует в настраиваемые сегменты (buckets) по длительности. Он также считает общее количество наблюдений и сумму всех наблюдаемых значений.

Например, вы можете определить сегменты следующим образом: 0.1, 0.2, 0.3, 0.4, 0.5 секунды. Каждый раз, когда Prometheus получает новое значение latency, он увеличивает счетчик для соответствующего сегмента.

Как выбрать распределение сегментов

Например в клиенте prometheus_client предлагается такое значение:

DEFAULT_BUCKETS = (.005, .01, .025, .05, .075, .1, .25, .5, .75, 1.0, 2.5, 5.0, 7.5, 10.0, INF)

Дефолтные сегменты не всегда имеют смысл для вашего приложения. Я бы рекомендовал выбирать сегменты относительно SLO (целевой уровень обслуживания). А так же несколько сегментов выше/ниже SLO.

Например, если SLO для микросервисов составляет около 500 мс. Слишком меньшие сегменты (5 мс, 10 мс, 25 мс, 50 мс) и слишком большие сегменты (2500 мс, 5000 мс, 7500 мс, 10 000 мс) бесполезны.

Histogram состоит из трех элементов:

  • <имя>_count, подсчитывающий количество наблюдений;

  • <имя>_sum, сумма всех наблюдаемых значений;

  • набор из сегментов <имя>_bucket с меткой le (меньше или равно), которые содержат количество наблюдений, значение которых меньше или равно числовому значению, содержащемуся в сегменте.

Было два запроса по 30 ms - данные с /metrics
Было два запроса по 30 ms - данные с /metrics

Сегмент le="0.1" указывает, что 2 запроса завершились за 0.1 секунду или быстрее.

Сделали еще один запрос на 468 ms - данные с /metrics
Сделали еще один запрос на 468 ms - данные с /metrics

Частоты для каждого отдельного сегмента, сообщаемые клиентом Prometheus, являются кумулятивными. Это означает, что счетчик для сегмента le="0,4" также включает счетчик для сегментов le="0,3", le="0,2", le="0,1".

По Histogram можно посчитать квантили(перцентили).

Что такое перцентиль

Квантиль — значение, которое заданная случайная величина не превышает с фиксированной вероятностью. Если вероятность задана в процентах, то квантиль называется процентилем или перцентилем. Если 25% всех наблюдений лежат ниже или равны значению, мы можем сказать, что значение является 25-м перцентилем, и это значение может быть представлено как p25.

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

В контексте latency, перцентили обычно используются для описания распределения времени ответа системы.

Рассмотрим пример. Пусть у вас есть веб-сервер, и вы замерили время ответа сервера на 1000 запросов. Вы записали эти времена ответа и отсортировали их по возрастанию.

Пусть 50-й перцентиль (или медиана) равен 200 миллисекундам. Это означает, что 50% всех запросов были обработаны за 200 миллисекунд или быстрее.

Если 95-й перцентиль равен 500 миллисекундам, это означает, что 95% всех запросов были обработаны за 500 миллисекунд или быстрее, а 5% запросов требовали больше времени на обработку.

99-й перцентиль, который может быть равен, например, 800 миллисекундам, показывает, что 99% всех запросов были обработаны за 800 миллисекунд или быстрее, а самые медленные 1% запросов требовали больше времени на обработку.

Таким образом, перцентили предоставляют важное понимание о том, как система ведет себя не только в среднем, но и в крайних условиях, позволяя определить как нормальную работу системы, так и ее поведение в условиях пиковой нагрузки.

Выполним запросы к web-приложению
Выполним запросы к web-приложению
Получим такие метрики с /metrics

Как построить график Latency в Grafana

Для графика Latency будем использовать перцентиль 95%, можно так же построить и другие перцентили. Для визуализации в Grafana нужно выполнить PromQL (Prometheus Query Language) запрос:

histogram_quantile(
    0.95,
    sum(
      rate(
        request_latency_seconds_bucket[1m]
      )
    ) by (le)
)

request_latency_seconds_bucket — временной ряд из Prometheus.

rate — используется для вычисления средней скорости изменения для временных рядов в указанный промежуток времени, как часто определенное событие происходит в течении определенного времени. Грубо говоря, как производная в математике.

Средняя скорость изменения в сегментах
Средняя скорость изменения в сегментах

sum — оператор агрегации, который суммирует значения по группе элементов. Используется для получения общей суммы значений для всех подходящих временных рядов.

Суммируем, в нашем случае ничего не изменилось :)
Суммируем, в нашем случае ничего не изменилось :)

histogram_quantile — ищет значение, которое не превышает определенный процент всех запросов. Интерпретировать можно так: «N% всех запросов обрабатывается быстрее, чем это значение».

95% запросов выполняются быстрее
95% запросов выполняются быстрее
50% запросов выполняются быстрее
50% запросов выполняются быстрее

Вывод

Для построения Latency, можно использовать выражение:

histogram_quantile(0.95, sum(rate(request_latency_seconds_bucket[1m])) by (le))

Это выражение дает вам 95-й перцентиль Latency запроса за последнюю минуту. Это значит, что 95% всех измеренных запросов за последнюю минуту имели задержку, которая была меньше или равна вычисленному значению.

Histogram не являются эффективным инструментом для точного измерения задержки, особенно на границах сегментов. Так как если latency уменьшился на 20 мс, будет ли это заметно на графике — зависит от настроенных сегментов. Данный график можно использовать в широком смысле для качественной оценки оптимизации, но не для количественной.

Не стоит использовать очень много сегментов, так как каждый сегмент образует свой временной ряд в БД Prometheus'a.

Материалы

Материалы статьи

Мой тг канал, где я пишу заметки/мысли о backend, system design, архитектуре и проектировании

Комментарии (9)


  1. PqDn
    11.07.2023 15:06
    +4

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

    Мы после обновления до 2.6 спринг бута, внезапно обнаружили, что у нас прометеус начал отдавать метрики по 2-3 мегабайта. А было до этого 150-200кб. Как оказалось в спринге решили метрики для редиса по дефолту сделать гистограмными.


    1. AntonOcean Автор
      11.07.2023 15:06
      +3

      Кажется, для длительного хранения метрик лучше подойдет VictoriaMetrics


      1. PqDn
        11.07.2023 15:06

        да, мы этим и пользуемся


  1. miga
    11.07.2023 15:06
    +3

    Стоит отметить, что это не настоящие квантили, а приблизительно вычисленные из гистограммы, и чем меньше бакетов, тем меньше точность. Честно и эффективно считать квантили на потоковых данных - это та еще задачка, к которой пром, кажется, и не подступался, в отличие от, например, m3db.

    Я б сказал, что для визуализации гистограмм больше подходят хитмапы, они вам и покажут именно то, что хранится, у них и плотность информации больше (видно не только латенси, но и ее распределение). Но читать их, конечно, сложнее.


    1. AntonOcean Автор
      11.07.2023 15:06

      Спасибо!)


  1. akurilov
    11.07.2023 15:06

    Строго говоря, на графике в нижнем правом углу Utilization, а не Saturation. Но так даже лучше, ибо Saturation определяет Latency и виден на соответствующем графике


    1. punilki
      11.07.2023 15:06

      картинка с сайта IBM и там как раз описывается saturation


  1. letenkov
    11.07.2023 15:06

    Вам нужны метрики для метрик ;-)


  1. nskforward
    11.07.2023 15:06
    +1

    Также интересно будет почитать на официальном сайте прометея Про гистораммы