Админим с Буквой
5.52K subscribers
303 photos
8 videos
59 files
1.16K links
Канал о системном администрировании, DevOps и немного Инфобеза.

По всем вопросам обращаться к @bykva. Рекламу не размещаю.
Download Telegram
Forwarded from Инженер Тяпкин (Сергей)
#8holes_edu #8holes_prometheus
Типы возвращаемых значений в PromQL

Prometheus в своих запросах может вернуть 3.5 вида ответов, а не 1.
Сразу уточню: я специально убрал из запросов и результатов все нерелевантные метки ради экономии места.

- одинокий int\float
Instant vector, классика для построения графиков\алертов.
Запрос:
  -> node_time_seconds{instance="localhost"}

Ответ:
  <- node_time_seconds{instance="localhost"}
1588419123

Обратите внимание, что float64 может нести в себе такие интересные значения, как -Inf, +Inf и Nan.
  -> node_time_seconds{instance="localhost"} / 0
<- node_time_seconds{instance="localhost"}
+Inf


- два и больше int\float
Range-vector, нужно для функций работающих с изменениями метрик.
  -> node_time_seconds{instance="localhost"}[90s]
<- node_time_seconds{instance="localhost"}
1588501106 @1588501106
1588501136 @1588501136
1588501166 @1588501166

Здесь мы получили все значения node_time_seconds, которые были собраны за указанный интервал(90s в данном случае)
В сыром виде такие данные не используются, и попытка отрисовать их в виде графика выдаст нам ошибку.
Однако, мы можем посмотреть изменения:
  -> delta(node_time_seconds{instance="localhost"}[90s])
<- {instance="localhost"}
90.003

Что мы видим?
Во-первых, в ответе теперь нет имени метрики.
Во-вторых, часики неожиданно тикают по одной секунде в секунду.
И сразу покажу, чем отличаются (кроме рыночной стоимости) delta() и idelta():
  -> idelta(node_time_seconds{instance="localhost"}[90s])
<- {instance="localhost"}
29.999

Да, функции с префиксом i анализируют не весь набор значений, а только 2 последних.
Это относится к idelta() и irate().

Также есть синтаксис, позволяющий отсечь излишние точки из ряда метрик.
Имейте ввиду, что такие запросы могут работать странно или не работать вообще в альтернативных реализациях, например в Promxy (точно валится с 500 в v0.0.57).
  -> node_time_seconds{instance="localhost"}[3m:1m]
<- node_time_seconds{instance="localhost"}
1588420473 @1588420500
1588420533 @1588420560
1588420593 @1588420620

Теперь мы получили метрики за последние 3m, с шагом по 1m.
Считать агрегацию по времени немного тупо, поэтому давайте поиграем в вангу, и предскажем, сколько натикают наши часики за минуту:
  -> predict_linear(
node_time_seconds{instance="localhost"}[5m:1m],
60
)
-
node_time_seconds{instance="localhost"}
<- {instance="localhost"}
59.23516726


- No data
Пустой ответ на ваш запрос.
И почти любые манипуляции (count() в том числе) над NoData вернут нам NoData.
И если отсутствующая нулевая линия в графике скорее всего не будет критичной проблемой, то вот в алерте это может быть фатально.
Тут уже сложнее приводить часы в пример, поэтому перейдем на метрику доступности Openstack API.
Запрос метрик dc1 , в котором все нормально
  -> count(
openstack_neutron_up{inventory_dc="dc1"}
) by (inventory_dc,job)
<- {inventory_dc="dc1",job="openstack-exporter"}
3

Запрос метрик dc2 , в котором все экспортеры лежат, и метрик нет
  -> count(
openstack_neutron_up{inventory_dc="dc1"}
) by (inventory_dc,job)
<- No data


Это можно обыграть бинарным операциями и absent().
dc1
  -> count(
openstack_neutron_up{inventory_dc="dc1"}
) by (inventory_dc,job)
or
(
absent(
openstack_neutron_up{inventory_dc="dc1"}
)
* 0
)
<- {inventory_dc="dc1",job="openstack-exporter"}
3

dc2
  -> count(
openstack_neutron_up{inventory_dc="dc2"}
) by (inventory_dc,job)
or
(
absent(
openstack_neutron_up{inventory_dc="dc2"}
)
* 0
)
<- {inventory_dc="dc2"}
0

Обратите внимане, что absent() не телепат, поэтому в случае отсутствия метрики вернутся только те метки, которые вы передали в запросе.

Если нам вообще не интересны метки, то запрос можно упростить:
dc1
  -> count(openstack_neutron_up{inventory_dc="dc1"})
or
vector(0)
<- {}
3

dc2
  -> count(openstack_neutron_up{inventory_dc="dc2"})
or
vector(0)
<- {}
0