Kapacitorдо метрикаларды иштетүү үчүн амалдар

Кыязы, бүгүнкү күндө эч ким эмне үчүн кызматтык көрсөткүчтөрдү чогултуу керек деп сурабайт. Кийинки логикалык кадам - ​​бул сиз үчүн ыңгайлуу каналдардагы (почта, Slack, Telegram) маалыматтардагы ар кандай четтөөлөр жөнүндө кабарлай турган, чогултулган көрсөткүчтөр үчүн эскертүү орнотуу. Мейманканага онлайн брондоо кызматында Ostrovok.ru биздин кызматтардын бардык көрсөткүчтөрү InfluxDBге куюлуп, Grafanaда көрсөтүлөт жана негизги эскертүүлөр да ошол жерде конфигурацияланган. "Бир нерсени эсептеп, аны менен салыштыруу керек" сыяктуу тапшырмалар үчүн биз Kapacitor колдонобуз.

Kapacitorдо метрикаларды иштетүү үчүн амалдар
Kapacitor InfluxDBден метрикаларды иштете алган TICK стекинин бир бөлүгү. Ал бир нече өлчөөлөрдү бириктире алат (кошулуу), алынган маалыматтардан пайдалуу нерсени эсептеп, натыйжаны кайра InfluxDBге жазып, Slack/Telegram/mailге эскертүү жөнөтө алат.

Бардык стек салкын жана деталдуу документтештирүү, бирок колдонмолордо ачык көрсөтүлбөгөн пайдалуу нерселер ар дайым болот. Бул макалада мен бир нече пайдалуу, ачык-айкын эмес кеңештерди чогултууну чечтим (TICKsciptтин негизги синтаксиси сүрөттөлөт. бул жерде) жана аларды кантип колдонсо болорун биздин көйгөйлөрүбүздүн бирин чечүүнүн мисалы аркылуу көрсөтүңүз.

Кеттик!

float & int, эсептөө каталары

Касталар аркылуу чечилген таптакыр стандарттуу маселе:

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

default() колдонуу

Эгер тег/талаа толтурулбаса, эсептөө каталары пайда болот:

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

кошулууну толтуруу (ички жана тышкы)

Демейки боюнча, кошулуу эч кандай маалымат жок пункттарды (ички) жокко чыгарат.
fill('null') менен сырткы кошулуу аткарылат, андан кийин сиз default() жасап, бош маанилерди толтурушуңуз керек:

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

Бул жерде дагы бир нюанс бар. Жогорудагы мисалда катарлардын бири (res1 же res2) бош болсо, натыйжада пайда болгон катар (маалыматтар) да бош болот. Githubда бул тема боюнча бир нече билеттер бар (1633, 1871, 6967) – оңдоону күтүп, бир аз кыйналып жатабыз.

Эсептөөдө шарттарды колдонуу (ламбдада болсо)

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

Мезгил үчүн куурдан акыркы беш мүнөт

Мисалы, акыркы беш мүнөттүн маанисин мурунку жума менен салыштыруу керек. Маалыматтын эки партиясын эки өзүнчө партияда ала аласыз же маалыматтын бир бөлүгүн чоңураак мезгилден чыгара аласыз:

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

Акыркы беш мүнөткө альтернатива катары көрсөтүлгөн убакытка чейин маалыматтарды өчүрүүчү BarrierNode колдонуу болот:

|barrier()
        .period(5m)

Кабарда Go шаблондорун колдонуунун мисалдары

Калыптар пакеттеги форматка туура келет text.templateТөмөндө көп жолуккан табышмактар ​​бар.

эгерде-башка

Биз нерселерди иретке келтиребиз жана адамдарды текст менен дагы бир жолу козгобойбуз:

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

Билдирүүдө ондук чекиттен кийин эки сан

Билдирүүнүн окууга жөндөмдүүлүгүн жакшыртуу:

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

Кабарда өзгөрмөлөрдү кеңейтүү

Биз "Эмне үчүн кыйкырып жатат" деген суроого жооп берүү үчүн билдирүүдө көбүрөөк маалымат көрсөтөбүз.

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

Уникалдуу эскертүү идентификатору

Бул маалыматтарда бир нече топ болгондо зарыл нерсе, антпесе бир гана эскертүү түзүлөт:

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

Ыңгайлаштырылган иштеткичтер

Иштетүүчүлөрдүн чоң тизмесине exec кирет, ал скриптиңизди өткөн параметрлер менен (stdin) аткарууга мүмкүндүк берет - чыгармачылык жана башка эч нерсе жок!

Биздин каада-салттарыбыздын бири - бул эскертмелерди жайбаракат жөнөтүү үчүн кичинекей Python скрипти.
Адегенде биз билдирүүдө авторизация менен корголгон графана сүрөтүн жөнөткүбүз келди. Андан кийин, өзүнчө билдирүү катары эмес, ошол эле топтун мурунку эскертүүсүнө ОК деп жазыңыз. Бир аздан кийин - билдирүүгө акыркы X мүнөттө эң көп кездешкен катаны кошуңуз.

Өзүнчө тема башка кызматтар менен байланыш жана эскертүү менен башталган ар кандай иш-аракеттер (эгерде сиздин мониторингиңиз жакшы иштесе гана).
Slack_handler.py биздин өз алдынча жазылган скрипт болгон иштеткичтин сүрөттөмөсүнө мисал:

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

Кантип оңдоо керек?

Таржымал чыгаруу менен опция

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

Watch (cli): capacitor -url хост-же-ip:9092 logs lvl=error

httpOut менен опция

Учурдагы куурдагы маалыматтарды көрсөтөт:

|httpOut('something')

Көрүү (алуу): хост-же-ip:9092/kapacitor/v1/tasks/task_name/nese

Аткаруу диаграммасы

  • Ар бир тапшырма форматта пайдалуу сандары бар аткаруу дарагын кайтарат graphviz.
  • Блок ал чекит.
  • Аны көрүүчүгө чаптаңыз, ырахат алуу.

Дагы кайдан тырмоо алса болот?

кайра жазуу боюнча influxdb ичинде убакыт белгиси

Мисалы, биз саатына суроо-талаптардын суммасы үчүн эскертүү орнотуп жатабыз (groupBy(1h)) жана influxdb ичинде болгон эскертүүнү жазгыбыз келет (графанадагы графикте маселенин фактысын сонун көрсөтүү үчүн).

influxDBOut() эскертүүдөн убакыт белгисине чейин убакыттын маанисин жазат, диаграммадагы чекит эскертүү келгенден эрте/кечирээк жазылат;

Тактык талап кылынганда: биз ыңгайлаштырылган иштеткичти чакыруу менен бул көйгөйдү чечебиз, ал учурдагы убакыт белгиси менен influxdbге маалыматтарды жазат.

докер, куруу жана жайылтуу

Ишке киргизүүдө конденсатор [жүктөө] блогундагы конфигурацияда көрсөтүлгөн каталогдон тапшырмаларды, шаблондорду жана иштеткичтерди жүктөй алат.

Туура тапшырманы түзүү үчүн, сизге төмөнкүлөр керек:

  1. Файлдын аты – скрипт идентификаторуна/атына кеңейтилген
  2. Түрү – агым/топтом
  3. dbrp – скрипт кайсы маалымат базасында + саясатта иштей турганын көрсөтүү үчүн ачкыч сөз (dbrp “жабдуучу.” “автоген”)

Эгерде кандайдыр бир партия тапшырмасында dbrp сызыгы жок болсо, бүткүл кызмат баштоодон баш тартат жана бул тууралуу журналга чынчылдык менен жазат.

Хронографта, тескерисинче, бул сызык болбошу керек, ал интерфейс аркылуу кабыл алынбайт жана ката жаратат.

Контейнерди курууда бузук: //.+dbrp сызыктары бар болсо, Dockerfile -1 менен чыгат, бул конструкцияны чогултууда катачылыктын себебин дароо түшүнүүгө мүмкүндүк берет.

көпкө кошул

Мисал тапшырма: сиз бир жума бою кызматтын иштөө убактысынын 95-проценттилин алышыңыз керек, акыркы 10 мүнөттүн ар бир мүнөтүн ушул маани менен салыштырыңыз.

Бирден көпкө кошулууну жасай албайсыз, чекиттер тобунун акыркы/орточо/медианасы түйүндү агымга айлантат, "баланын дал келбеген четтерин кошууга болбойт: партия -> агым" катасы кайтарылат.

Ламбда туюнтмасындагы өзгөрмө катары партиянын натыйжасы да алмаштырылбайт.

Биринчи партиядан керектүү сандарды udf аркылуу файлга сактоо жана бул файлды sideload аркылуу жүктөө мүмкүнчүлүгү бар.

Муну менен эмнени чечтик?

Бизде 100гө жакын мейманкана жеткирүүчүлөр бар, алардын ар бири бир нече байланышка ээ болушу мүмкүн, муну канал деп коёлу. Бул каналдардын 300гө жакыны бар, каналдардын ар бири кулап калышы мүмкүн. Бардык жазылган көрсөткүчтөрдүн ичинен биз ката ылдамдыгын (суроолор жана каталар) көзөмөлдөйбүз.

Эмне үчүн графана эмес?

Grafanaда конфигурацияланган ката эскертүүлөрүнүн бир нече кемчиликтери бар. Кээ бирлери сынчыл, кээ бирлери кырдаалга жараша көзүңүздү жумуп койсоңуз болот.

Grafana өлчөө + эскертүү ортосунда кантип эсептөөнү билбейт, бирок бизге чен керек (суроолор-каталар)/суроолор.

каталар жагымсыз көрүнөт:

Kapacitorдо метрикаларды иштетүү үчүн амалдар

Ийгиликтүү өтүнүчтөр менен караганда азыраак жаман:

Kapacitorдо метрикаларды иштетүү үчүн амалдар

Макул, биз графанага чейин кызматтагы тарифти алдын ала эсептей алабыз жана кээ бир учурларда бул иштейт. Бирок биздикинде эмес, анткени... ар бир канал үчүн өзүнүн катышы "нормалдуу" деп эсептелет жана эскертүүлөр статикалык маанилерге ылайык иштейт (биз аларды көзүбүз менен издейбиз, тез-тез сигналдар болсо, аларды өзгөртөбүз).

Булар ар кандай каналдар үчүн "нормалдуу" мисалдар:

Kapacitorдо метрикаларды иштетүү үчүн амалдар

Kapacitorдо метрикаларды иштетүү үчүн амалдар

Биз мурунку пунктка көңүл бурбайбыз жана "нормалдуу" сүрөт бардык жеткирүүчүлөр үчүн окшош деп ойлойбуз. Азыр баары жакшы, биз графанадагы эскертүүлөр менен иштей алабызбы?
Биз мүмкүн, бирок биз каалабайбыз, анткени биз варианттардын бирин тандап алышыбыз керек:
а) ар бир канал үчүн өзүнчө көп графиктерди түзүңүз (жана аларды азаптуу коштоп жүрүңүз)
б) бардык каналдар менен бир диаграмманы калтырыңыз (жана түстүү сызыктарда жана ыңгайлаштырылган эскертүүлөрдөн адашып кетиңиз)

Kapacitorдо метрикаларды иштетүү үчүн амалдар

Муну кантип кылдыңыз?

Дагы, документацияда жакшы башталгыч мисал бар (Кошулган сериялар боюнча тарифтерди эсептөө), карап чыгууга же окшош көйгөйлөргө негиз катары алынышы мүмкүн.

Акырында эмне кылдык:

  • бир нече сааттын ичинде эки серияга кошулуу, каналдар боюнча топтоо;
  • маалыматтар жок болсо, катарды топ боюнча толтуруңуз;
  • акыркы 10 мүнөттүн медианасын мурунку маалыматтар менен салыштыруу;
  • бир нерсе тапсак кыйкырабыз;
  • биз influxdb болгон эсептелген чендерди жана эскертүүлөрдү жазабыз;
  • боштук үчүн пайдалуу билдирүү жөнөтүү.

Менин оюмча, биз эң акырында каалаган нерсенин баарына (жана көнүмүш иштетүүчүлөр менен дагы бир аз көбүрөөк) мүмкүн болушунча сонун жетише алдык.

Сиз github.com дарегин карасаңыз болот код мисалы и минималдуу схема (график) натыйжасында сценарий.

Натыйжада коддун мисалы:

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)

Жыйынтык кандай?

Kapacitor бир топ топтор менен мониторинг-эскертүүлөрдү аткарууда, буга чейин жазылган метрикалардын негизинде кошумча эсептөөлөрдү жүргүзүүдө, ыңгайлаштырылган аракеттерди аткарууда жана скрипттерди (udf) иштетүүдө сонун.

Кирүү тоскоолдугу өтө жогору эмес - эгер графана же башка каражаттар сиздин каалооңузду толук канааттандырбаса, аракет кылып көрүңүз.

Source: www.habr.com

DDoS коргоосу, VPS VDS серверлери бар сайттар үчүн ишенимдүү хостинг сатып алыңыз 🔥 DDoS коргоосу, VPS VDS серверлери бар ишенимдүү веб-сайт хостингин сатып алыңыз | ProHoster