Increase () в Prometheus иногда удваивает значения: как избежать?

Я обнаружил, что для некоторых графиков я получаю двойные значения от Prometheus, где должны быть только единицы:

«График

Я использую запрос:

increase(signups_count[4m])

Интервал очистки установлен на рекомендованный максимум, равный 2 минутам.

Если я запрашиваю фактические сохраненные данные:

curl -gs 'localhost:9090/api/v1/query?query=(signups_count[1h])'

"values":[
     [1515721365.194, "579"],
     [1515721485.194, "579"],
     [1515721605.194, "580"],
     [1515721725.194, "580"],
     [1515721845.194, "580"],
     [1515721965.194, "580"],
     [1515722085.194, "580"],
     [1515722205.194, "581"],
     [1515722325.194, "581"],
     [1515722445.194, "581"],
     [1515722565.194, "581"]
],

Я вижу, что было всего два прибавления. И действительно, если я запрашиваю это время, я вижу ожидаемый результат:

curl -gs 'localhost:9090/api/v1/query_range?step=4m&query=increase(signups_count[4m])&start=1515721965.194&end=1515722565.194'

"values": [
     [1515721965.194, "0"],
     [1515722205.194, "1"],
     [1515722445.194, "0"]
],

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

curl -gs 'localhost:9090/api/v1/query_range?step=15&query=increase(signups_count[4m])&start=1515721965.194&end=1515722565.194'

... skip ...
 [1515722190.194, "0"],
 [1515722205.194, "1"],
 [1515722220.194, "2"],
 [1515722235.194, "2"],
... skip ...

Зная, что increase() - это просто синтаксический сахар для конкретного варианта использования функции rate() , я полагаю, что именно так он и должен работать с учетом обстоятельств.

Как избежать таких ситуаций? Как сделать так, чтобы Прометей / Графана в большинстве случаев показывала мне одного для одного и двоих для двоих? Кроме увеличения интервала очистки (это будет мое последнее средство).

Я понимаю, что Прометей не является точным инструментом , поэтому меня устраивает, если у меня будет хорошее число не всегда, а в большинстве случаев.

Что еще мне здесь не хватает?


person sanmai    schedule 12.01.2018    source источник
comment
Попробуйте MetricsQL. Он предоставляет increase() функцию, которая возвращает правильные целочисленные результаты для медленно растущих временных рядов.   -  person valyala    schedule 06.12.2020


Ответы (2)


Это называется псевдонимом и является фундаментальной проблемой при обработке сигналов. Вы можете немного улучшить это, увеличив частоту дискретизации, диапазон 4 м немного короче с диапазоном 2 м. Попробуйте дальность действия 10 метров.

Здесь, например, запрос, выполненный по адресу 1515722220, видит только образцы [email protected] и [email protected]. Это увеличение на 1 за 2 минуты, экстраполированное за 4 минуты дает увеличение на 2, что вполне ожидаемо.

Любая система мониторинга на основе метрик будет иметь похожие артефакты, если вы хотите 100% точности, вам нужны журналы.

person brian-brazil    schedule 12.01.2018
comment
Это утверждение Любая система мониторинга на основе метрик будет иметь похожие артефакты, если вы хотите 100% точности, вам нужны журналы. Фактически неверно, это не только уникально для Prometheus, но и несколько человек отправили в Prometheus ошибки с предлагаемыми исправлениями для этой проблемы. - person Preston; 12.05.2021

increase() всегда будет (приблизительно) удваивать фактическое увеличение при вашей настройке.

Причина в том, что (как сейчас реализовано):

  1. increase() - это (как вы заметили) синтаксический сахар для rate(), т.е. это значение, которое будет возвращено на rate(), умноженное на количество секунд в указанном вами диапазоне. В вашем случае это rate() * 240.
  2. rate() в своих вычислениях использует экстраполяцию. В подавляющем большинстве случаев 4-минутный диапазон возвращает ровно 2 точки данных с интервалом почти точно 2 минуты. Затем скорость вычисляется как разница между последним и первым (т.е. 2 балла в вашем случае), деленная на разницу во времени 2 баллов (около 120 секунд в 99,99% случаев), умноженную на запрошенный вами диапазон (точно 240 секунд. ). Таким образом, если увеличение между двумя точками равно нулю, ставка равна нулю. Если увеличение между двумя точками равно 1.0, вычисленное rate() будет близко к 2.0 / 240 и, в результате, increase() будет 2.0.

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

Вы можете, по сути, перепроектировать реализацию Прометея и получить (что-то очень близкое) фактическое увеличение, умножив на (requested_range - scrape interval) и разделив на requested_range, по сути, отступив от экстраполяции, которую делает Прометей.

В вашем случае это будет означать

increase(signups_count[4m]) * (240 - 120) / 240

или, более кратко,

increase(signups_count[4m]) / 2

Это требует, чтобы вы знали как длину диапазона, так и интервал очистки, но он даст вам то, что вы хотите: «один для одного и два для двоих, большую часть времени». Иногда вы получаете 1.01 вместо 1.0, потому что царапины составляли 119 секунд, а не 120 секунд, а иногда, если ваша оценка близко совпадает с царапинами, некоторые точки прямо на границе могут быть включены или не включены в расчет точки данных, но это все же лучший ответ, чем 2.0.

person Alin Sînpălean    schedule 04.04.2018
comment
Это не очень хороший совет, поскольку он предполагает, что в диапазоне всегда будут находиться ровно 2 образца. Во-первых, он не устойчив к неудачным царапинам, так как все еще использует слишком низкий диапазон. Во-вторых, он делает предположения о фазе и дрожании царапин, на которые вы не можете полагаться, и может привести к тому, что ответ будет намного больше, чем должен быть. - person brian-brazil; 10.04.2018
comment
Предполагается, что большую часть времени в диапазоне будут ровно 2 образца. Это именно то, о чем просил ОП: большую часть времени один на одного и двое на двоих. И у plain rate () / age () есть точно такие же проблемы с фазой и джиттером: они будут давать ответы намного больше, чем они должны быть (совершенно не считая того факта, что они уже дают ответы в два раза больше, чем они должны быть в средний случай. - person Alin Sînpălean; 11.04.2018
comment
Кроме того, вы по-прежнему можете использовать тот же базовый подход с более длинными диапазонами и по-прежнему улучшать то, что дает метод увеличения (). Ничто не заставляет вас использовать двукратный интервал очистки. Просто вы можете и в большинстве случаев получите ответы лучше, чем Increase (). - person Alin Sînpălean; 11.04.2018