Awọn ẹtan fun sisẹ awọn metiriki ni Kapacitor

O ṣeese julọ, loni ko si ẹnikan ti o beere idi ti o ṣe pataki lati gba awọn metiriki iṣẹ. Igbesẹ ọgbọn ti o tẹle ni lati ṣeto itaniji fun awọn metiriki ti a gba, eyiti yoo ṣe akiyesi nipa awọn iyapa eyikeyi ninu data ninu awọn ikanni ti o rọrun fun ọ (meeli, Slack, Telegram). Ninu iṣẹ ifiṣura hotẹẹli lori ayelujara Ostrovok.ru gbogbo awọn metiriki ti awọn iṣẹ wa ni a da sinu InfluxDB ati ṣafihan ni Grafana, ati pe titaniji ipilẹ tun jẹ tunto nibẹ. Fun awọn iṣẹ ṣiṣe bii “o nilo lati ṣe iṣiro nkan kan ki o ṣe afiwe pẹlu rẹ,” a lo Kapacitor.

Awọn ẹtan fun sisẹ awọn metiriki ni Kapacitor
Kapacitor jẹ apakan ti akopọ TICK ti o le ṣe ilana awọn metiriki lati InfluxDB. O le so awọn wiwọn pupọ pọ (darapọ), ṣe iṣiro nkan ti o wulo lati data ti o gba, kọ abajade pada si InfluxDB, fi itaniji ranṣẹ si Slack/Telegram/mail.

Gbogbo akopọ jẹ itura ati alaye iwe aṣẹ, ṣugbọn awọn ohun ti o wulo nigbagbogbo yoo wa ti ko ṣe afihan ni pato ninu awọn itọnisọna. Ninu nkan yii, Mo pinnu lati gba nọmba kan ti iru iwulo, awọn imọran ti ko han gbangba (sintasi ipilẹ ti TICKscipt jẹ apejuwe nibi) kí o sì fi bí a ṣe lè fi wọ́n sílò hàn nípa lílo àpẹẹrẹ yíyanjú ọ̀kan lára ​​àwọn ìṣòro wa.

Lọ!

leefofo & int, isiro aṣiṣe

Iṣoro idiwọn pipe, ti a yanju nipasẹ awọn simẹnti:

var alert_float = 5.0
var alert_int = 10
data|eval(lambda: float("value") > alert_float OR float("value") < float("alert_int"))

Lilo aiyipada()

Ti aami kan ko ba kun, awọn aṣiṣe iṣiro yoo waye:

|default()
        .tag('status', 'empty')
        .field('value', 0)

fọwọsi idapọ (inu vs lode)

Nipa aiyipada, darapọ mọ awọn aaye ti ko si data (inu).
Nigbati o ba kun ('asan') isọdọkan ita yoo ṣee ṣe, lẹhin eyi o nilo lati ṣe aiyipada () ki o kun awọn iye ofo:

var data = res1
    |join(res2)
        .as('res1', 'res2)
        .fill('null')
    |default()
        .field('res1.value', 0.0)
        .field('res2.value', 100.0)

Nuance tun wa nibi. Ninu apẹẹrẹ ti o wa loke, ti ọkan ninu jara (res1 tabi res2) ba ṣofo, jara ti abajade (data) yoo tun jẹ ofo. Awọn tikẹti pupọ wa lori koko yii lori Github (1633, 1871, 6967) - a n duro de awọn atunṣe ati ijiya diẹ.

Lilo awọn ipo ni iṣiro (ti o ba wa ni lambda)

|eval(lambda: if("value" > 0, true, false)

Iṣẹju marun to kẹhin lati opo gigun ti epo fun akoko naa

Fun apẹẹrẹ, o nilo lati ṣe afiwe awọn iye ti iṣẹju marun to kẹhin pẹlu ọsẹ ti tẹlẹ. O le gba awọn ipele meji ti data ni awọn ipele lọtọ meji tabi yọ apakan ti data jade lati akoko nla:

 |where(lambda: duration((unixNano(now()) - unixNano("time"))/1000, 1u) < 5m)

Yiyan fun iṣẹju marun to kẹhin yoo jẹ lati lo BarrierNode kan, eyiti o ge data kuro ṣaaju akoko ti a sọ pato:

|barrier()
        .period(5m)

Awọn apẹẹrẹ ti lilo awọn awoṣe Go ninu ifiranṣẹ

Awọn awoṣe badọgba si ọna kika lati package ọrọ.awoṣeNi isalẹ wa diẹ ninu awọn adojuru ti o nwaye nigbagbogbo.

ti o ba ti-miiran

A ṣeto awọn nkan ati pe a ko ṣe okunfa eniyan pẹlu ọrọ lẹẹkan si:

|alert()
    ...
    .message(
        '{{ if eq .Level "OK" }}It is ok now{{ else }}Chief, everything is broken{{end}}'
    )

Awọn nọmba meji lẹhin aaye eleemewa ninu ifiranṣẹ

Imudara kika ti ifiranṣẹ naa:

|alert()
    ...
    .message(
        'now value is {{ index .Fields "value" | printf "%0.2f" }}'
    )

Faagun awọn oniyipada ninu ifiranṣẹ

A ṣe afihan alaye diẹ sii ninu ifiranṣẹ lati dahun ibeere naa “Kini idi ti o n pariwo”?

var warnAlert = 10
  |alert()
    ...
    .message(
       'Today value less then '+string(warnAlert)+'%'
    )

Oto gbigbọn idamo

Eyi jẹ ohun pataki nigbati o ba wa ju ẹgbẹ kan lọ ninu data naa, bibẹẹkọ titaniji kan yoo jẹ ipilẹṣẹ:

|alert()
      ...
      .id('{{ index .Tags "myname" }}/{{ index .Tags "myfield" }}')

Aṣa olutọju ká

Atokọ nla ti awọn olutọju pẹlu exec, eyiti o fun ọ laaye lati ṣiṣẹ iwe afọwọkọ rẹ pẹlu awọn aye ti o kọja (stdin) - iṣẹda ati ohunkohun diẹ sii!

Ọkan ninu awọn aṣa wa jẹ iwe afọwọkọ Python kekere kan fun fifiranṣẹ awọn iwifunni si ọlẹ.
Ni akọkọ, a fẹ lati firanṣẹ aworan grafana ti o ni aabo ni aṣẹ ninu ifiranṣẹ kan. Lẹhinna, kọ O dara ninu o tẹle ara si titaniji iṣaaju lati ẹgbẹ kanna, kii ṣe bi ifiranṣẹ lọtọ. Ni igba diẹ - ṣafikun ifiranṣẹ aṣiṣe ti o wọpọ julọ ni awọn iṣẹju X to kẹhin.

Koko lọtọ jẹ ibaraẹnisọrọ pẹlu awọn iṣẹ miiran ati awọn iṣe eyikeyi ti o bẹrẹ nipasẹ itaniji (nikan ti ibojuwo rẹ ba ṣiṣẹ daradara to).
Apeere ti apejuwe olutọju kan, nibiti slack_handler.py jẹ iwe afọwọkọ ti ara wa:

topic: slack_graph
id: slack_graph.alert
match: level() != INFO AND changed() == TRUE
kind: exec
options:
  prog: /sbin/slack_handler.py
  args: ["-c", "CHANNELID", "--graph", "--search"]

Bawo ni lati ṣatunṣe?

Aṣayan pẹlu iṣẹjade log

|log()
      .level("error")
      .prefix("something")

Watch (cli): kapacitor -url ogun-tabi-ip:9092 àkọọlẹ lvl=aṣiṣe

Aṣayan pẹlu httpOut

Ṣe afihan data ni opo gigun ti isiyi:

|httpOut('something')

Wo (gba): ogun-tabi-ip: 9092 / kapacitor / v1 / awọn iṣẹ-ṣiṣe / task_name / nkankan

Ilana ipaniyan

  • Iṣẹ-ṣiṣe kọọkan pada igi ipaniyan pẹlu awọn nọmba to wulo ni ọna kika awonya.
  • Ya kan Àkọsílẹ aami.
  • Lẹẹmọ sinu oluwo, gbadun.

Nibo miiran ti o le gba rake?

timestamp ni influxdb lori kikọ

Fun apẹẹrẹ, a ṣeto itaniji fun apao awọn ibeere fun wakati kan (ẹgbẹBy(1h)) ati pe a fẹ lati ṣe igbasilẹ titaniji ti o waye ni influxdb (lati fi ẹwa han otitọ iṣoro naa lori aworan ni grafana).

influxDBout () yoo kọ iye akoko lati gbigbọn si timestamp; ni ibamu, aaye ti o wa lori chart yoo kọ tẹlẹ / nigbamii ju gbigbọn ti de.

Nigbati o ba nilo deede: a ṣiṣẹ ni ayika iṣoro yii nipa pipe oluṣakoso aṣa, eyiti yoo kọ data si influxdb pẹlu aami akoko lọwọlọwọ.

docker, kọ ati imuṣiṣẹ

Ni ibẹrẹ, kapacitor le gbe awọn iṣẹ-ṣiṣe, awọn awoṣe ati awọn olutọju lati inu iwe-itọsọna ti a pato ninu iṣeto ni [fifuye] Àkọsílẹ.

Lati ṣẹda iṣẹ-ṣiṣe ti o tọ, o nilo awọn nkan wọnyi:

  1. Orukọ faili – gbooro si id/orukọ iwe afọwọkọ
  2. Iru - ṣiṣan / ipele
  3. dbrp – Koko lati tọka iru data + eto imulo ti iwe afọwọkọ nṣiṣẹ ninu (dbrp “olupese.” “autogen”)

Ti iṣẹ-ṣiṣe ipele kan ko ba ni laini pẹlu dbrp, gbogbo iṣẹ naa yoo kọ lati bẹrẹ ati pe yoo kọ nipa rẹ ni otitọ ninu akọọlẹ.

Ni chronograf, ni ilodi si, laini yii ko yẹ ki o wa; ko gba nipasẹ wiwo ati ṣe ipilẹṣẹ aṣiṣe.

Gige nigbati o ba n kọ eiyan kan: Dockerfile jade pẹlu -1 ti awọn laini ba wa pẹlu //.+dbrp, eyiti yoo gba ọ laaye lati loye lẹsẹkẹsẹ idi fun ikuna nigbati o ba n pejọ kọ.

darapọ mọ ọkan si ọpọlọpọ

Apẹẹrẹ iṣẹ-ṣiṣe: o nilo lati mu ipin 95th ti akoko iṣẹ iṣẹ fun ọsẹ kan, ṣe afiwe iṣẹju kọọkan ti 10 to kẹhin pẹlu iye yii.

O ko le ṣe idapọ ọkan-si-ọpọlọpọ, kẹhin / tumosi / agbedemeji lori ẹgbẹ kan ti awọn aaye yi oju ipade sinu ṣiṣan, aṣiṣe “ko le ṣafikun awọn egbegbe ti ko baamu ọmọ: ipele -> ṣiṣan” yoo pada.

Abajade ipele kan, bi oniyipada ninu ikosile lambda, ko tun paarọ rẹ.

Aṣayan wa lati ṣafipamọ awọn nọmba pataki lati ipele akọkọ si faili nipasẹ udf ati fifuye faili yii nipasẹ fifuye ẹgbẹ.

Kini a yanju pẹlu eyi?

A ni awọn olupese hotẹẹli to bii 100, ọkọọkan wọn le ni awọn asopọ pupọ, jẹ ki a pe ni ikanni kan. O fẹrẹ to 300 ti awọn ikanni wọnyi, ọkọọkan awọn ikanni le ṣubu ni pipa. Ninu gbogbo awọn metiriki ti o gbasilẹ, a yoo ṣe atẹle oṣuwọn aṣiṣe (awọn ibeere ati awọn aṣiṣe).

Kilode ti kii ṣe grafana?

Awọn titaniji aṣiṣe ni tunto ni Grafana ni ọpọlọpọ awọn alailanfani. Diẹ ninu jẹ pataki, diẹ ninu awọn ti o le pa oju rẹ si, da lori ipo naa.

Grafana ko mọ bi o ṣe le ṣe iṣiro laarin awọn wiwọn + titaniji, ṣugbọn a nilo oṣuwọn kan (awọn ibeere-aṣiṣe)/awọn ibeere.

Awọn aṣiṣe dabi buburu:

Awọn ẹtan fun sisẹ awọn metiriki ni Kapacitor

Ati pe o kere si ibi nigba wiwo pẹlu awọn ibeere aṣeyọri:

Awọn ẹtan fun sisẹ awọn metiriki ni Kapacitor

O dara, a le ṣaju-iṣiro oṣuwọn ninu iṣẹ ṣaaju grafana, ati ni awọn igba miiran eyi yoo ṣiṣẹ. Ṣugbọn kii ṣe ninu tiwa, nitori ... fun ikanni kọọkan ni ipin tirẹ ni “deede”, ati awọn itaniji ṣiṣẹ ni ibamu si awọn iye aimi (a wa wọn pẹlu oju wa, yi wọn pada ti awọn itaniji loorekoore ba wa).

Iwọnyi jẹ apẹẹrẹ ti “deede” fun awọn ikanni oriṣiriṣi:

Awọn ẹtan fun sisẹ awọn metiriki ni Kapacitor

Awọn ẹtan fun sisẹ awọn metiriki ni Kapacitor

A foju aaye ti tẹlẹ ati ro pe aworan “deede” jẹ iru fun gbogbo awọn olupese. Bayi ohun gbogbo dara, ati pe a le gba pẹlu awọn titaniji ni grafana?
A le, ṣugbọn a ko fẹ gaan, nitori a ni lati yan ọkan ninu awọn aṣayan:
a) ṣe ọpọlọpọ awọn aworan fun ikanni kọọkan lọtọ (ati ni irora tẹle wọn)
b) fi apẹrẹ kan silẹ pẹlu gbogbo awọn ikanni (ki o padanu ni awọn laini awọ ati awọn itaniji ti adani)

Awọn ẹtan fun sisẹ awọn metiriki ni Kapacitor

Bawo ni o ṣe ṣe?

Lẹẹkansi, apẹẹrẹ ibẹrẹ ti o dara wa ninu iwe naa (Iṣiro awọn oṣuwọn kọja jara ti o darapọ), le ti wa ni yoju ni tabi ya bi ipilẹ ni iru isoro.

Ohun ti a ṣe ni ipari:

  • darapọ mọ jara meji ni awọn wakati diẹ, ṣiṣe akojọpọ nipasẹ awọn ikanni;
  • fọwọsi jara nipasẹ ẹgbẹ ti ko ba si data;
  • ṣe afiwe agbedemeji ti awọn iṣẹju 10 to kẹhin pẹlu data iṣaaju;
  • a pariwo ti a ba ri nkan;
  • a kọ awọn oṣuwọn iṣiro ati awọn itaniji ti o waye ni influxdb;
  • firanṣẹ ifiranṣẹ to wulo lati lọra.

Ni ero mi, a ṣakoso lati ṣaṣeyọri ohun gbogbo ti a fẹ lati gba ni ipari (ati paapaa diẹ sii pẹlu awọn olutọju aṣa) bi ẹwa bi o ti ṣee.

O le wo github.com apẹẹrẹ koodu и iyika kekere (graphviz) Abajade akosile.

Apẹẹrẹ ti koodu abajade:

dbrp "supplier"."autogen"
var name = 'requests.rate'
var grafana_dash = 'pczpmYZWU/mydashboard'
var grafana_panel = '26'
var period = 8h
var todayPeriod = 10m
var every = 1m
var warnAlert = 15
var warnReset = 5
var reqQuery = 'SELECT sum("count") AS value FROM "supplier"."autogen"."requests"'
var errQuery = 'SELECT sum("count") AS value FROM "supplier"."autogen"."errors"'

var prevErr = batch
    |query(errQuery)
        .period(period)
        .every(every)
        .groupBy(1m, 'channel', 'supplier')

var prevReq = batch
    |query(reqQuery)
        .period(period)
        .every(every)
        .groupBy(1m, 'channel', 'supplier')

var rates = prevReq
    |join(prevErr)
        .as('req', 'err')
        .tolerance(1m)
        .fill('null')
    // заполняем значения нулями, если их не было
    |default()
        .field('err.value', 0.0)
        .field('req.value', 0.0)
    // if в lambda: считаем рейт, только если ошибки были
    |eval(lambda: if("err.value" > 0, 100.0 * (float("req.value") - float("err.value")) / float("req.value"), 100.0))
        .as('rate')

// записываем посчитанные значения в инфлюкс
rates
    |influxDBOut()
        .quiet()
        .create()
        .database('kapacitor')
        .retentionPolicy('autogen')
        .measurement('rates')

// выбираем данные за последние 10 минут, считаем медиану
var todayRate = rates
    |where(lambda: duration((unixNano(now()) - unixNano("time")) / 1000, 1u) < todayPeriod)
    |median('rate')
        .as('median')

var prevRate = rates
    |median('rate')
        .as('median')

var joined = todayRate
    |join(prevRate)
        .as('today', 'prev')
    |httpOut('join')

var trigger = joined
    |alert()
        .warn(lambda: ("prev.median" - "today.median") > warnAlert)
        .warnReset(lambda: ("prev.median" - "today.median") < warnReset)
        .flapping(0.25, 0.5)
        .stateChangesOnly()
        // собираем в message ссылку на график дашборда графаны
        .message(
            '{{ .Level }}: {{ index .Tags "channel" }} err/req ratio ({{ index .Tags "supplier" }})
{{ if eq .Level "OK" }}It is ok now{{ else }}
'+string(todayPeriod)+' median is {{ index .Fields "today.median" | printf "%0.2f" }}%, by previous '+string(period)+' is {{ index .Fields "prev.median" | printf "%0.2f" }}%{{ end }}
http://grafana.ostrovok.in/d/'+string(grafana_dash)+
'?var-supplier={{ index .Tags "supplier" }}&var-channel={{ index .Tags "channel" }}&panelId='+string(grafana_panel)+'&fullscreen&tz=UTC%2B03%3A00'
        )
        .id('{{ index .Tags "name" }}/{{ index .Tags "channel" }}')
        .levelTag('level')
        .messageField('message')
        .durationField('duration')
        .topic('slack_graph')

// "today.median" дублируем как "value", также пишем в инфлюкс остальные филды алерта (keep)
trigger
    |eval(lambda: "today.median")
        .as('value')
        .keep()
    |influxDBOut()
        .quiet()
        .create()
        .database('kapacitor')
        .retentionPolicy('autogen')
        .measurement('alerts')
        .tag('alertName', name)

Kini ipari?

Kapacitor jẹ nla ni ṣiṣe awọn titaniji ibojuwo pẹlu akojọpọ awọn akojọpọ, ṣiṣe awọn iṣiro afikun ti o da lori awọn metiriki ti o ti gbasilẹ tẹlẹ, ṣiṣe awọn iṣe aṣa ati awọn iwe afọwọkọ nṣiṣẹ (udf).

Idanwo si titẹsi ko ga pupọ - gbiyanju rẹ ti grafana tabi awọn irinṣẹ miiran ko ni itẹlọrun awọn ifẹ rẹ ni kikun.

orisun: www.habr.com

Fi ọrọìwòye kun