Mga limbong alang sa pagproseso sa mga sukatan sa Kapacitor

Lagmit, karon walay nangutana kon nganong gikinahanglan ang pagkolekta sa mga sukdanan sa serbisyo. Ang sunod nga lohikal nga lakang mao ang pag-set up sa usa ka alerto alang sa nakolekta nga mga sukatan, nga magpahibalo bahin sa bisan unsang mga pagtipas sa datos sa mga channel nga kombenyente alang kanimo (mail, Slack, Telegram). Sa online nga serbisyo sa pag-book sa hotel Ostrovok.ru ang tanang metrics sa among mga serbisyo gibubo ngadto sa InfluxDB ug gipakita sa Grafana, ug ang basic alerting gi-configure usab didto. Para sa mga buluhaton sama sa "kinahanglan nimo nga kuwentahon ang usa ka butang ug itandi niini," among gigamit ang Kapacitor.

Mga limbong alang sa pagproseso sa mga sukatan sa Kapacitor
Ang Kapacitor kabahin sa TICK stack nga makaproseso sa metrics gikan sa InfluxDB. Mahimo kini nga magkonektar sa daghang mga pagsukod nga magkauban (pag-apil), kuwentahon ang usa ka butang nga mapuslanon gikan sa nadawat nga datos, isulat ang resulta balik sa InfluxDB, magpadala usa ka alerto sa Slack / Telegram / mail.

Ang tibuok stack kay bugnaw ug detalyado dokumentasyon, apan adunay kanunay nga mapuslanon nga mga butang nga dili klaro nga gipakita sa mga manwal. Niini nga artikulo, nakahukom ko nga mangolekta og daghang mapuslanon, dili klaro nga mga tip (ang sukaranan nga syntax sa TICKscipt gihulagway dinhi) ug ipakita kon sa unsang paagi kini magamit gamit ang usa ka pananglitan sa pagsulbad sa usa sa atong mga problema.

Tana!

float & int, mga sayop sa pagkalkula

Usa ka hingpit nga sumbanan nga problema, masulbad pinaagi sa mga kasta:

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

Gigamit ang default()

Kung ang usa ka tag/field wala mapuno, ang mga sayup sa pagkalkula mahitabo:

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

pun-a ang pag-apil (inner vs outer)

Sa kasagaran, ang pag-apil magwagtang sa mga punto diin walay data (sulod).
Uban sa pagpuno ('null'), usa ka gawas nga pag-apil ang himuon, pagkahuman kinahanglan nimo nga buhaton ang usa ka default () ug pun-on ang mga walay sulod nga kantidad:

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

Adunay gihapon usa ka nuance dinhi. Sa pananglitan sa ibabaw, kung ang usa sa mga serye (res1 o res2) walay sulod, ang resulta nga serye (data) mahimong walay sulod. Adunay daghang mga tiket sa kini nga hilisgutan sa Github (1633, 1871, 6967) - naghulat kami alang sa mga pag-ayo ug gamay nga pag-antos.

Paggamit sa mga kondisyon sa mga kalkulasyon (kung sa lambda)

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

Katapusan nga lima ka minuto gikan sa pipeline alang sa panahon

Pananglitan, kinahanglan nimo itandi ang mga kantidad sa miaging lima ka minuto sa miaging semana. Mahimo nimong kuhaon ang duha ka hugpong sa datos sa duha ka managlahing batch o pagkuha sa bahin sa datos gikan sa mas dako nga panahon:

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

Usa ka alternatibo alang sa katapusang lima ka minuto mao ang paggamit sa usa ka BarrierNode, nga nagputol sa datos sa wala pa ang gitakda nga oras:

|barrier()
        .period(5m)

Mga pananglitan sa paggamit sa mga template sa Go sa mensahe

Ang mga template katumbas sa format gikan sa package text.templateSa ubos mao ang pipila nga kanunay nga makit-an nga mga puzzle.

kung-unsa pa

Gihan-ay namo ang mga butang ug dili na mag-trigger sa mga tawo sa text sa makausa pa:

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

Duha ka digit human sa decimal nga punto sa mensahe

Pagpauswag sa pagkabasa sa mensahe:

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

Pagpalapad sa mga variable sa mensahe

Nagpakita kami og dugang nga impormasyon sa mensahe aron matubag ang pangutana nga "Nganong nagsinggit"?

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

Talagsaon nga alert identifier

Kini usa ka kinahanglanon nga butang kung adunay labaw pa sa usa ka grupo sa datos, kung dili usa ra ka alerto ang mahimo:

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

Custom nga handler

Ang dako nga lista sa mga handler naglakip sa exec, nga nagtugot kanimo sa pagpatuman sa imong script sa mga gipasa nga mga parameter (stdin) - pagkamamugnaon ug wala na!

Usa sa among mga kostumbre mao ang usa ka gamay nga script sa Python alang sa pagpadala mga pahibalo aron maluya.
Sa sinugdan, gusto namong magpadala ug grafana nga protektado sa pagtugot nga hulagway sa usa ka mensahe. Pagkahuman, isulat ang OK sa hilo sa miaging alerto gikan sa parehas nga grupo, ug dili ingon usa ka lahi nga mensahe. Usa ka gamay nga ulahi - idugang sa mensahe ang labing kasagaran nga sayup sa katapusan nga X minuto.

Ang usa ka bulag nga hilisgutan mao ang komunikasyon sa ubang mga serbisyo ug bisan unsang mga aksyon nga gisugdan pinaagi sa usa ka alerto (kung ang imong pag-monitor lang molihok nga maayo).
Usa ka pananglitan sa paghulagway sa handler, diin ang slack_handler.py mao ang among kaugalingon nga sinulat nga script:

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"]

Unsaon pag-debug?

Opsyon nga adunay log output

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

Tan-awa (cli): kapacitor -url host-o-ip:9092 logs lvl=error

Opsyon uban sa httpOut

Nagpakita sa datos sa kasamtangan nga pipeline:

|httpOut('something')

Tan-awa (pagkuha): host-o-ip:9092/kapacitor/v1/tasks/task_name/something

Iskema sa pagpatuman

  • Ang matag buluhaton nagbalik sa usa ka punoan sa pagpatay nga adunay mapuslanon nga mga numero sa format graphviz.
  • Pagkuha usa ka bloke tulbok.
  • Idikit kini sa viewer, malingaw.

Asa man ka makakuha ug rake?

timestamp sa influxdb sa writeback

Pananglitan, nagbutang kami usa ka alerto alang sa kantidad sa mga hangyo matag oras (groupBy (1h)) ug gusto nga irekord ang alerto nga nahitabo sa influxdb (aron nindot nga ipakita ang kamatuoran sa problema sa graph sa grafana).

influxDBOut() isulat ang kantidad sa oras gikan sa alerto hangtod sa timestamp; busa, ang punto sa tsart isulat sa sayo pa / ulahi kaysa sa pag-abot sa alerto.

Kung gikinahanglan ang pagkatukma: gitrabaho namo kini nga problema pinaagi sa pagtawag sa usa ka custom handler, nga mosulat sa data ngadto sa influxdb uban sa kasamtangan nga timestamp.

docker, pagtukod ug pag-deploy

Sa pagsugod, ang kapacitor maka-load sa mga buluhaton, templates ug handler gikan sa direktoryo nga gitakda sa config sa [load] block.

Aron sa husto nga paghimo sa usa ka buluhaton, kinahanglan nimo ang mosunod nga mga butang:

  1. Ngalan sa file - gipalapdan sa script id/ngalan
  2. Type – stream/batch
  3. dbrp – keyword aron ipakita kung unsang database + polisiya ang gipadagan sa script (dbrp β€œsupplier.” β€œautogen”)

Kung ang pila ka buluhaton sa batch wala’y linya nga adunay dbrp, ang tibuuk nga serbisyo magdumili sa pagsugod ug matinud-anon nga isulat kini sa log.

Sa chronograf, sa sukwahi, kini nga linya kinahanglan dili maglungtad; dili kini dawaton pinaagi sa interface ug makamugna og usa ka sayup.

Pag-hack sa paghimo og usa ka sudlanan: Ang Dockerfile mogawas nga adunay -1 kung adunay mga linya nga adunay //.+dbrp, nga magtugot kanimo nga masabtan dayon ang hinungdan sa pagkapakyas sa pag-assemble sa pagtukod.

apil sa usa ngadto sa daghan

Pananglitan nga buluhaton: kinahanglan nimo nga kuhaon ang ika-95 nga porsyento sa oras sa pag-operate sa serbisyo sulod sa usa ka semana, itandi ang matag minuto sa katapusang 10 sa kini nga kantidad.

Dili nimo mahimo ang usa-sa-daghan nga pag-apil, ang katapusan / mean / median sa usa ka grupo sa mga punto nga nahimo ang node nga usa ka sapa, ang sayup nga "dili makadugang sa mga bata nga dili magkatugma nga mga sulud: batch -> sapa" ibalik.

Ang resulta sa usa ka batch, isip usa ka variable sa usa ka lambda nga ekspresyon, dili usab ilisan.

Adunay usa ka kapilian sa pagluwas sa gikinahanglan nga mga numero gikan sa unang batch ngadto sa usa ka file pinaagi sa udf ug load niini nga file pinaagi sa sideload.

Unsa ang atong nasulbad niini?

Adunay kami mga 100 nga mga supplier sa hotel, ang matag usa kanila adunay daghang mga koneksyon, tawgon kini nga usa ka channel. Adunay gibana-bana nga 300 niini nga mga kanal, ang matag usa sa mga kanal mahimong mahulog. Sa tanan nga natala nga sukatan, among bantayan ang rate sa sayup (mga hangyo ug mga sayup).

Nganong dili grafana?

Ang mga alerto sa sayup nga gi-configure sa Grafana adunay daghang mga kakulangan. Ang uban kritikal, ang uban mahimo nimong piyongon ang imong mga mata, depende sa sitwasyon.

Wala mahibal-an ni Grafana kung giunsa ang pagkalkulo tali sa mga pagsukod + pag-alerto, apan kinahanglan namon ang usa ka rate (mga hangyo-sayup) / hangyo.

Ang mga sayup tan-awon nga daotan:

Mga limbong alang sa pagproseso sa mga sukatan sa Kapacitor

Ug dili kaayo daotan kung tan-awon uban ang malampuson nga mga hangyo:

Mga limbong alang sa pagproseso sa mga sukatan sa Kapacitor

Okay, mahimo namong makalkula ang rate sa serbisyo sa wala pa ang grafana, ug sa pipila ka mga kaso kini molihok. Pero dili sa atoa, kay... alang sa matag channel ang kaugalingon nga ratio giisip nga "normal", ug ang mga alerto molihok sumala sa static nga mga kantidad (gipangita namon sila sa among mga mata, usba kini kung adunay kanunay nga mga alerto).

Kini ang mga pananglitan sa "normal" alang sa lainlaing mga channel:

Mga limbong alang sa pagproseso sa mga sukatan sa Kapacitor

Mga limbong alang sa pagproseso sa mga sukatan sa Kapacitor

Gibalewala namo ang miaging punto ug gihunahuna nga ang "normal" nga litrato parehas sa tanan nga mga supplier. Karon maayo na ang tanan, ug makapadayon kami sa mga alerto sa grafana?
Mahimo namon, apan dili gyud namon gusto, tungod kay kinahanglan namon nga mopili usa sa mga kapilian:
a) paghimo og daghang mga graph alang sa matag channel nga gilain (ug sakit nga pag-uban kanila)
b) biyai ang usa ka tsart sa tanan nga mga kanal (ug mawala sa mabulukon nga mga linya ug gipahiangay nga mga alerto)

Mga limbong alang sa pagproseso sa mga sukatan sa Kapacitor

Giunsa nimo kini nahimo?

Pag-usab, adunay usa ka maayong panig-ingnan sa pagsugod sa dokumentasyon (Pagkuwenta sa mga bayranan sa giapil nga serye), mahimong tan-awon o himoong basehan sa susamang mga problema.

Unsa ang among gibuhat sa katapusan:

  • pag-apil sa duha ka serye sa pipila ka oras, paggrupo sa mga channel;
  • pun-a ang serye pinaagi sa grupo kung walay datos;
  • itandi ang median sa katapusang 10 ka minuto sa miaging datos;
  • kita mosinggit kon kita makakita og usa ka butang;
  • gisulat namo ang kalkulado nga mga rate ug mga alerto nga nahitabo sa influxdb;
  • magpadala usa ka mapuslanon nga mensahe sa paghinay.

Sa akong opinyon, nakahimo kami sa pagkab-ot sa tanan nga gusto namong makuha sa katapusan (ug bisan gamay pa uban sa custom handler) ingon ka nindot kutob sa mahimo.

Mahimo nimong tan-awon ang github.com pananglitan sa code ΠΈ gamay nga sirkito (graphviz) ang resulta nga script.

Usa ka pananglitan sa resulta nga code:

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)

Unsa ang konklusyon?

Ang Kapacitor maayo sa paghimo sa monitoring-alerto uban sa usa ka pundok sa mga grupo, paghimo og dugang nga mga kalkulasyon base sa natala na nga mga metrics, paghimo og custom nga mga aksyon ug running scripts (udf).

Ang babag sa pagsulod dili kaayo taas - sulayi kini kung ang grafana o uban pang mga himan dili hingpit nga makatagbaw sa imong mga gusto.

Source: www.habr.com

Idugang sa usa ka comment