Π‘ΠΊΠΎΡΠ΅Π΅ Π²ΡΠ΅Π³ΠΎ, ΡΠ΅Π³ΠΎΠ΄Π½Ρ ΡΠΆΠ΅ Π½ΠΈ Ρ ΠΊΠΎΠ³ΠΎ Π½Π΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ Π²ΠΎΠΏΡΠΎΡ, Π·Π°ΡΠ΅ΠΌ Π½ΡΠΆΠ½ΠΎ ΡΠΎΠ±ΠΈΡΠ°ΡΡ ΠΌΠ΅ΡΡΠΈΠΊΠΈ ΡΠ΅ΡΠ²ΠΈΡΠΎΠ². Π‘Π»Π΅Π΄ΡΡΡΠΈΠΉ Π»ΠΎΠ³ΠΈΡΠ½ΡΠΉ ΡΠ°Π³ β Π½Π°ΡΡΡΠΎΠΈΡΡ Π°Π»Π΅ΡΡΠΈΠ½Π³ Π½Π° ΡΠΎΠ±ΠΈΡΠ°Π΅ΠΌΡΠ΅ ΠΌΠ΅ΡΡΠΈΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅Ρ ΠΎΠΏΠΎΠ²Π΅ΡΠ°ΡΡ ΠΎ Π»ΡΠ±ΡΡ
ΠΎΡΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΡΡ
Π² Π΄Π°Π½Π½ΡΡ
Π² ΡΠ΄ΠΎΠ±Π½ΡΠ΅ Π²Π°ΠΌ ΠΊΠ°Π½Π°Π»Ρ (ΠΏΠΎΡΡΡ, Slack, Telegram). Π ΡΠ΅ΡΠ²ΠΈΡΠ΅ ΠΎΠ½Π»Π°ΠΉΠ½-Π±ΡΠΎΠ½ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΎΡΠ΅Π»Π΅ΠΉ
Kapacitor β ΡΠ°ΡΡΡ TICK-ΡΡΠ΅ΠΊΠ°, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΌΠ΅Π΅Ρ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ ΠΌΠ΅ΡΡΠΈΠΊΠΈ ΠΈΠ· InfluxDB. ΠΠ½ ΠΌΠΎΠΆΠ΅Ρ ΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΈΠ·ΠΌΠ΅ΡΠ΅Π½ΠΈΠΉ ΠΌΠ΅ΠΆΠ΄Ρ ΡΠΎΠ±ΠΎΠΉ (join), ΠΈΠ· ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΡΡ
Π΄Π°Π½Π½ΡΡ
Π²ΡΡΠΈΡΠ»ΠΈΡΡ ΡΡΠΎ-ΡΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠ΅, Π·Π°ΠΏΠΈΡΠ°ΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ Π² InfluxDB, ΠΎΡΠΏΡΠ°Π²ΠΈΡΡ Π°Π»Π΅ΡΡ Π² Slack/Telegram/ΠΏΠΎΡΡΡ.
ΠΠ΅ΡΡ ΡΡΠ΅ΠΊ ΠΈΠΌΠ΅Π΅Ρ ΠΊΡΡΡΡΡ ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΡΡ
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 Π² join (inner vs outer)
ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ join ΠΎΡΠ±ΡΠΎΡΠΈΡ ΡΠΎΡΠΊΠΈ, Π³Π΄Π΅ Π΄Π°Π½Π½ΡΡ
Π½Π΅Ρ (inner).
ΠΡΠΈ fill(‘null’) Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ outer join, ΠΏΠΎΡΠ»Π΅ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ Π½ΡΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°ΡΡ default() ΠΈ Π·Π°ΠΏΠΎΠ»Π½ΠΈΡΡ ΠΏΡΡΡΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ:
var data = res1
|join(res2)
.as('res1', 'res2)
.fill('null')
|default()
.field('res1.value', 0.0)
.field('res2.value', 100.0)
Π’ΡΡ Π²ΡΠ΅ ΡΠ°Π²Π½ΠΎ Π΅ΡΡΡ Π½ΡΠ°Π½Ρ. ΠΡΠ»ΠΈ Π² ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π²ΡΡΠ΅ ΠΎΠ΄Π½Π° ΠΈΠ· ΡΠ΅ΡΠΈΠΉ (res1 ΠΈΠ»ΠΈ res2) Π±ΡΠ΄Π΅Ρ ΠΏΡΡΡΠΎΠΉ, ΠΈΡΠΎΠ³ΠΎΠ²Π°Ρ ΡΠ΅ΡΠΈΡ (data) ΡΠ°ΠΊΠΆΠ΅ Π±ΡΠ΄Π΅Ρ ΠΏΡΡΡΠΎΠΉ. ΠΠ° ΡΡΡ ΡΠ΅ΠΌΡ Π΅ΡΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠΈΠΊΠ΅ΡΠΎΠ² Π½Π° Π³ΠΈΡΡ
Π°Π±Π΅ (
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΡΠ»ΠΎΠ²ΠΈΠΉ Π² Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡΡ (if Π² lambda)
|eval(lambda: if("value" > 0, true, false)
ΠΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ ΠΏΡΡΡ ΠΌΠΈΠ½ΡΡ ΠΈΠ· ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π° Π·Π° ΠΏΠ΅ΡΠΈΠΎΠ΄
ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π²Π°ΠΌ Π½ΡΠΆΠ½ΠΎ ΡΡΠ°Π²Π½ΠΈΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡ ΠΏΡΡΠΈ ΠΌΠΈΠ½ΡΡ Ρ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΉ Π½Π΅Π΄Π΅Π»Π΅ΠΉ. ΠΠΎΠΆΠ½ΠΎ Π²Π·ΡΡΡ Π΄Π²Π΅ ΠΏΠ°ΡΠΊΠΈ Π΄Π°Π½Π½ΡΡ Π΄Π²ΡΠΌΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΌΠΈ batchβΠ°ΠΌΠΈ ΠΈΠ»ΠΈ Π²ΡΡΠ°ΡΠΈΡΡ ΡΠ°ΡΡΡ Π΄Π°Π½Π½ΡΡ ΠΈΠ· Π±ΠΎΠ»ΡΡΠ΅Π³ΠΎ ΠΏΠ΅ΡΠΈΠΎΠ΄Π°:
|where(lambda: duration((unixNano(now()) - unixNano("time"))/1000, 1u) < 5m)
ΠΠ»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²ΠΎΠΉ Π΄Π»Ρ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡ ΠΏΡΡΠΈ ΠΌΠΈΠ½ΡΡ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ Π½ΠΎΠ΄Ρ BarrierNode, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΎΡΡΠ΅ΠΊΠ°Π΅Ρ Π΄Π°Π½Π½ΡΠ΅ ΡΠ°Π½ΡΡΠ΅ ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ:
|barrier()
.period(5m)
ΠΡΠΈΠΌΠ΅ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ GoβΡΠ½ΡΡ ΡΠ°Π±Π»ΠΎΠ½ΠΎΠ² Π² message
Π¨Π°Π±Π»ΠΎΠ½Ρ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡ ΡΠΎΡΠΌΠ°ΡΡ ΠΈΠ· ΠΏΠ°ΠΊΠ΅ΡΠ°
if-else
ΠΠ°Π²ΠΎΠ΄ΠΈΠΌ ΠΏΠΎΡΡΠ΄ΠΎΠΊ, Π½Π΅ ΡΡΠΈΠ³Π³Π΅ΡΠΈΠΌ Π»ΡΠ΄Π΅ΠΉ ΡΠ΅ΠΊΡΡΠΎΠΌ Π»ΠΈΡΠ½ΠΈΠΉ ΡΠ°Π·:
|alert()
...
.message(
'{{ if eq .Level "OK" }}It is ok now{{ else }}Chief, everything is broken{{end}}'
)
ΠΠ²Π΅ ΡΠΈΡΡΡ ΠΏΠΎΡΠ»Π΅ Π·Π°ΠΏΡΡΠΎΠΉ Π² message
Π£Π»ΡΡΡΠ°Π΅ΠΌ ΡΠΈΡΠ°Π±Π΅Π»ΡΠ½ΠΎΡΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ:
|alert()
...
.message(
'now value is {{ index .Fields "value" | printf "%0.2f" }}'
)
Π Π°Π·Π²ΠΎΡΠ°ΡΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ Π² message
ΠΡΠ²ΠΎΠ΄ΠΈΠΌ Π² ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ Π±ΠΎΠ»ΡΡΠ΅ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ Π΄Π»Ρ ΠΎΡΠ²Π΅ΡΠ° Π½Π° Π²ΠΎΠΏΡΠΎΡ Β«ΠΠΎΡΠ΅ΠΌΡ ΠΎΡΠ΅Ρ-ΡΠΎΒ»?
var warnAlert = 10
|alert()
...
.message(
'Today value less then '+string(warnAlert)+'%'
)
Π£Π½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΉ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ Π°Π»Π΅ΡΡΠ°
ΠΡΠΆΠ½Π°Ρ ΡΡΡΠΊΠ°, ΠΊΠΎΠ³Π΄Π° Π² Π΄Π°Π½Π½ΡΡ Π±ΠΎΠ»ΡΡΠ΅ ΠΎΠ΄Π½ΠΎΠΉ Π³ΡΡΠΏΠΏΡ, ΠΈΠ½Π°ΡΠ΅ Π±ΡΠ΄Π΅Ρ Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Π°Π»Π΅ΡΡ:
|alert()
...
.id('{{ index .Tags "myname" }}/{{ index .Tags "myfield" }}')
ΠΠ°ΡΡΠΎΠΌΠ½ΡΠ΅ handlerβs
Π Π±ΠΎΠ»ΡΡΠΎΠΌ ΡΠΏΠΈΡΠΊΠ΅ Ρ Π΅Π½Π΄Π»Π΅ΡΠΎΠ² Π΅ΡΡΡ exec, ΠΊΠΎΡΠΎΡΡΠΉ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π²ΡΠΏΠΎΠ»Π½ΠΈΡΡ ΡΠ²ΠΎΠΉ ΡΠΊΡΠΈΠΏΡ Ρ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΡΠΌΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ (stdin) β ΡΠ²ΠΎΡΡΠ΅ΡΡΠ²ΠΎ Π΄Π° ΠΈ ΡΠΎΠ»ΡΠΊΠΎ!
ΠΠ΄ΠΈΠ½ ΠΈΠ· Π½Π°ΡΠΈΡ
ΠΊΠ°ΡΡΠΎΠΌΠΎΠ² β ΡΡΠΎ Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΉ ΠΏΠΈΡΠΎΠ½ΡΡΠΈΠΉ ΡΠΊΡΠΈΠΏΡ Π΄Π»Ρ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΠΉ Π² ΡΠ»Π°ΠΊ.
Π‘Π½Π°ΡΠ°Π»Π° Π½Π°ΠΌ Π·Π°Ρ
ΠΎΡΠ΅Π»ΠΎΡΡ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡ Π² ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΈ ΠΊΠ°ΡΡΠΈΠ½ΠΊΡ ΠΈΠ· Π³ΡΠ°ΡΠ°Π½Ρ, Π·Π°ΡΠΈΡΠ΅Π½Π½ΠΎΠΉ Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΠ΅ΠΉ. ΠΠΎΡΠ»Π΅ β ΠΏΠΈΡΠ°ΡΡ OK Π² ΡΡΠ΅Π΄ ΠΊ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΌΡ Π°Π»Π΅ΡΡΡ ΠΈΠ· ΡΠΎΠΉ ΠΆΠ΅ Π³ΡΡΠΏΠΏΡ, Π° Π½Π΅ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠΌ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ΠΌ. ΠΡΡ ΡΡΡΡ ΠΏΠΎΠ·ΠΆΠ΅ β Π΄ΠΎΠΏΠΈΡΡΠ²Π°ΡΡ Π² ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΡΠ°ΠΌΡΡ ΡΠ°ΡΡΡΡ ΠΎΡΠΈΠ±ΠΊΡ Π·Π° ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ Π₯ ΠΌΠΈΠ½ΡΡ.
ΠΡΠ΄Π΅Π»ΡΠ½Π°Ρ ΡΠ΅ΠΌΠ° β ΡΠ²ΡΠ·Ρ Ρ Π΄ΡΡΠ³ΠΈΠΌΠΈ ΡΠ΅ΡΠ²ΠΈΡΠ°ΠΌΠΈ ΠΈ ΠΊΠ°ΠΊΠΈΠ΅-Π»ΠΈΠ±ΠΎ Π΄Π΅ΠΉΡΡΠ²ΠΈΡ, ΠΈΠ½ΠΈΡΠΈΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ Π°Π»Π΅ΡΡΠΎΠΌ (ΡΠΎΠ»ΡΠΊΠΎ Π΅ΡΠ»ΠΈ Π²Π°Ρ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ Ρ
ΠΎΡΠΎΡΠΎ).
ΠΡΠΈΠΌΠ΅Ρ ΠΎΠΏΠΈΡΠ°Π½ΠΈΡ Ρ
Π΅Π½Π΄Π»Π΅ΡΠ°, Π³Π΄Π΅ 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")
Π‘ΠΌΠΎΡΡΠ΅ΡΡ (cli): kapacitor -url
ΠΠ°ΡΠΈΠ°Π½Ρ Ρ httpOut
ΠΠΎΠΊΠ°Π·ΡΠ²Π°Π΅Ρ Π΄Π°Π½Π½ΡΠ΅ Π² ΡΠ΅ΠΊΡΡΠ΅ΠΌ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½Π΅:
|httpOut('something')
Π‘ΠΌΠΎΡΡΠ΅ΡΡ (get):
Π‘Ρ Π΅ΠΌΠ° Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ
- ΠΠ°ΠΆΠ΄Π°Ρ ΡΠ°ΡΠΊΠ° Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ Π΄Π΅ΡΠ΅Π²ΠΎ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Ρ ΠΏΠΎΠ»Π΅Π·Π½ΡΠΌΠΈ ΡΠΈΡΡΠ°ΠΌΠΈ Π² ΡΠΎΡΠΌΠ°ΡΠ΅
graphviz . - ΠΠ΅ΡΠ΅ΠΌ Π±Π»ΠΎΠΊ
dot . - ΠΡΡΠ°Π²Π»ΡΠ΅ΠΌ Π² viewer,
Π½Π°ΡΠ»Π°ΠΆΠ΄Π°Π΅ΠΌΡΡ .
ΠΠ΄Π΅ Π΅ΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π³ΡΠ°Π±Π»ΡΠΌΠΈ
timestamp Π² influxdb ΠΏΡΠΈ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠΉ Π·Π°ΠΏΠΈΡΠΈ
ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΡ Π½Π°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌ Π°Π»Π΅ΡΡ Π½Π° ΡΡΠΌΠΌΡ Π·Π°ΠΏΡΠΎΡΠΎΠ² Π·Π° ΡΠ°Ρ (groupBy(1h)) ΠΈ Ρ ΠΎΡΠΈΠΌ Π·Π°ΠΏΠΈΡΠ°ΡΡ ΡΠ»ΡΡΠΈΠ²ΡΠΈΠΉΡΡ Π°Π»Π΅ΡΡ Π² influxdb (ΡΡΠΎΠ±Ρ ΠΊΡΠ°ΡΠΈΠ²ΠΎ ΠΏΠΎΠΊΠ°Π·Π°ΡΡ ΡΠ°ΠΊΡ Π½Π°Π»ΠΈΡΠΈΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Π½Π° Π³ΡΠ°ΡΠΈΠΊΠ΅ Π² grafana).
influxDBOut() Π·Π°ΠΏΠΈΡΠ΅Ρ Π² timestamp Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ time ΠΈΠ· Π°Π»Π΅ΡΡΠ°, ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎ, ΡΠΎΡΠΊΠ° Π½Π° Π³ΡΠ°ΡΠΈΠΊΠ΅ Π±ΡΠ΄Π΅Ρ Π·Π°ΠΏΠΈΡΠ°Π½Π° ΡΠ°Π½ΡΡΠ΅/ΠΏΠΎΠ·ΠΆΠ΅, ΡΠ΅ΠΌ ΠΏΡΠΈΡΠ΅Π» Π°Π»Π΅ΡΡ.
ΠΠΎΠ³Π΄Π° ΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΡΠΎΡΠ½ΠΎΡΡΡ: ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌ ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ ΡΠ΅ΡΠ΅Π· Π²ΡΠ·ΠΎΠ² ΠΊΠ°ΡΡΠΎΠΌΠ½ΠΎΠ³ΠΎ handler’Π°, ΠΊΠΎΡΠΎΡΡΠΉ Π·Π°ΠΏΠΈΡΠ΅Ρ Π΄Π°Π½Π½ΡΠ΅ Π² influxdb Ρ ΡΠ΅ΠΊΡΡΠΈΠΌ timestamp’ΠΎΠΌ.
docker, ΡΠ±ΠΎΡΠΊΠ° ΠΈ Π΄Π΅ΠΏΠ»ΠΎΠΉ
ΠΡΠΈ ΡΡΠ°ΡΡΠ΅ kapacitor ΠΌΠΎΠΆΠ΅Ρ ΠΏΠΎΠ΄Π³ΡΡΠΆΠ°ΡΡ ΡΠ°ΡΠΊΠΈ, ΡΠ°Π±Π»ΠΎΠ½Ρ ΠΈ Ρ Π΅Π½Π΄Π»Π΅ΡΡ ΠΈΠ· Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΈ, ΠΏΡΠΎΠΏΠΈΡΠ°Π½Π½ΠΎΠΉ Π² ΠΊΠΎΠ½ΡΠΈΠ³Π΅, Π² Π±Π»ΠΎΠΊΠ΅ [load].
ΠΠ»Ρ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΠ³ΠΎ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΡΠ°ΡΠΊΠΈ Π½ΡΠΆΠ½Ρ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ Π²Π΅ΡΠΈ:
- ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠ°ΠΉΠ»Π° β ΡΠ°Π·Π²ΠΎΡΠ°ΡΠΈΠ²Π°Π΅ΡΡΡ Π² id/Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΊΡΠΈΠΏΡΠ°
- Π’ΠΈΠΏ β stream/batch
- dbrp β ΠΊΠ΅ΠΉΠ²ΠΎΡΠ΄ Π΄Π»Ρ ΡΠΊΠ°Π·Π°Π½ΠΈΡ Π² ΠΊΠ°ΠΊΠΎΠΉ Π±Π°Π·Π΅ + ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠ΅ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ ΡΠΊΡΠΈΠΏΡ (dbrp Β«supplierΒ».Β«autogenΒ»)
ΠΡΠ»ΠΈ Π² ΠΊΠ°ΠΊΠΎΠΉ-ΡΠΎ batch-ΡΠ°ΡΠΊΠ΅ Π½Π΅ Π±ΡΠ΄Π΅Ρ ΡΡΡΠΎΠΊΠΈ Ρ dbrp, Π²Π΅ΡΡ ΡΠ΅ΡΠ²ΠΈΡ ΠΎΡΠΊΠ°ΠΆΠ΅ΡΡΡ Π·Π°ΠΏΡΡΠΊΠ°ΡΡΡΡ ΠΈ ΡΠ΅ΡΡΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ΅Ρ ΠΎΠ± ΡΡΠΎΠΌ Π² Π»ΠΎΠ³.
Π chronografβΠ΅ ΠΆΠ΅, Π½Π°ΠΏΡΠΎΡΠΈΠ², ΡΡΠΎΠΉ ΡΡΡΠΎΠΊΠΈ Π±ΡΡΡ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ, ΡΠ΅ΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΠΎΠ½Π° Π½Π΅ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅ΡΡΡ ΠΈ Π²ΡΠ΄Π°ΡΡ ΠΎΡΠΈΠ±ΠΊΡ.
Π₯Π°ΠΊ ΠΏΡΠΈ ΡΠ±ΠΎΡΠΊΠ΅ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ°: Dockerfile Π²ΡΡ ΠΎΠ΄ΠΈΡ Ρ -1, Π΅ΡΠ»ΠΈ Π΅ΡΡΡ ΡΡΡΠΎΠΊΠΈ Ρ //.+dbrp, ΡΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ ΡΡΠ°Π·Ρ ΠΏΠΎΠ½ΡΡΡ ΠΏΡΠΈΡΠΈΠ½Ρ ΡΠ΅ΠΉΠ»Π° ΠΏΡΠΈ ΡΠ±ΠΎΡΠΊΠ΅ Π±ΠΈΠ»Π΄Π°.
join ΠΎΠ΄ΠΈΠ½ ΠΊΠΎ ΠΌΠ½ΠΎΠ³ΠΈΠΌ
ΠΠ°Π΄Π°ΡΠ°-ΠΏΡΠΈΠΌΠ΅Ρ: Π½ΡΠΆΠ½ΠΎ Π²Π·ΡΡΡ 95-ΠΉ ΠΏΠ΅ΡΡΠ΅Π½ΡΠΈΠ»Ρ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ ΡΠ°Π±ΠΎΡΡ ΡΠ΅ΡΠ²ΠΈΡΠ° Π·Π° Π½Π΅Π΄Π΅Π»Ρ, ΡΡΠ°Π²Π½ΠΈΡΡ ΠΊΠ°ΠΆΠ΄ΡΡ ΠΌΠΈΠ½ΡΡΡ ΠΈΠ· 10 ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡ Ρ ΡΡΠΈΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ.
ΠΠ΅Π»ΡΠ·Ρ ΡΠ΄Π΅Π»Π°ΡΡ join ΠΎΠ΄ΠΈΠ½ ΠΊΠΎ ΠΌΠ½ΠΎΠ³ΠΈΠΌ, last/mean/median ΠΏΠΎ Π³ΡΡΠΏΠΏΠ΅ ΡΠΎΡΠ΅ΠΊ ΠΏΡΠ΅Π²ΡΠ°ΡΠ°ΡΡ Π½ΠΎΠ΄Ρ Π² stream, Π²Π΅ΡΠ½Π΅ΡΡΡ ΠΎΡΠΈΠ±ΠΊΠ° Β«cannot add child mismatched edges: batch -> streamΒ».
Π Π΅Π·ΡΠ»ΡΡΠ°Ρ batchβΠ°, ΠΊΠ°ΠΊ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ Π² lambda-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠΈ, ΡΠΎΠΆΠ΅ Π½Π΅ ΠΏΠΎΠ΄ΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ.
ΠΡΡΡ Π²Π°ΡΠΈΠ°Π½Ρ ΡΠΎΡ ΡΠ°Π½ΡΡΡ Π½ΡΠΆΠ½ΡΠ΅ ΡΠΈΡΡΡ ΠΈΠ· ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ Π±Π°ΡΡΠ° Π² ΡΠ°ΠΉΠ» ΡΠ΅ΡΠ΅Π· udf ΠΈ Π·Π°Π³ΡΡΠΆΠ°ΡΡ ΡΡΠΎΡ ΡΠ°ΠΉΠ» ΡΠ΅ΡΠ΅Π· sideload.
Π§ΡΠΎ ΠΌΡ ΡΡΠΈΠΌ ΡΠ΅ΡΠ°Π»ΠΈ?
Π£ Π½Π°Ρ Π΅ΡΡΡ ΠΎΠΊΠΎΠ»ΠΎ 100 ΠΏΠΎΡΡΠ°Π²ΡΠΈΠΊΠΎΠ² ΠΎΡΠ΅Π»Π΅ΠΉ, ΠΊ ΠΊΠ°ΠΆΠ΄ΠΎΠΌΡ ΠΈΠ· Π½ΠΈΡ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ, Π½Π°Π·ΠΎΠ²Π΅ΠΌ ΡΡΠΎ ΠΊΠ°Π½Π°Π»ΠΎΠΌ. ΠΡΠΈΡ ΠΊΠ°Π½Π°Π»ΠΎΠ² ΠΏΡΠΈΠΌΠ΅ΡΠ½ΠΎ 300, ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΈΠ· ΠΊΠ°Π½Π°Π»ΠΎΠ² ΠΌΠΎΠΆΠ΅Ρ ΠΎΡΠ²Π°Π»ΠΈΡΡΡΡ. ΠΠ· Π²ΡΠ΅Ρ Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΠΌΡΡ ΠΌΠ΅ΡΡΠΈΠΊ Π±ΡΠ΄Π΅ΠΌ ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΡΡ ΡΠ΅ΠΉΡ ΠΎΡΠΈΠ±ΠΎΠΊ (requests ΠΈ errors).
ΠΠΎΡΠ΅ΠΌΡ Π½Π΅ Π³ΡΠ°ΡΠ°Π½Π°?
ΠΠ»Π΅ΡΡΡ ΠΏΠΎ ΠΎΡΠΈΠ±ΠΊΠ°ΠΌ, Π½Π°ΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ Π² Π³ΡΠ°ΡΠ°Π½Π΅, ΠΈΠΌΠ΅ΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΌΠΈΠ½ΡΡΠΎΠ². ΠΠ°ΠΊΠΈΠ΅-ΡΠΎ ΠΊΡΠΈΡΠΈΡΠ½ΡΠ΅, Π½Π° ΠΊΠ°ΠΊΠΈΠ΅-ΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΊΡΡΡΡ Π³Π»Π°Π·Π°, Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΈΡΡΠ°ΡΠΈΠΈ.
ΠΡΠ°ΡΠ°Π½Π° Π½Π΅ ΡΠΌΠ΅Π΅Ρ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρ ΠΈΠ·ΠΌΠ΅ΡΠ΅Π½ΠΈΡΠΌΠΈ + Π°Π»Π΅ΡΡΠΈΠ½Π³, Π° Π½Π°ΠΌ ΠΆΠ΅ Π½ΡΠΆΠ΅Π½ ΡΠ΅ΠΉΡ (requests-errors)/requests.
ΠΡΠΈΠ±ΠΊΠΈ Π²ΡΠ³Π»ΡΠ΄ΡΡ Π·Π»ΠΎΠ±Π½ΠΎ:
Π ΠΌΠ΅Π½Π΅Π΅ Π·Π»ΠΎΠ±Π½ΠΎ, Π΅ΡΠ»ΠΈ ΡΠΌΠΎΡΡΠ΅ΡΡ Ρ ΡΡΠΏΠ΅ΡΠ½ΡΠΌΠΈ Π·Π°ΠΏΡΠΎΡΠ°ΠΌΠΈ:
ΠΠΊΠ΅ΠΉ, ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΠΎΡΡΠΈΡΠ°ΡΡ ΡΠ΅ΠΉΡ Π² ΡΠ΅ΡΠ²ΠΈΡΠ΅ Π΄ΠΎ Π³ΡΠ°ΡΠ°Π½Ρ, ΠΈ Π² ΠΊΠ°ΠΊΠΈΡ
-ΡΠΎ ΡΠ»ΡΡΠ°ΡΡ
ΡΡΠΎ ΠΏΠΎΠ΄ΠΎΠΉΠ΄Π΅Ρ. ΠΠΎ Π½Π΅ Π² Π½Π°ΡΠ΅ΠΌ, Ρ.ΠΊ. Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΊΠ°Π½Π°Π»Π° ΡΠ²ΠΎΠ΅ ΡΠΎΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΠ΅ ΡΡΠΈΡΠ°Π΅ΡΡΡ Β«Π½ΠΎΡΠΌΠ°Π»ΡΠ½ΡΠΌΒ», Π° Π°Π»Π΅ΡΡΡ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΠΏΠΎ ΡΡΠ°ΡΠΈΡΠ½ΡΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΡΠΌ (ΠΈΡΠ΅ΠΌ Π³Π»Π°Π·ΠΊΠ°ΠΌΠΈ, ΠΌΠ΅Π½ΡΠ΅ΠΌ, Π΅ΡΠ»ΠΈ ΡΠ°ΡΡΠΎ Π°Π»Π΅ΡΡΠΈΡ).
ΠΡΠΎ ΠΏΡΠΈΠΌΠ΅ΡΡ Β«Π½ΠΎΡΠΌΠ°Π»ΡΠ½ΠΎΒ» Π΄Π»Ρ ΡΠ°Π·Π½ΡΡ ΠΊΠ°Π½Π°Π»ΠΎΠ²:
ΠΡΠ΅Π½Π΅Π±ΡΠ΅Π³Π°Π΅ΠΌ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠΈΠΌ ΠΏΡΠ½ΠΊΡΠΎΠΌ ΠΈ ΠΏΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, ΡΡΠΎ Ρ Π²ΡΠ΅Ρ
ΠΏΠΎΡΡΠ°Π²ΡΠΈΠΊΠΎΠ² Β«Π½ΠΎΡΠΌΠ°Π»ΡΠ½Π°ΡΒ» ΠΊΠ°ΡΡΠΈΠ½Π° ΠΏΠΎΡ
ΠΎΠΆΠ°. Π’Π΅ΠΏΠ΅ΡΡ-ΡΠΎ Π²ΡΠ΅ Ρ
ΠΎΡΠΎΡΠΎ, ΠΈ ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΠ±ΠΎΠΉΡΠΈΡΡ Π°Π»Π΅ΡΡΠ°ΠΌΠΈ Π² grafana?
ΠΠΎΠΆΠ΅ΠΌ, Π½ΠΎ ΠΎΡΠ΅Π½Ρ Π½Π΅ Ρ
ΠΎΡΠ΅ΡΡΡ, ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ Π½Π°Π΄ΠΎ Π²ΡΠ±ΠΈΡΠ°ΡΡ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ²:
Π°) ΡΠ΄Π΅Π»Π°ΡΡ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ Π³ΡΠ°ΡΠΈΠΊΠΎΠ² ΠΏΠΎΠ΄ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΊΠ°Π½Π°Π» ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎ (ΠΈ ΠΌΡΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΈΡ
ΡΠΎΠΏΡΠΎΠ²ΠΎΠΆΠ΄Π°ΡΡ)
Π±) ΠΎΡΡΠ°Π²ΠΈΡΡ ΠΎΠ΄ΠΈΠ½ Π³ΡΠ°ΡΠΈΠΊ ΡΠΎ Π²ΡΠ΅ΠΌΠΈ ΠΊΠ°Π½Π°Π»Π°ΠΌΠΈ (ΠΈ ΠΏΠΎΡΠ΅ΡΡΡΡΡΡ Π² ΡΠ²Π΅ΡΠ°ΡΡΡΡ
Π»ΠΈΠ½ΠΈΡΡ
ΠΈ Π½Π°ΡΡΡΠΎΠ΅Π½Π½ΡΡ
Π°Π»Π΅ΡΡΠ°Ρ
)
ΠΠ°ΠΊ ΡΠ΄Π΅Π»Π°Π»ΠΈ?
ΠΠΏΡΡΡ ΠΆΠ΅, Π² Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ Π΅ΡΡΡ Ρ
ΠΎΡΠΎΡΠΈΠΉ ΡΡΠ°ΡΡΠΎΠ²ΡΠΉ ΠΏΡΠΈΠΌΠ΅Ρ (
Π§ΡΠΎ ΡΠ΄Π΅Π»Π°Π»ΠΈ Π² ΠΈΡΠΎΠ³Π΅:
- join Π΄Π²ΡΡ ΡΠ΅ΡΠΈΠΉ Π·Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ°ΡΠΎΠ², Π³ΡΡΠΏΠΏΠΈΡΠΎΠ²ΠΊΠ° ΠΏΠΎ ΠΊΠ°Π½Π°Π»Π°ΠΌ;
- Π·Π°ΠΏΠΎΠ»Π½ΡΠ΅ΠΌ ΡΠ΅ΡΠΈΠΈ ΠΏΠΎ Π³ΡΡΠΏΠΏΠ°ΠΌ, Π΅ΡΠ»ΠΈ Π΄Π°Π½Π½ΡΡ Π½Π΅ Π±ΡΠ»ΠΎ;
- ΡΡΠ°Π²Π½ΠΈΠ²Π°Π΅ΠΌ ΠΌΠ΅Π΄ΠΈΠ°Π½Ρ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡ 10 ΠΌΠΈΠ½ΡΡ Ρ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠΈΠΌΠΈ Π΄Π°Π½Π½ΡΠΌΠΈ;
- ΠΊΡΠΈΡΠΈΠΌ, Π΅ΡΠ»ΠΈ ΡΡΠΎ-ΡΠΎ ΠΎΠ±Π½Π°ΡΡΠΆΠΈΠ»ΠΈ;
- ΠΏΠΈΡΠ΅ΠΌ ΠΏΠΎΡΡΠΈΡΠ°Π½Π½ΡΠ΅ ΡΠ΅ΠΉΡΡ ΠΈ ΡΠ»ΡΡΠΈΠ²ΡΠΈΠ΅ΡΡ Π°Π»Π΅ΡΡΡ Π² influxdb;
- ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌ ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ Π² slack.
ΠΠ° ΠΌΠΎΠΉ Π²Π·Π³Π»ΡΠ΄, Π½Π°ΠΌ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎ ΠΊΡΠ°ΡΠΈΠ²ΠΎ ΡΠ΄Π°Π»ΠΎΡΡ Π²ΡΡ, ΡΡΠΎ Ρ ΠΎΡΠ΅Π»ΠΈ Π±Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π½Π° Π²ΡΡ ΠΎΠ΄Π΅ (ΠΈ Π΄Π°ΠΆΠ΅ ΡΡΡΡ Π±ΠΎΠ»ΡΡΠ΅ Ρ ΠΊΠ°ΡΡΠΎΠΌΠ½ΡΠΌΠΈ Ρ ΡΠ½Π΄Π»Π΅ΡΠ°ΠΌΠΈ).
ΠΠ° 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).
ΠΠΎΡΠΎΠ³ Π²Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΡ Π½Π΅ ΠΎΡΠ΅Π½Ρ Π²ΡΡΠΎΠΊΠΈΠΉ β ΠΏΠΎΠΏΡΠΎΠ±ΡΠΉΡΠ΅ Π΅Π³ΠΎ, Π΅ΡΠ»ΠΈ Π³ΡΠ°ΡΠ°Π½Π° ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ Π½Π΅ Π΄ΠΎ ΠΊΠΎΠ½ΡΠ° ΡΠ΄ΠΎΠ²Π»Π΅ΡΠ²ΠΎΡΡΡΡ Π²Π°ΡΠΈ Ρ
ΠΎΡΠ΅Π»ΠΊΠΈ.
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com