Cleasan airson làimhseachadh metrics ann an Kapacitor

As dualtaiche, an-diugh chan eil duine a 'faighneachd carson a tha e riatanach a' cruinneachadh seirbheis metrics. Is e an ath cheum loidsigeach rabhadh a chuir air dòigh airson na meatrach cruinnichte, a bheir fios mu ghluasadan sam bith san dàta ann an seanalan a tha iomchaidh dhut (post, Slack, Telegram). Anns an t-seirbheis glèidhidh taigh-òsta air-loidhne Ostrovok.ru tha a h-uile meatrach de na seirbheisean againn air an dòrtadh a-steach do InfluxDB agus air an taisbeanadh ann an Grafana, agus tha rabhadh bunaiteach air a rèiteachadh an sin cuideachd. Airson gnìomhan mar “feumaidh tu rudeigin obrachadh a-mach agus coimeas a dhèanamh ris,” bidh sinn a’ cleachdadh Kapacitor.

Cleasan airson làimhseachadh metrics ann an Kapacitor
Tha Kapacitor mar phàirt den stac TICK as urrainn metrics a phròiseasadh bho InfluxDB. Faodaidh e grunn tomhasan a cheangal ri chèile (ceangal), obrachadh a-mach rudeigin feumail bhon dàta a fhuaireadh, an toradh a sgrìobhadh air ais gu InfluxDB, fios a chuir gu Slack / Telegram / post.

Tha an stac gu lèir fionnar agus mionaideach sgrìobhainnean, ach bidh an-còmhnaidh rudan feumail ann nach eil air an comharrachadh gu soilleir anns na leabhraichean-làimhe. San artaigil seo, chuir mi romhpa grunn mholaidhean feumail, neo-fhollaiseach a chruinneachadh (tha mìneachadh air co-chòrdadh bunaiteach TICKscipt an seo) agus seall mar a ghabhas an cur an sàs a’ cleachdadh eisimpleir de bhith a’ fuasgladh aon de na duilgheadasan againn.

Leamamaid!

fleòdradh & int, mearachdan àireamhachaidh

Duilgheadas gu tur àbhaisteach, air fhuasgladh tro chasan:

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

A' cleachdadh default()

Mura h-eil taga / raon air a lìonadh a-steach, bidh mearachdan àireamhachaidh a’ tachairt:

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

lìon a-steach ballrachd (a-staigh vs taobh a-muigh)

Gu gnàthach, tilgidh join air falbh puingean far nach eil dàta ann (a-staigh).
Le lìonadh ('null'), thèid ceangal a-muigh a dhèanamh, às deidh sin feumaidh tu bunait () a dhèanamh agus na luachan falamh a lìonadh:

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

Tha nuance fhathast an seo. Anns an eisimpleir gu h-àrd, ma tha aon den t-sreath (res1 no res2) falamh, bidh an t-sreath a thig às (dàta) falamh cuideachd. Tha grunn thiogaidean air a’ chuspair seo air Github (1633, 1871, 6967) - tha sinn a’ feitheamh ri fuasglaidhean agus a’ fulang beagan.

A’ cleachdadh shuidheachaidhean ann an àireamhachadh (ma tha e ann an lambda)

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

Còig mionaidean mu dheireadh bhon loidhne-phìoban airson na h-ùine

Mar eisimpleir, feumaidh tu coimeas a dhèanamh eadar luachan nan còig mionaidean mu dheireadh leis an t-seachdain roimhe. Faodaidh tu dà bhaidse dàta a ghabhail ann an dà bhaidse eadar-dhealaichte no pàirt den dàta a thoirt a-mach à ùine nas motha:

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

Is e roghainn eile airson na còig mionaidean mu dheireadh BarrierNode a chleachdadh, a bhios a’ gearradh dheth dàta ron ùine ainmichte:

|barrier()
        .period(5m)

Eisimpleirean de bhith a 'cleachdadh teamplaidean Go ann an teachdaireachd

Bidh teamplaidean a 'freagairt ris an fhòrmat bhon phacaid teacs.templateGu h-ìosal tha cuid de thòimhseachain a thachair gu tric.

ma tha - eile

Bidh sinn a’ cur rudan ann an òrdugh agus cha bhith sinn a’ brosnachadh dhaoine le teacsa a-rithist:

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

Dà fhigear às deidh a’ phuing deicheach san teachdaireachd

Ag adhartachadh leughadh na teachdaireachd:

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

A’ leudachadh caochladairean ann an teachdaireachd

Bidh sinn a’ taisbeanadh barrachd fiosrachaidh anns an teachdaireachd gus a’ cheist “Carson a tha e ag èigheach” a fhreagairt?

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

Aithniche rabhaidh gun samhail

Tha seo riatanach nuair a tha barrachd air aon bhuidheann san dàta, air neo cha tèid ach aon rabhadh a chruthachadh:

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

Neach-làimhseachaidh gnàthaichte

Tha an liosta mhòr de luchd-làimhseachaidh a’ toirt a-steach exec, a leigeas leat do sgriobt a chuir an gnìomh leis na paramadairean a chaidh seachad (stdin) - cruthachalachd agus gun dad a bharrachd!

Is e aon de na cleachdaidhean againn sgriobt Python beag airson fiosan a chuir gu slack.
An toiseach, bha sinn airson dealbh grafana le dìon cead a chuir ann an teachdaireachd. Às deidh sin, sgrìobh OK san t-snàthainn chun rabhadh roimhe bhon aon bhuidheann, agus chan ann mar theachdaireachd air leth. Beagan nas fhaide air adhart - cuir ris an teachdaireachd am mearachd as cumanta anns na X mionaidean mu dheireadh.

Is e cuspair air leth conaltradh le seirbheisean eile agus gnìomhan sam bith air an tòiseachadh le rabhadh (dìreach ma dh’ obraicheas an sgrùdadh agad math gu leòr).
Eisimpleir de thuairisgeul làimhseachaidh, far a bheil slack_handler.py na sgriobt fèin-sgrìobhte againn:

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

Ciamar a debug?

Roghainn le toradh log

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

Freiceadan (cli): kapacitor -url aoigheachd-or-ip: 9092 logaichean lvl = mearachd

Roghainn le httpOut

A’ sealltainn dàta san loidhne-phìoban làithreach:

|httpOut('something')

Coimhead (faigh): aoigheachd-or-ip:9092/kapacitor/v1/tasks/task_name/rudeigin

Sgeama cur gu bàs

  • Bidh gach gnìomh a’ tilleadh craobh-chur gu bàs le àireamhan feumail anns a’ chruth graffviz.
  • Gabh bloc dotag.
  • Cuir a-steach e san t-seallaidh, tlachd.

Càite eile am faigh thu ràcan?

stampa-ama ann an influxdb air sgrìobhadh air ais

Mar eisimpleir, stèidhich sinn rabhadh airson an t-suim de dh'iarrtasan san uair (groupBy(1h)) agus tha sinn airson an rabhadh a thachair ann an influxdb a chlàradh (gus sealltainn gu h-àlainn fìrinn na duilgheadas air a 'ghraf ann an grafana).

influxDBOut () sgrìobhaidh e an luach ùine bhon rabhadh chun an stampa-ama; a rèir sin, thèid a’ phuing air a’ chairt a sgrìobhadh nas tràithe/nas fhaide na thàinig an rabhadh.

Nuair a tha feum air cruinneas: bidh sinn ag obair timcheall air an duilgheadas seo le bhith a’ gairm inneal-làimhseachaidh àbhaisteach, a sgrìobhas dàta gu influxdb leis an stampa-ama làithreach.

docker, togail agus cleachdadh

Aig toiseach tòiseachaidh, faodaidh kapacitor gnìomhan, teamplaidean agus luchd-làimhseachaidh a luchdachadh bhon eòlaire a tha air a shònrachadh anns an config sa bhloc [load].

Gus obair a chruthachadh gu ceart, feumaidh tu na rudan a leanas:

  1. Ainm faidhle - air a leudachadh gu ID / ainm an sgriobt
  2. Seòrsa - sruth / baidse
  3. dbrp - prìomh fhacal gus innse dè an stòr-dàta + poileasaidh a tha an sgriobt a’ ruith a-steach (dbrp “solaraiche.” “autogen”)

Mura h-eil loidhne le dbrp ann an cuid de ghnìomh baidse, diùlt an t-seirbheis gu lèir tòiseachadh agus sgrìobhaidh i gu h-onarach mu dheidhinn sa log.

Ann an chronograf, air an làimh eile, cha bu chòir an loidhne seo a bhith ann; chan eilear a 'gabhail ris tron ​​​​eadar-aghaidh agus a' cruthachadh mearachd.

Hack nuair a bhios tu a’ togail soitheach: Bidh Dockerfile a’ dol a-mach le -1 ma tha loidhnichean ann le //.+dbrp, a leigeas leat tuigsinn sa bhad an adhbhar airson an fhàiligeadh nuair a bhios tu a’ cruinneachadh an togalaich.

ceangail aon ri mòran

Eisimpleir gnìomh: feumaidh tu an 95mh ceudad de ùine obrachaidh na seirbheis a ghabhail airson seachdain, dèan coimeas eadar gach mionaid den 10 mu dheireadh leis an luach seo.

Chan urrainn dhut ceangal aon-ri-iomadh a dhèanamh, mu dheireadh / cuibheasach / meadhanach thairis air buidheann de phuingean a’ tionndadh an nód gu sruth, a ’mhearachd“ chan urrainn dha oirean mì-fhreagarrach pàiste a chuir ris: batch -> sruthan ”air ais.

Chan eil toradh baidse, mar chaochladair ann an abairt lambda, air a chuir na àite cuideachd.

Tha roghainn ann na h-àireamhan riatanach a shàbhaladh bhon chiad bhaidse gu faidhle tro udf agus am faidhle seo a luchdachadh tro sideload.

Dè a dh’ fhuasglas sinn le seo?

Tha timcheall air 100 solaraiche taigh-òsta againn, faodaidh grunn cheanglaichean a bhith aig gach fear dhiubh, canaidh sinn seanal ris. Tha timcheall air 300 de na seanalan sin ann, faodaidh gach aon de na seanalan tuiteam dheth. De na meatrach clàraichte uile, cumaidh sinn sùil air an ìre mearachd (iarrtasan agus mearachdan).

Carson nach grafana?

Tha grunn eas-bhuannachdan aig rabhaidhean mearachd a chaidh an rèiteachadh ann an Grafana. Tha cuid deatamach, cuid as urrainn dhut do shùilean a dhùnadh, a rèir an t-suidheachaidh.

Chan eil fios aig Grafana mar a nì thu àireamhachadh eadar tomhais + rabhadh, ach feumaidh sinn ìre (iarrtasan-mearachdan) / iarrtasan.

Tha coltas dona air na mearachdan:

Cleasan airson làimhseachadh metrics ann an Kapacitor

Agus nas lugha de dhroch nuair a thathar ga fhaicinn le iarrtasan soirbheachail:

Cleasan airson làimhseachadh metrics ann an Kapacitor

Gu ceart, is urrainn dhuinn an ìre san t-seirbheis ro-àireamhachadh ro grafana, agus ann an cuid de chùisean obraichidh seo. Ach chan ann nar linne, oir... airson gach seanal tha a cho-mheas fhèin air a mheas “àbhaisteach”, agus bidh rabhaidhean ag obair a rèir luachan statach (bidh sinn a’ coimhead air an son le ar sùilean, atharraich iad ma bhios rabhaidhean tric ann).

Seo eisimpleirean de “àbhaisteach” airson diofar shianalan:

Cleasan airson làimhseachadh metrics ann an Kapacitor

Cleasan airson làimhseachadh metrics ann an Kapacitor

Bidh sinn a’ seachnadh a’ phuing roimhe agus a’ gabhail ris gu bheil an dealbh “àbhaisteach” coltach ris a h-uile solaraiche. A-nis tha a h-uile dad gu math, agus gheibh sinn seachad le rabhaidhean ann an grafana?
Faodaidh sinn, ach chan eil sinn ag iarraidh, oir feumaidh sinn aon de na roghainnean a thaghadh:
a) dèan tòrr ghrafaichean airson gach seanail air leth (agus gu pianail nan cois)
b) fàg aon chairt leis a h-uile seanal (agus a dhol air chall anns na loidhnichean dathte agus rabhaidhean gnàthaichte)

Cleasan airson làimhseachadh metrics ann an Kapacitor

Ciamar a rinn thu e?

A-rithist, tha deagh eisimpleir tòiseachaidh anns na sgrìobhainnean (Ag obrachadh a-mach ìrean thar sreath ceangailte), faodar sùil a thoirt air no a ghabhail mar bhunait ann an duilgheadasan coltach ris.

Na rinn sinn mu dheireadh:

  • gabh còmhla ri dà shreath ann am beagan uairean a thìde, gan cruinneachadh a rèir seanalan;
  • lìon a-steach an t-sreath le buidheann mura robh dàta ann;
  • coimeas a dhèanamh eadar meadhan nan 10 mionaidean mu dheireadh le dàta roimhe;
  • bidh sinn ag èigheach ma lorgas sinn rudeigin;
  • bidh sinn a’ sgrìobhadh na h-ìrean àireamhaichte agus rabhaidhean a thachair ann an influxdb;
  • cuir teachdaireachd feumail gu slack.

Nam bheachd-sa, chaidh againn air a h-uile dad a bha sinn ag iarraidh a choileanadh aig an deireadh (agus eadhon beagan a bharrachd le làimhseachadh àbhaisteach) cho breagha ‘s a ghabhas.

Faodaidh tu coimhead air github.com eisimpleir còd и cuairt bheag (graphviz) an sgriobt mar thoradh air.

Eisimpleir den chòd a thàinig às:

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)

Dè an co-dhùnadh a th’ ann?

Tha Kapacitor air leth math air a bhith a’ coileanadh rabhaidhean sgrùdaidh le dòrlach de bhuidhnean, a’ dèanamh àireamhachadh a bharrachd stèidhichte air meatrach a chaidh a chlàradh mu thràth, a’ coileanadh gnìomhan àbhaisteach agus a’ ruith sgriobtaichean (udf).

Chan eil an cnap-starra airson faighinn a-steach glè àrd - feuch e mura h-eil grafana no innealan eile a’ sàsachadh do mhiannan gu tur.

Source: www.habr.com

Cuir beachd ann