ΠΠ°ΠΉ-Π²Π΅ΡΠΎΡΡΠ½ΠΎ Π΄Π½Π΅Ρ Π½ΠΈΠΊΠΎΠΉ Π½Π΅ ΡΠ΅ ΠΏΠΈΡΠ° Π·Π°ΡΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° ΡΠ΅ ΡΡΠ±ΠΈΡΠ°Ρ ΠΏΠΎΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ Π·Π° ΡΡΠ»ΡΠ³Π°ΡΠ°. Π‘Π»Π΅Π΄Π²Π°ΡΠ°ΡΠ° Π»ΠΎΠ³ΠΈΡΠ½Π° ΡΡΡΠΏΠΊΠ° Π΅ Π΄Π° Π½Π°ΡΡΡΠΎΠΈΡΠ΅ ΠΏΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π·Π° ΡΡΠ±ΡΠ°Π½ΠΈΡΠ΅ ΠΌΠ΅ΡΡΠΈΠΊΠΈ, ΠΊΠΎΠ΅ΡΠΎ Π΄Π° ΠΈΠ·Π²Π΅ΡΡΡΠ²Π° Π·Π° ΠΎΡΠΊΠ»ΠΎΠ½Π΅Π½ΠΈΡ Π² Π΄Π°Π½Π½ΠΈΡΠ΅ ΠΏΠΎ ΡΠ΄ΠΎΠ±Π½ΠΈ Π·Π° Π²Π°Ρ ΠΊΠ°Π½Π°Π»ΠΈ (ΠΏΠΎΡΠ°, Slack, Telegram). Π ΠΎΠ½Π»Π°ΠΉΠ½ ΡΡΠ»ΡΠ³Π°ΡΠ° Π·Π° Ρ
ΠΎΡΠ΅Π»ΡΠΊΠΈ ΡΠ΅Π·Π΅ΡΠ²Π°ΡΠΈΠΈ
Kapacitor Π΅ ΡΠ°ΡΡ ΠΎΡ ΡΡΠ΅ΠΊΠ° TICK, ΠΊΠΎΠΉΡΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠ²Π° ΠΏΠΎΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ ΠΎΡ InfluxDB. ΠΠΎΠΆΠ΅ Π΄Π° ΡΠ²ΡΡΠΆΠ΅ Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΠΈΠ·ΠΌΠ΅ΡΠ²Π°Π½ΠΈΡ Π·Π°Π΅Π΄Π½ΠΎ (join), Π΄Π° ΠΈΠ·ΡΠΈΡΠ»ΠΈ Π½Π΅ΡΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ ΠΎΡ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡΠ΅ Π΄Π°Π½Π½ΠΈ, Π΄Π° Π·Π°ΠΏΠΈΡΠ΅ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΠ° ΠΎΠ±ΡΠ°ΡΠ½ΠΎ Π² InfluxDB, Π΄Π° ΠΈΠ·ΠΏΡΠ°ΡΠΈ ΠΏΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π΄ΠΎ Slack/Telegram/mail.
Π¦Π΅Π»ΠΈΡΡ ΡΡΠ°ΠΊ Π΅ Π³ΠΎΡΠΈΠ½ ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ±Π΅Π½
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 (
ΠΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΡΡΠ»ΠΎΠ²ΠΈΡ Π² ΠΈΠ·ΡΠΈΡΠ»Π΅Π½ΠΈΡΡΠ° (Π°ΠΊΠΎ Π΅ Π² Π»Π°ΠΌΠ±Π΄Π°)
|eval(lambda: if("value" > 0, true, false)
ΠΠΎΡΠ»Π΅Π΄Π½ΠΈ ΠΏΠ΅Ρ ΠΌΠΈΠ½ΡΡΠΈ ΠΎΡ ΡΡΡΠ±ΠΎΠΏΡΠΎΠ²ΠΎΠ΄Π° Π·Π° ΠΏΠ΅ΡΠΈΠΎΠ΄Π°
ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΡΡΠ±Π²Π° Π΄Π° ΡΡΠ°Π²Π½ΠΈΡΠ΅ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈΡΠ΅ ΠΎΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ ΠΏΠ΅Ρ ΠΌΠΈΠ½ΡΡΠΈ Ρ ΠΏΡΠ΅Π΄Ρ ΠΎΠ΄Π½Π°ΡΠ° ΡΠ΅Π΄ΠΌΠΈΡΠ°. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π²Π·Π΅ΠΌΠ΅ΡΠ΅ Π΄Π²Π΅ ΠΏΠ°ΡΡΠΈΠ΄ΠΈ Π΄Π°Π½Π½ΠΈ Π² Π΄Π²Π΅ ΠΎΡΠ΄Π΅Π»Π½ΠΈ ΠΏΠ°ΡΡΠΈΠ΄ΠΈ ΠΈΠ»ΠΈ Π΄Π° ΠΈΠ·Π²Π»Π΅ΡΠ΅ΡΠ΅ ΡΠ°ΡΡ ΠΎΡ Π΄Π°Π½Π½ΠΈΡΠ΅ ΠΎΡ ΠΏΠΎ-Π³ΠΎΠ»ΡΠΌ ΠΏΠ΅ΡΠΈΠΎΠ΄:
|where(lambda: duration((unixNano(now()) - unixNano("time"))/1000, 1u) < 5m)
ΠΠ»ΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π° Π·Π° ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ ΠΏΠ΅Ρ ΠΌΠΈΠ½ΡΡΠΈ Π±ΠΈ Π±ΠΈΠ»Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ΡΠΎ Π½Π° BarrierNode, ΠΊΠΎΠΉΡΠΎ ΠΏΡΠ΅ΠΊΡΡΠ²Π° Π΄Π°Π½Π½ΠΈΡΠ΅ ΠΏΡΠ΅Π΄ΠΈ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΎΡΠΎ Π²ΡΠ΅ΠΌΠ΅:
|barrier()
.period(5m)
ΠΡΠΈΠΌΠ΅ΡΠΈ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Go ΡΠ°Π±Π»ΠΎΠ½ΠΈ Π² ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΠ΅
Π¨Π°Π±Π»ΠΎΠ½ΠΈΡΠ΅ ΠΎΡΠ³ΠΎΠ²Π°ΡΡΡ Π½Π° ΡΠΎΡΠΌΠ°ΡΠ° ΠΎΡ ΠΏΠ°ΠΊΠ΅ΡΠ°
Π°ΠΊΠΎ-Π΄ΡΡΠ³ΠΎ
ΠΠΎΠ΄ΡΠ΅ΠΆΠ΄Π°ΠΌΠ΅ Π½Π΅ΡΠ°ΡΠ° ΠΈ Π½Π΅ Π·Π°Π΄Π΅ΠΉΡΡΠ²Π°ΠΌΠ΅ Ρ ΠΎΡΠ°ΡΠ° ΠΎΡΠ½ΠΎΠ²ΠΎ Ρ ΡΠ΅ΠΊΡΡ:
|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 Π·Π° ΠΈΠ·ΠΏΡΠ°ΡΠ°Π½Π΅ Π½Π° ΠΈΠ·Π²Π΅ΡΡΠΈΡ Π΄ΠΎ slack.
ΠΡΡΠ²ΠΎΠ½Π°ΡΠ°Π»Π½ΠΎ ΠΈΡΠΊΠ°Ρ
ΠΌΠ΅ Π΄Π° ΠΈΠ·ΠΏΡΠ°ΡΠΈΠΌ Π·Π°ΡΠΈΡΠ΅Π½Π° ΠΎΡ Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΡ Π³ΡΠ°ΡΠ°Π½Π° Π² ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΠ΅. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° Π½Π°ΠΏΠΈΡΠ΅ΡΠ΅ ΠΠ Π² ΡΠ΅ΠΌΠ°ΡΠ° ΠΊΡΠΌ ΠΏΡΠ΅Π΄ΠΈΡΠ½ΠΈΡ ΡΠΈΠ³Π½Π°Π» ΠΎΡ ΡΡΡΠ°ΡΠ° Π³ΡΡΠΏΠ°, Π° Π½Π΅ ΠΊΠ°ΡΠΎ ΠΎΡΠ΄Π΅Π»Π½ΠΎ ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΠ΅. ΠΠ°Π»ΠΊΠΎ ΠΏΠΎ-ΠΊΡΡΠ½ΠΎ - Π΄ΠΎΠ±Π°Π²Π΅ΡΠ΅ ΠΊΡΠΌ ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ΡΠΎ Π½Π°ΠΉ-ΡΠ΅ΡΡΠ°ΡΠ° Π³ΡΠ΅ΡΠΊΠ° ΠΏΡΠ΅Π· ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ 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")
ΠΠ»Π΅Π΄Π°ΠΉΡΠ΅ (cli): kapacitor -url
ΠΠΏΡΠΈΡ Ρ httpOut
ΠΠΎΠΊΠ°Π·Π²Π° Π΄Π°Π½Π½ΠΈ Π² ΡΠ΅ΠΊΡΡΠΈΡ ΠΊΠΎΠ½Π²Π΅ΠΉΠ΅Ρ:
|httpOut('something')
ΠΠ»Π΅Π΄Π°ΠΉΡΠ΅ (Π²Π·Π΅ΠΌΠ΅ΡΠ΅):
Π‘Ρ Π΅ΠΌΠ° Π½Π° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅
- ΠΡΡΠΊΠ° Π·Π°Π΄Π°ΡΠ° Π²ΡΡΡΠ° Π΄ΡΡΠ²ΠΎ Π·Π° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ Ρ ΠΏΠΎΠ»Π΅Π·Π½ΠΈ ΡΠΈΡΠ»Π° Π²ΡΠ² ΡΠΎΡΠΌΠ°ΡΠ°
graphviz . - ΠΠ·Π΅ΠΌΠ΅ΡΠ΅ Π±Π»ΠΎΠΊ
ΡΠΎΡΠΊΠ° . - ΠΠΎΡΡΠ°Π²Π΅ΡΠ΅ Π³ΠΎ Π²ΡΠ² Π²ΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΎΡΠ°,
Π½Π°ΡΠ»Π°Π΄ΠΈ ΡΠ΅ .
ΠΡΠ΄Π΅ Π΄ΡΡΠ³Π°Π΄Π΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π²Π·Π΅ΠΌΠ΅ΡΠ΅ ΡΠ΅ΠΉΠΊ?
ΠΊΠ»Π΅ΠΉΠΌΠΎ Π·Π° Π²ΡΠ΅ΠΌΠ΅ Π² influxdb ΠΏΡΠΈ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ Π·Π°ΠΏΠΈΡΠ²Π°Π½Π΅
ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π½Π°ΡΡΡΠΎΠΉΠ²Π°ΠΌΠ΅ ΠΏΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ Π·Π° ΡΡΠΌΠ°ΡΠ° ΠΎΡ Π·Π°ΡΠ²ΠΊΠΈ Π½Π° ΡΠ°Ρ (groupBy(1h)) ΠΈ ΠΈΡΠΊΠ°ΠΌΠ΅ Π΄Π° Π·Π°ΠΏΠΈΡΠ΅ΠΌ ΠΏΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ΡΠΎ, ΠΊΠΎΠ΅ΡΠΎ ΡΠ΅ Π΅ ΡΠ»ΡΡΠΈΠ»ΠΎ Π² influxdb (Π·Π° Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ ΠΊΡΠ°ΡΠΈΠ²ΠΎ ΡΠ°ΠΊΡΠ° Π½Π° ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Π½Π° Π³ΡΠ°ΡΠΈΠΊΠ°ΡΠ° Π² grafana).
influxDBOut() ΡΠ΅ Π·Π°ΠΏΠΈΡΠ΅ Π²ΡΠ΅ΠΌΠ΅Π²Π°ΡΠ° ΡΡΠΎΠΉΠ½ΠΎΡΡ ΠΎΡ ΠΏΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ΡΠΎ Π² ΠΊΠ»Π΅ΠΉΠΌΠΎΡΠΎ Π·Π° Π²ΡΠ΅ΠΌΠ΅; ΡΡΠΎΡΠ²Π΅ΡΠ½ΠΎ ΡΠΎΡΠΊΠ°ΡΠ° Π½Π° Π΄ΠΈΠ°Π³ΡΠ°ΠΌΠ°ΡΠ° ΡΠ΅ Π±ΡΠ΄Π΅ Π½Π°ΠΏΠΈΡΠ°Π½Π° ΠΏΠΎ-ΡΠ°Π½ΠΎ/ΠΏΠΎ-ΠΊΡΡΠ½ΠΎ ΠΎΡ ΠΏΡΠΈΡΡΠΈΠ³Π°Π½Π΅ΡΠΎ Π½Π° ΠΏΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ΡΠΎ.
ΠΠΎΠ³Π°ΡΠΎ ΡΠ΅ ΠΈΠ·ΠΈΡΠΊΠ²Π° ΡΠΎΡΠ½ΠΎΡΡ: Π·Π°ΠΎΠ±ΠΈΠΊΠ°Π»ΡΠΌΠ΅ ΡΠΎΠ·ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌ, ΠΊΠ°ΡΠΎ ΠΈΠ·Π²ΠΈΠΊΠ²Π°ΠΌΠ΅ ΠΏΠ΅ΡΡΠΎΠ½Π°Π»ΠΈΠ·ΠΈΡΠ°Π½ ΠΌΠ°Π½ΠΈΠΏΡΠ»Π°ΡΠΎΡ, ΠΊΠΎΠΉΡΠΎ ΡΠ΅ Π·Π°ΠΏΠΈΡΠ²Π° Π΄Π°Π½Π½ΠΈ Π² influxdb Ρ ΡΠ΅ΠΊΡΡΠΈΡ Π²ΡΠ΅ΠΌΠ΅Π²ΠΈ ΠΏΠ΅ΡΠ°Ρ.
Π΄ΠΎΠΊΠ΅Ρ, ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π°Π½Π΅ ΠΈ Π²Π½Π΅Π΄ΡΡΠ²Π°Π½Π΅
ΠΡΠΈ ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ kapacitor ΠΌΠΎΠΆΠ΅ Π΄Π° Π·Π°ΡΠ΅ΠΆΠ΄Π° Π·Π°Π΄Π°ΡΠΈ, ΡΠ°Π±Π»ΠΎΠ½ΠΈ ΠΈ ΠΌΠ°Π½ΠΈΠΏΡΠ»Π°ΡΠΎΡΠΈ ΠΎΡ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΡΠ°, ΠΏΠΎΡΠΎΡΠ΅Π½Π° Π² ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΡΠ° Π² Π±Π»ΠΎΠΊΠ° [load].
ΠΠ° Π΄Π° ΡΡΠ·Π΄Π°Π΄Π΅ΡΠ΅ ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ Π·Π°Π΄Π°ΡΠ°, ΠΈΠΌΠ°ΡΠ΅ Π½ΡΠΆΠ΄Π° ΠΎΡ ΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ Π½Π΅ΡΠ°:
- ΠΠΌΠ΅ Π½Π° ΡΠ°ΠΉΠ» β ΡΠ°Π·ΡΠΈΡΠ΅Π½ΠΎ Π² ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡ/ΠΈΠΌΠ΅ Π½Π° ΡΠΊΡΠΈΠΏΡ
- Π’ΠΈΠΏ β ΠΏΠΎΡΠΎΠΊ/ΠΏΠ°ΡΡΠΈΠ΄Π°
- dbrp β ΠΊΠ»ΡΡΠΎΠ²Π° Π΄ΡΠΌΠ° Π·Π° ΡΠΊΠ°Π·Π²Π°Π½Π΅ Π² ΠΊΠΎΡ Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ + ΠΏΠΎΠ»ΠΈΡΠΈΠΊΠ° ΡΠ΅ ΠΈΠ·ΠΏΡΠ»Π½ΡΠ²Π° ΡΠΊΡΠΈΠΏΡΡΡ (dbrp βΠ΄ΠΎΡΡΠ°Π²ΡΠΈΠΊ.β βautogenβ)
ΠΠΊΠΎ Π½ΡΠΊΠΎΡ ΠΏΠ°ΠΊΠ΅ΡΠ½Π° Π·Π°Π΄Π°ΡΠ° Π½Π΅ ΡΡΠ΄ΡΡΠΆΠ° ΡΠ΅Π΄ Ρ dbrp, ΡΡΠ»Π°ΡΠ° ΡΡΠ»ΡΠ³Π° ΡΠ΅ ΠΎΡΠΊΠ°ΠΆΠ΅ Π΄Π° ΡΡΠ°ΡΡΠΈΡΠ° ΠΈ ΡΠ΅ΡΡΠ½ΠΎ ΡΠ΅ Π½Π°ΠΏΠΈΡΠ΅ Π·Π° ΡΠΎΠ²Π° Π² Π΄Π½Π΅Π²Π½ΠΈΠΊΠ°.
Π chronograf, Π½Π°ΠΏΡΠΎΡΠΈΠ², ΡΠΎΠ·ΠΈ ΡΠ΅Π΄ Π½Π΅ ΡΡΡΠ±Π²Π° Π΄Π° ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π°, ΡΠΎΠΉ Π½Π΅ ΡΠ΅ ΠΏΡΠΈΠ΅ΠΌΠ° ΠΏΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° ΠΈ Π³Π΅Π½Π΅ΡΠΈΡΠ° Π³ΡΠ΅ΡΠΊΠ°.
Π₯Π°ΠΊ ΠΏΡΠΈ ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π°Π½Π΅ Π½Π° ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ: Dockerfile ΠΈΠ·Π»ΠΈΠ·Π° Ρ -1, Π°ΠΊΠΎ ΠΈΠΌΠ° ΡΠ΅Π΄ΠΎΠ²Π΅ Ρ //.+dbrp, ΠΊΠΎΠ΅ΡΠΎ ΡΠ΅ Π²ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π²Π΅Π΄Π½Π°Π³Π° Π΄Π° ΡΠ°Π·Π±Π΅ΡΠ΅ΡΠ΅ ΠΏΡΠΈΡΠΈΠ½Π°ΡΠ° Π·Π° Π½Π΅ΡΡΠΏΠ΅Ρ Π° ΠΏΡΠΈ ΡΠ³Π»ΠΎΠ±ΡΠ²Π°Π½Π΅ΡΠΎ Π½Π° ΠΊΠΎΠΌΠΏΠΈΠ»Π°ΡΠΈΡΡΠ°.
ΠΏΡΠΈΡΡΠ΅Π΄ΠΈΠ½Π΅ΡΠ΅ ΡΠ΅ ΠΊΡΠΌ Π΅Π΄ΠΈΠ½ ΠΊΡΠΌ ΠΌΠ½ΠΎΠ³ΠΎ
ΠΡΠΈΠΌΠ΅ΡΠ½Π° Π·Π°Π΄Π°ΡΠ°: ΡΡΡΠ±Π²Π° Π΄Π° Π²Π·Π΅ΠΌΠ΅ΡΠ΅ 95-ΠΈΡ ΠΏΡΠΎΡΠ΅Π½ΡΠΈΠ» ΠΎΡ ΡΠ°Π±ΠΎΡΠ½ΠΎΡΠΎ Π²ΡΠ΅ΠΌΠ΅ Π½Π° ΡΡΠ»ΡΠ³Π°ΡΠ° Π·Π° Π΅Π΄Π½Π° ΡΠ΅Π΄ΠΌΠΈΡΠ°, ΡΡΠ°Π²Π½Π΅ΡΠ΅ Π²ΡΡΠΊΠ° ΠΌΠΈΠ½ΡΡΠ° ΠΎΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ 10 Ρ ΡΠ°Π·ΠΈ ΡΡΠΎΠΉΠ½ΠΎΡΡ.
ΠΠ΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ΅ ΠΏΡΠΈΡΡΠ΅Π΄ΠΈΠ½ΡΠ²Π°Π½Π΅ "Π΅Π΄ΠΈΠ½ ΠΊΡΠΌ ΠΌΠ½ΠΎΠ³ΠΎ", ΠΏΠΎΡΠ»Π΅Π΄Π½Π°ΡΠ°/ΡΡΠ΅Π΄Π½Π°ΡΠ° ΡΡΠΎΠΉΠ½ΠΎΡΡ/ΠΌΠ΅Π΄ΠΈΠ°Π½Π°ΡΠ° Π½Π°Π΄ Π³ΡΡΠΏΠ° ΠΎΡ ΡΠΎΡΠΊΠΈ ΠΏΡΠ΅Π²ΡΡΡΠ° Π²ΡΠ·Π΅Π»Π° Π² ΠΏΠΎΡΠΎΠΊ, ΡΠ΅ Π±ΡΠ΄Π΅ Π²ΡΡΠ½Π°ΡΠ° Π³ΡΠ΅ΡΠΊΠ°ΡΠ° βΠ½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π΄ΠΎΠ±Π°Π²ΠΈ Π΄ΡΡΠ΅ΡΠ½ΠΈ Π½Π΅ΡΡΠΎΡΠ²Π΅ΡΡΡΠ²Π°ΡΠΈ ΡΡΠ±ΠΎΠ²Π΅: ΠΏΠ°ΡΡΠΈΠ΄Π° -> ΠΏΠΎΡΠΎΠΊβ.
Π Π΅Π·ΡΠ»ΡΠ°ΡΡΡ ΠΎΡ ΠΏΠ°ΡΡΠΈΠ΄Π°, ΠΊΠ°ΡΠΎ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° Π² Π»Π°ΠΌΠ±Π΄Π° ΠΈΠ·ΡΠ°Π·, ΡΡΡΠΎ Π½Π΅ ΡΠ΅ Π·Π°ΠΌΠ΅ΡΡΠ²Π°.
ΠΠΌΠ° ΠΎΠΏΡΠΈΡ Π·Π° Π·Π°ΠΏΠ°Π·Π²Π°Π½Π΅ Π½Π° Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΈΡΠ΅ Π½ΠΎΠΌΠ΅ΡΠ° ΠΎΡ ΠΏΡΡΠ²Π°ΡΠ° ΠΏΠ°ΡΡΠΈΠ΄Π° Π²ΡΠ² ΡΠ°ΠΉΠ» ΡΡΠ΅Π· udf ΠΈ Π·Π°ΡΠ΅ΠΆΠ΄Π°Π½Π΅ Π½Π° ΡΠΎΠ·ΠΈ ΡΠ°ΠΉΠ» ΡΡΠ΅Π· sideload.
ΠΠ°ΠΊΠ²ΠΎ ΡΠ΅ΡΠΈΡ ΠΌΠ΅ Ρ ΡΠΎΠ²Π°?
ΠΠΌΠ°ΠΌΠ΅ ΠΎΠΊΠΎΠ»ΠΎ 100 Ρ ΠΎΡΠ΅Π»ΡΠΊΠΈ Π΄ΠΎΡΡΠ°Π²ΡΠΈΠΊΠ°, Π²ΡΠ΅ΠΊΠΈ ΠΎΡ ΡΡΡ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° Π½ΡΠΊΠΎΠ»ΠΊΠΎ Π²ΡΡΠ·ΠΊΠΈ, Π΄Π° Π³ΠΎ Π½Π°ΡΠ΅ΡΠ΅ΠΌ ΠΊΠ°Π½Π°Π». ΠΠΌΠ° ΠΏΡΠΈΠ±Π»ΠΈΠ·ΠΈΡΠ΅Π»Π½ΠΎ 300 ΠΎΡ ΡΠ΅Π·ΠΈ ΠΊΠ°Π½Π°Π»ΠΈ, Π²ΡΠ΅ΠΊΠΈ ΠΎΡ ΠΊΠ°Π½Π°Π»ΠΈΡΠ΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΠ°Π΄Π½Π΅. ΠΡ Π²ΡΠΈΡΠΊΠΈ Π·Π°ΠΏΠΈΡΠ°Π½ΠΈ ΠΏΠΎΠΊΠ°Π·Π°ΡΠ΅Π»ΠΈ ΡΠ΅ Π½Π°Π±Π»ΡΠ΄Π°Π²Π°ΠΌΠ΅ ΠΏΡΠΎΡΠ΅Π½ΡΠ° Π½Π° Π³ΡΠ΅ΡΠΊΠΈ (Π·Π°ΡΠ²ΠΊΠΈ ΠΈ Π³ΡΠ΅ΡΠΊΠΈ).
ΠΠ°ΡΠΎ Π½Π΅ Π³ΡΠ°ΡΠ°Π½Π°?
ΠΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΡΡΠ° Π·Π° Π³ΡΠ΅ΡΠΊΠΈ, ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΠ°Π½ΠΈ Π² Grafana, ΠΈΠΌΠ°Ρ Π½ΡΠΊΠΎΠ»ΠΊΠΎ Π½Π΅Π΄ΠΎΡΡΠ°ΡΡΠΊΠ°. ΠΡΠΊΠΎΠΈ ΡΠ° ΠΊΡΠΈΡΠΈΡΠ½ΠΈ, Π·Π° Π½ΡΠΊΠΎΠΈ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠΈ Π·Π°ΡΠ²ΠΎΡΠΈΡΠ΅ ΠΎΡΠΈΡΠ΅, Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡ ΠΎΡ ΡΠΈΡΡΠ°ΡΠΈΡΡΠ°.
Grafana Π½Π΅ Π·Π½Π°Π΅ ΠΊΠ°ΠΊ Π΄Π° ΠΈΠ·ΡΠΈΡΠ»ΡΠ²Π° ΠΌΠ΅ΠΆΠ΄Ρ ΠΈΠ·ΠΌΠ΅ΡΠ²Π°Π½ΠΈΡ + ΡΠΈΠ³Π½Π°Π»ΠΈΠ·ΠΈΡΠ°Π½Π΅, Π½ΠΎ Π½ΠΈ ΡΡΡΠ±Π²Π° ΠΏΡΠΎΡΠ΅Π½Ρ (Π·Π°ΡΠ²ΠΊΠΈ-Π³ΡΠ΅ΡΠΊΠΈ)/Π·Π°ΡΠ²ΠΊΠΈ.
ΠΡΠ΅ΡΠΊΠΈΡΠ΅ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°Ρ Π³Π°Π΄Π½ΠΈ:
Π ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ Π·Π»ΠΎ, ΠΊΠΎΠ³Π°ΡΠΎ ΡΠ΅ Π³Π»Π΅Π΄Π° Ρ ΡΡΠΏΠ΅ΡΠ½ΠΈ Π·Π°ΡΠ²ΠΊΠΈ:
ΠΠΎΠ±ΡΠ΅, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΡΠΈΡΠ»ΠΈΠΌ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»Π½ΠΎ ΡΠ°ΡΠΈΡΠ°ΡΠ° Π² ΡΡΠ»ΡΠ³Π°ΡΠ° ΠΏΡΠ΅Π΄ΠΈ grafana ΠΈ Π² Π½ΡΠΊΠΎΠΈ ΡΠ»ΡΡΠ°ΠΈ ΡΠΎΠ²Π° ΡΠ΅ ΡΠ°Π±ΠΎΡΠΈ. ΠΠΎ Π½Π΅ ΠΈ Π² Π½Π°ΡΠ°ΡΠ°, Π·Π°ΡΠΎΡΠΎ... Π·Π° Π²ΡΠ΅ΠΊΠΈ ΠΊΠ°Π½Π°Π» Π½Π΅Π³ΠΎΠ²ΠΎΡΠΎ ΡΠΎΠ±ΡΡΠ²Π΅Π½ΠΎ ΡΡΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΠ΅ ΡΠ΅ ΡΡΠΈΡΠ° Π·Π° βΠ½ΠΎΡΠΌΠ°Π»Π½ΠΎβ, Π° ΡΠΈΠ³Π½Π°Π»ΠΈΡΠ΅ ΡΠ°Π±ΠΎΡΡΡ ΡΠΏΠΎΡΠ΅Π΄ ΡΡΠ°ΡΠΈΡΠ½ΠΈ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ (Π½ΠΈΠ΅ Π³ΠΈ ΡΡΡΡΠΈΠΌ Ρ ΠΎΡΠΈΡΠ΅ ΡΠΈ, ΠΏΡΠΎΠΌΠ΅Π½ΡΠΌΠ΅ Π³ΠΈ, Π°ΠΊΠΎ ΠΈΠΌΠ° ΡΠ΅ΡΡΠΈ ΡΠΈΠ³Π½Π°Π»ΠΈ).
Π’ΠΎΠ²Π° ΡΠ° ΠΏΡΠΈΠΌΠ΅ΡΠΈ Π·Π° βΠ½ΠΎΡΠΌΠ°Π»Π½ΠΎβ Π·Π° ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΠΊΠ°Π½Π°Π»ΠΈ:
ΠΡΠ΅Π½Π΅Π±ΡΠ΅Π³Π²Π°ΠΌΠ΅ ΠΏΡΠ΅Π΄ΠΈΡΠ½Π°ΡΠ° ΡΠΎΡΠΊΠ° ΠΈ ΠΏΡΠΈΠ΅ΠΌΠ°ΠΌΠ΅, ΡΠ΅ βΠ½ΠΎΡΠΌΠ°Π»Π½Π°ΡΠ°β ΠΊΠ°ΡΡΠΈΠ½Π° Π΅ ΠΏΠΎΠ΄ΠΎΠ±Π½Π° Π·Π° Π²ΡΠΈΡΠΊΠΈ Π΄ΠΎΡΡΠ°Π²ΡΠΈΡΠΈ. Π‘Π΅Π³Π° Π²ΡΠΈΡΠΊΠΎ Π΅ Π½Π°ΡΠ΅Π΄ ΠΈ ΠΌΠΎΠΆΠ΅ΠΌ Π»ΠΈ Π΄Π° ΡΠ΅ ΡΠΏΡΠ°Π²ΠΈΠΌ ΡΡΡ ΡΠΈΠ³Π½Π°Π»ΠΈ Π² grafana?
ΠΠΎΠΆΠ΅ΠΌ, Π½ΠΎ Π½Π°ΠΈΡΡΠΈΠ½Π° Π½Π΅ ΠΈΡΠΊΠ°ΠΌΠ΅, Π·Π°ΡΠΎΡΠΎ ΡΡΡΠ±Π²Π° Π΄Π° ΠΈΠ·Π±Π΅ΡΠ΅ΠΌ Π΅Π΄Π½Π° ΠΎΡ ΠΎΠΏΡΠΈΠΈΡΠ΅:
Π°) Π½Π°ΠΏΡΠ°Π²Π΅ΡΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ Π³ΡΠ°ΡΠΈΠΊΠΈ Π·Π° Π²ΡΠ΅ΠΊΠΈ ΠΊΠ°Π½Π°Π» ΠΏΠΎΠΎΡΠ΄Π΅Π»Π½ΠΎ (ΠΈ Π±ΠΎΠ»Π΅Π·Π½Π΅Π½ΠΎ Π³ΠΈ ΠΏΡΠΈΠ΄ΡΡΠΆΠ΅ΡΠ΅)
Π±) ΠΎΡΡΠ°Π²Π΅ΡΠ΅ Π΅Π΄Π½Π° Π΄ΠΈΠ°Π³ΡΠ°ΠΌΠ° Ρ Π²ΡΠΈΡΠΊΠΈ ΠΊΠ°Π½Π°Π»ΠΈ (ΠΈ ΡΠ΅ ΠΈΠ·Π³ΡΠ±Π΅ΡΠ΅ Π² ΡΠ²Π΅ΡΠ½ΠΈΡΠ΅ Π»ΠΈΠ½ΠΈΠΈ ΠΈ ΠΏΠ΅ΡΡΠΎΠ½Π°Π»ΠΈΠ·ΠΈΡΠ°Π½ΠΈΡΠ΅ ΡΠΈΠ³Π½Π°Π»ΠΈ)
ΠΠ°ΠΊ Π³ΠΎ Π½Π°ΠΏΡΠ°Π²ΠΈ?
ΠΡΠ½ΠΎΠ²ΠΎ ΠΈΠΌΠ° Π΄ΠΎΠ±ΡΡ Π½Π°ΡΠ°Π»Π΅Π½ ΠΏΡΠΈΠΌΠ΅Ρ Π² Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡΠ° (
ΠΠ°ΠΊΠ²ΠΎ Π½Π°ΠΏΡΠ°Π²ΠΈΡ ΠΌΠ΅ Π² ΠΊΡΠ°ΠΉΠ½Π° ΡΠΌΠ΅ΡΠΊΠ°:
- ΠΏΡΠΈΡΡΠ΅Π΄ΠΈΠ½ΡΠ²Π°Π½Π΅ ΠΊΡΠΌ Π΄Π²Π΅ ΡΠ΅ΡΠΈΠΈ Π·Π° Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΡΠ°ΡΠ°, Π³ΡΡΠΏΠΈΡΠ°Π½Π΅ ΠΏΠΎ ΠΊΠ°Π½Π°Π»ΠΈ;
- ΠΏΠΎΠΏΡΠ»Π½Π΅ΡΠ΅ ΡΠ΅ΡΠΈΡΡΠ° ΠΏΠΎ Π³ΡΡΠΏΠ°, Π°ΠΊΠΎ Π½ΡΠΌΠ° Π΄Π°Π½Π½ΠΈ;
- ΡΡΠ°Π²Π½Π΅ΡΠ΅ ΠΌΠ΅Π΄ΠΈΠ°Π½Π°ΡΠ° ΠΎΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ 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).
ΠΠ°ΡΠΈΠ΅ΡΠ°ΡΠ° Π·Π° Π²Π»ΠΈΠ·Π°Π½Π΅ Π½Π΅ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ Π²ΠΈΡΠΎΠΊΠ° - ΠΎΠΏΠΈΡΠ°ΠΉΡΠ΅, Π°ΠΊΠΎ Π³ΡΠ°ΡΠ°Π½Π° ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΈ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΈ Π½Π΅ Π·Π°Π΄ΠΎΠ²ΠΎΠ»ΡΠ²Π°Ρ Π½Π°ΠΏΡΠ»Π½ΠΎ Π²Π°ΡΠΈΡΠ΅ ΠΆΠ΅Π»Π°Π½ΠΈΡ.
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: www.habr.com