PromQL, MetricQL
Expand VictoriaMetrics WITH templates to canonical PromQL
Все описанные метрики получены vmagent'ом с snmp_exporter'а, записаны в базу VictoriaMetrics.
Список метрик
В grafana есть возможность делать запросы в базы через Explore. Для вывода всех метрик, полученных по job'у job_name выполнить:
max({job="job_name"}) by (__name__)
Варианты запросов в базу
В редакторе панели есть query inspector. Он позволяет посмотреть запрос в базу со всеми параметрами. Можно разделить запросы на два типа, описанных в API:
- instant-queries. Включается галочкой instant.
- range-queries. Используется по умолчанию.
Цитата из чата:
Instant запросы идут к /api/v1/query, а не к /api/v1/query_range. Там вообще нет параметра step - см. https://prometheus.io/docs/prometheus/latest/querying/api/#instant-queries, т.к. такой запрос должен возвращать только по одной точке на ряд в момент времени, переданном в параметре time. ВМ принимает step в запросе к /api/v1/query из-за особенностей реализации. В большинстве случаев его туда передавать не нужно.
Переменные для дашбордов
Для дашборда с выводом информации по маршрутизаторам и коммутаторам понадобится несколько переменных: хост (ip) и интерфейс (iface). Имя хоста (instance) из метрики ifHCInOctets в переменную ip.
label_values(ifHCInOctets{},instance)
label_values(ifHCInOctets{instance="$ip"}, ifName)
Uptime
sysUpTime{instance="$ip"}*10
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | Stat | 1m | 15m |
Field -> Standard options -> Units -> Time -> duration (ms), Field -> Standard options -> Decimals -> 3, Panel -> Display -> Fields - Numeric Fields
Таблица для определения утечки памяти на cisco
В vmagent'е job'у соотвествует модуль snmp_exporter'а, созданный для определенного типа устройств: asa, router, l2 switch, l3 switch. Т.е. выбирается по 5 для каждого типа устройств.
bottomk by (job) (5, (delta(ciscoMemoryPoolFree{ciscoMemoryPoolType!="20"}[7d])))
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | table | 7d | 7d |
Ошибки на интерфейсах
Устройства имеют label "obj" для идентификации места установки и удобства при составлении запросов.
topk(10, (increase(ifInErrors{obj="$object"}[8h]))) > 0
topk(5, (increase(ifOutDiscards{obj="$object"}[8h]))) > 0
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | table | 8d | 8d |
Для вывода ошибок по конкретному хосту удобнее видеть таблицу с текущими ошибками и суммой за период:
increase(ifInErrors{instance="$ip"}[5m])
instant | panel | format | interval | relative time |
---|---|---|---|---|
no | table | timeseries | 5m | 1h |
Для timeseries нужно в таблице сделать Transform Reduce с Calculation Last, Total.
В поле Legend указать {{ ifName }}
чтобы не отображать все имеющиеся лейблы временного ряда.
Отчет по доступности
Анализируются статусы недоступности в cisco ip sla (4) и huawei nqa (2). В дашборде создана переменная ivl тип Interval. Для каждого пробера в одной таблице создается отдельный запрос, чтобы понятными буквами в легенде описать название канала связи. Каждая строка - отдельный запрос: A,B и т.д.
count_gt_over_time(rttMonLatestRttOperSense{instance="cisco-router-1",rttMonCtrlAdminIndex="1"}[$ivl], 3)
count_gt_over_time(rttMonLatestRttOperSense{instance="cisco-router-1",rttMonCtrlAdminIndex="2"}[$ivl], 3)
..
count_gt_over_time(nqaResultsCompletions{instance="huawei-1",nqaAdminCtrlOwnerIndex="1",nqaAdminCtrlTestName="1"}[$ivl], 1)
count_gt_over_time(nqaResultsCompletions{instance="huawei-1",nqaAdminCtrlOwnerIndex="1",nqaAdminCtrlTestName="2"}[$ivl], 1)
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | timeseries | $ivl |
Для timeseries нужно в таблице сделать Transform Reduce с Calculation Max или Last.
График свободной памяти
Нужно вывести %, а значит нужно вычислить:
ciscoMemoryPoolFree{instance="$ip",ciscoMemoryPoolType!="20"}*100/(ciscoMemoryPoolFree{instance="$ip",ciscoMemoryPoolType!="20"}+ciscoMemoryPoolUsed{instance="$ip",ciscoMemoryPoolType!="20"})
instant | panel | format | interval | relative time |
---|---|---|---|---|
no | graph | timeseries |
В поле Legend указать {{ciscoMemoryPoolName}}
чтобы не отображать все имеющиеся лейблы временного ряда. Panel -> Axes -> Left Y -> Unit -> Misc -> percent (0-100)
График загрузки cpu
В метрике есть %, поэтому:
cpmCPUTotal5min{instance="$ip"}
instant | panel | format | interval | relative time |
---|---|---|---|---|
no | graph | timeseries |
В поле Legend указать {{cpu5min}}
чтобы не отображать все имеющиеся лейблы временного ряда. Panel -> Axes -> Left Y -> Unit -> Misc -> percent (0-100)
График ifOutDiscards ошибок
В панели будет график с двумя линиями: выбранный интерфейс, сумма ошибок по всем интерфейсам. Там будут записи только для ifType=6, потому что есть правило для удаление иных значений в vmagent'е. Для выбранного интерфейса:
increase(ifOutDiscards{instance="$ip",ifName="$iface"}[5m])
sum(increase(ifOutDiscards{instance="$ip"}[5m]))
instant | panel | format | interval | relative time |
---|---|---|---|---|
no | graph | timeseries |
В поле Legend указать $iface
для первого запроса и Total
для второго.
График IfInErrors ошибок
В панели будет график с двумя линиями: выбранный интерфейс, сумма ошибок по всем интерфейсам. Там будут записи только для ifType=6, потому что есть правило для удаление иных значений в vmagent'е. Для выбранного интерфейса:
increase(ifInErrors{instance="$ip",ifName="$iface"}[5m])
sum(increase(ifInErrors{instance="$ip"}[5m]))
instant | panel | format | interval | relative time |
---|---|---|---|---|
no | graph | timeseries |
В поле Legend указать $iface
для первого запроса и Total
для второго.
График BPS
Сумма по всем физическим интерфейсам хоста:
8 * sum(rate(ifHCInOctets{instance="$ip",ifType="6"}[5m]))
8 * rate(ifHCInOctets{instance="$ip",ifName="$iface"}[5m])
8 * rate(ifHCOutOctets{instance="$ip",ifName="$iface"}[5m])
instant | panel | format | interval | relative time |
---|---|---|---|---|
no | graph | timeseries |
В поле Legend указать $iface recv
и $iface send
для второго и третьего запроса и Total recv
для первого.
Panel -> Axes -> Left Y -> Unit -> Data rate -> bits/sec.
MetricQL позволяет конструировать один запрос для приема и передачи. Ниже сумма счетчиков с двух интерфейсов Gi0/1.100 разных маршрутизаторов для построения одного графика:
WITH (
cf = {instance=~"border-1|border-2", ifName="Gi0/1.100" },
netUsage(name, m) = label_set(sum(rate(m{cf})*8), "name", name),
)
union (
netUsage("recv", ifHCOutOctets),
netUsage("send", ifHCInOctets),
)
instance=~
для того чтобы указать какое-то регулярное выражение, то необходимо функцию rate()
поместить в sum()
.
Это сделано выше и ниже в примере, где BPS показан из счетчиков политики huawei c двух разных устройств. Счетчики политики для приема (direction=1):
sum(rate(hwCBQoSPolicyStatClassifierMatchedPassBytes{hwCBQoSIfApplyPolicyDirection="1",hwCBQoSIfApplyPolicyIfIndex="6",hwCBQoSIfVlanApplyPolicyVlanid1="0",hwCBQoSPolicyStatClassifierName="0xA",instance=~"huawei-[12]"}[5m]))*8
sum(rate(hwCBQoSPolicyStatClassifierMatchedPassBytes{hwCBQoSIfApplyPolicyDirection="2",hwCBQoSIfApplyPolicyIfIndex="6",hwCBQoSIfVlanApplyPolicyVlanid1="0",hwCBQoSPolicyStatClassifierName="0xB",instance=~"huawei-[12]"}[5m]))*8
8 * (sum(rate(cbQosCMPostPolicyByte{cbQosObjectsIndex="13816289",cbQosPolicyIndex="240",instance="border-1"}))
+
sum(rate(cbQosCMPostPolicyByte{cbQosObjectsIndex="1341969",cbQosPolicyIndex="3680",instance="border-2"})))
8 * (sum(rate(ifHCOutOctets{instance="switch",ifName="Gi1/0/1"})) - sum(rate(ifHCOutOctets{instance="switch",ifName="Gi1/0/1"}) offset 7d))
Таблица BPS
Снова MetricQL. Top 10 загруженных интерфейсов по всей сети за 5 минут по счетчику ifHCOutOctets, переданному как параметр PortUtilization из topk. Дополнительно используется функция ru() из MetricQL для определения % утилизации порта:
WITH (
maxRate = ifHighSpeed{ifType="6"}[$__interval] * 1e6 / 8,
commonFilters = {ifType="6"},
PortUtilization(ifHCOctets, maxRate) = ru(maxRate - rate(ifHCOctets{commonFilters}[$__interval]), maxRate)
)topk(10,PortUtilization(ifHCOutOctets, maxRate))
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | timeseries | 5m | 5m |
В поле Legend указать {{instance}},{{ifName}}
.
Такую же таблицу сделать для ifHCInOctets.
График PPS
PPS по выбранному интерфейсу по приему:
rate(ifHCInUcastPkts{instance="$ip",ifName="$iface"}[5m])
rate(ifHCOutUcastPkts{instance="$ip",ifName="$iface"}[5m])
instant | panel | format | interval | relative time |
---|---|---|---|---|
no | graph | timeseries |
В поле Legend указать $iface recv
и $iface send
для первого и второго запроса.
Panel -> Axes -> Left Y -> Unit -> Data rate -> packets/sec.
Таблица c top по flapping interface
Первая таблица по кол-ву изменений оперативного статуса интерфейса.
topk(10,sum_over_time(changes(ifOperStatus{}[1m])[1h]))
topk(10,sum_over_time(changes(ifHighSpeed{}[1m])[1h]))
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | timeseries | 1m | 1h |
В поле Legend указать {{instance}},{{ifName}}
.
Для timeseries нужно в таблице сделать Transform Reduce с Calculation Max.
Таблицы по spanning-tree
Определение root'а в регионе.
bottomk(1,dot1dStpPriority) by (obj)
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | timeseries | 1m | 5m |
В поле Legend указать {{instance}}
.
Для timeseries нужно в таблице сделать Transform Reduce с Calculation Max.
Таймеры TCN. Если изменился недавно, то значит произошло изменение топологии из-за переключений или из-за некорректных настроек.
10 * bottomk(1,dot1dStpTimeSinceTopologyChange != 0) by (obj)
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | timeseries | 1m | 5m |
В поле Legend указать {{instance}}
.
Для timeseries нужно в таблице сделать Transform Reduce с Calculation Max. Для колонки с временем выбрать Units -> Time -> duration (ms)
Сколько раз на коммутаторе менялся root port за час.
sum_over_time(changes(dot1dStpRootPort{})[1h]) >
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | timeseries | 1m | 1h |
В поле Legend указать {{instance}}
.
Для timeseries нужно в таблице сделать Transform Reduce с Calculation Max.
Cisco ErrDisableIfStatus
Это не метрики, а события. С одной стороны неправильно для этого использовать tsdb. С другой стороны, когда recovery на коммутаторах выключен, то вполне. В таблице будут числа, а Enum можно посмотреть в snmp.yml или в мибах. Так 2 - это отработал bpduguard.
cErrDisableIfStatusCause{}[1m]
instant | panel | format | interval | relative time |
---|---|---|---|---|
yes | table | table | 1m | 5m |
Проверка протоколов маршрутизации
Для проверки состояния протоколов маршрутизации можно использовать доступные метрики, создавать алерты средствами grafana или vmalerts+alertmanager.
BGP peer status равен 6, если established. Если не 6, то алерт.
bgpPeerState{bgpPeerRemoteAddr="10.9.8.7"}[1m]
hwOspfv2NbrState{hwOspfv2NbrIpAddrIndex="10.9.8.7"}[1m]
Проверка проберов SLA, NQA
NQA для huawei с icmp пробером. 1 - ОК. Если больше, то алерт.
nqaResultsCompletions{instance="huawei",nqaAdminCtrlTestName="1"}[1m]`
rttMonLatestRttOperSense{instance="cisco",rttMonCtrlAdminIndex="1"}[1m]
changes(rttMonLatestRttOperSense{instance="cisco",rttMonCtrlAdminIndex="1"}[15m])
Проверка статуса интерфейса
1 - OK. Если больше, то алерт.
ifOperStatus{ifName="Gi1/0/1",instance="cisco"}[1m]
Проверка температуры
Есть датчики на оборудовании Cisco и у большинства старых моделей одинаковый oid, но разные TemperatureStatusIndex для разных моделей, стеков. Либо датчиков более одного и нужно выбрать конкретный.
ciscoEnvMonTemperatureStatusValue{ciscoEnvMonTemperatureStatusIndex="1",instance="cisco"}[10m]
upsAdvBatteryTemperature{instance="apc_ups"}
Проверка ИБП APC
Статус. 2 - ОК. 3 - на батареях. 12 - напряжение выше 250В на входе.
upsBasicOutputStatus{instance="apc_ups"}
Enum
1: unknown
2: onLine
3: onBattery
4: onSmartBoost
5: timedSleeping
6: softwareBypass
7: "off"
8: rebooting
9: switchedBypass
10: hardwareFailureBypass
11: sleepingUntilPowerReturn
12: onSmartTrim
alerts ifmib
flapping физического интерфейса, который в up, но его состояние изменилось до этого
(changes(ifLastChange{ifType="6"}[15m]) > 0) and (ifOperStatus == 1) and ON(instance) (sysUpTime > 150000)
(max(ifLastChange{ifType="6"} < 20000) by (instance)) and ON(instance) (sysUpTime < 150000)
(ifAdminStatus == 1) and (ifOperStatus == 2)
rate(dot3HCInPauseFrames[5m]) > 5
rate(ifInErrors[15m]) > 5
rate(ifOutDiscards[15m]) > 100
rate(ifHCOutOctets{ifType="6"}[10m]) > ((ifHighSpeed{ifType="6"})*90000)
alerts fiber channel
Редко. не видел
rate(fcIfCreditLoss[5m]) > 0
rate(fcIfTxWaitCount[5m]) > 0
rate(fcIfLinkResetIns[5m]) > 0
rate(fcIfLinkResetOuts[5m]) > 0
rate(fcHCIfBBCreditTransistionToZero[5m]) > 500000
rate(fcHCIfBBCreditTransistionFromZero[5m]) > 500000
rate(fcIfTimeOutDiscards[5m]) > 0
rate(fcIfOutDiscards[5m]) > 0
rate(fcIfTxWtAvgBBCreditTransitionToZero[5m]) > 0
rate(fcIfC3InOctets[10m]) > ((ifHighSpeed)*90000)
rate(fcIfC3OutOctets[10m]) > ((ifHighSpeed)*90000)
alerts exos
Питание
extremePowerSupplyStatus !=2
extremeFanOperational > 1
extremeOverTemperatureAlarm < 2
extremeCpuMonitorSystemUtilization1min > 15