์๋ง๋ ์ค๋๋ ์๋น์ค ์งํ๋ฅผ ์์งํด์ผ ํ๋ ์ด์ ๋ฅผ ๋ฌป๋ ์ฌ๋์ ์๋ฌด๋ ์์ ๊ฒ์
๋๋ค. ๋ค์ ๋
ผ๋ฆฌ์ ๋จ๊ณ๋ ์์ง๋ ์งํ์ ๋ํด ํธ๋ฆฌํ ์ฑ๋(๋ฉ์ผ, Slack, Telegram)์ ๋ฐ์ดํฐ ํธ์ฐจ์ ๋ํด ์๋ฆฌ๋ ๊ฒฝ๊ณ ๋ฅผ ์ค์ ํ๋ ๊ฒ์
๋๋ค. ์จ๋ผ์ธ ํธํ
์์ฝ ์๋น์ค์์
Kapacitor๋ InfluxDB์ ๋ฉํธ๋ฆญ์ ์ฒ๋ฆฌํ ์ ์๋ TICK ์คํ์ ์ผ๋ถ์
๋๋ค. ์ฌ๋ฌ ์ธก์ ๊ฐ์ ํจ๊ป ์ฐ๊ฒฐ(์กฐ์ธ)ํ๊ณ , ์์ ๋ ๋ฐ์ดํฐ์์ ์ ์ฉํ ๊ฒ์ ๊ณ์ฐํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ 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()
.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)
ํด๋น ๊ธฐ๊ฐ ๋์ ํ์ดํ๋ผ์ธ์์ ๋ง์ง๋ง XNUMX๋ถ
์๋ฅผ ๋ค์ด ์ง๋ XNUMX๋ถ ๋์์ ๊ฐ์ ์ง๋์ฃผ์ ๋น๊ตํด์ผ ํฉ๋๋ค. ๋ ๊ฐ์ ๋ณ๋ ๋ฐฐ์น๋ก ๋ ๊ฐ์ ๋ฐ์ดํฐ ๋ฐฐ์น๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ๋ ํฐ ๊ธฐ๊ฐ์์ ๋ฐ์ดํฐ์ ์ผ๋ถ๋ฅผ ์ถ์ถํ ์ ์์ต๋๋ค.
|where(lambda: duration((unixNano(now()) - unixNano("time"))/1000, 1u) < 5m)
๋ง์ง๋ง XNUMX๋ถ ๋์์ ๋์์ ์ง์ ๋ ์๊ฐ ์ด์ ์ ๋ฐ์ดํฐ๋ฅผ ์ฐจ๋จํ๋ 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" }}')
๋ง์ถคํ ํธ๋ค๋ฌ
์ฒ๋ฆฌ๊ธฐ์ ํฐ ๋ชฉ๋ก์๋ ์ ๋ฌ๋ ๋งค๊ฐ๋ณ์(stdin)๋ฅผ ์ฌ์ฉํ์ฌ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ ์ ์๋ exec๊ฐ ํฌํจ๋์ด ์์ต๋๋ค. ์ฐฝ์์ฑ ๊ทธ ์ด์์ ์๋๋๋ค!
์ฐ๋ฆฌ์ ๊ด์ต ์ค ํ๋๋ Slack์ ์๋ฆผ์ ๋ณด๋ด๋ ์์ Python ์คํฌ๋ฆฝํธ์
๋๋ค.
์ฒ์์๋ ์น์ธ์ผ๋ก ๋ณดํธ๋ grafana ์ฌ์ง์ ๋ฉ์์ง๋ก ๋ณด๋ด๊ณ ์ถ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ณ๋์ ๋ฉ์์ง๊ฐ ์๋ ๋์ผํ ๊ทธ๋ฃน์ ์ด์ ๊ฒฝ๊ณ ์ ๋ํ ์ค๋ ๋์ OK๋ฅผ ์์ฑํฉ๋๋ค. ์กฐ๊ธ ํ์ - ์ง๋ 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')
์์ฒญ(๋ฐ๊ธฐ):
์คํ ๊ณํ
- ๊ฐ ์์
์ ๋ค์ ํ์์ผ๋ก ์ ์ฉํ ์ซ์๊ฐ ํฌํจ๋ ์คํ ํธ๋ฆฌ๋ฅผ ๋ฐํํฉ๋๋ค.
๊ทธ๋ํ๋น์ฆ . - ๋ธ๋ก์ ๊ฐ์ ธ ๊ฐ๋ผ.
์ . - ๋ทฐ์ด์ ๋ถ์ฌ๋ฃ๊ณ ,
์ฆ๊ธฐ๋ค .
๊ฐํด๋ ๋ ์ด๋์ ๊ตฌํ ์ ์๋์?
์ฐ๊ธฐ ์ ์ฅ ์ influxdb์ ํ์์คํฌํ
์๋ฅผ ๋ค์ด, ์๊ฐ๋น ์์ฒญ ํฉ๊ณ(groupBy(1h))์ ๋ํ ์๋ฆผ์ ์ค์ ํ๊ณ influxdb์ ๋ฐ์ํ ์๋ฆผ์ ๊ธฐ๋กํ๋ ค๊ณ ํฉ๋๋ค(๋ฌธ์ ์ ์ฌ์ค์ grafana์ ๊ทธ๋ํ์ ์๋ฆ๋ต๊ฒ ํ์ํ๊ธฐ ์ํด).
influxDBOut()์ ๊ฒฝ๊ณ ์ ์๊ฐ ๊ฐ์ ํ์์คํฌํ์ ๊ธฐ๋กํ๋ฏ๋ก ์ฐจํธ์ ์ง์ ์ ๊ฒฝ๊ณ ๊ฐ ๋์ฐฉํ ๊ฒ๋ณด๋ค ์ด์ /๋ฆ๊ฒ ๊ธฐ๋ก๋ฉ๋๋ค.
์ ํ์ฑ์ด ํ์ํ ๊ฒฝ์ฐ: ํ์ฌ ํ์์คํฌํ๋ฅผ ์ฌ์ฉํ์ฌ influxdb์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ์ฌ์ฉ์ ์ ์ ํธ๋ค๋ฌ๋ฅผ ํธ์ถํ์ฌ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค.
๋์ปค, ๋น๋ ๋ฐ ๋ฐฐํฌ
์์ ์ kapacitor๋ [load] ๋ธ๋ก์ ๊ตฌ์ฑ์ ์ง์ ๋ ๋๋ ํฐ๋ฆฌ์์ ์์ , ํ ํ๋ฆฟ ๋ฐ ํธ๋ค๋ฌ๋ฅผ ๋ก๋ํ ์ ์์ต๋๋ค.
์์ ์ ์ฌ๋ฐ๋ฅด๊ฒ ์์ฑํ๋ ค๋ฉด ๋ค์ ์ฌํญ์ด ํ์ํฉ๋๋ค.
- ํ์ผ ์ด๋ฆ โ ์คํฌ๋ฆฝํธ ID/์ด๋ฆ์ผ๋ก ํ์ฅ๋จ
- ์ ํ โ ์คํธ๋ฆผ/๋ฐฐ์น
- dbrp โ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค + ์ ์ฑ ์ ๋ํ๋ด๋ ํค์๋(dbrp โsupplier.โโautogenโ)
์ผ๋ถ ๋ฐฐ์น ์์ ์ dbrp ์ค์ด ํฌํจ๋์ด ์์ง ์์ผ๋ฉด ์ ์ฒด ์๋น์ค๊ฐ ์์์ ๊ฑฐ๋ถํ๊ณ ์ด์ ๋ํด ์์งํ๊ฒ ๋ก๊ทธ์ ๊ธฐ๋กํฉ๋๋ค.
๋ฐ๋๋ก chronograf์์๋ ์ด ์ค์ด ์กด์ฌํด์๋ ์ ๋๋ฉฐ, ์ธํฐํ์ด์ค๋ฅผ ํตํด ํ์ฉ๋์ง ์๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ปจํ ์ด๋ ๋น๋ ์ ํดํน: //.+dbrp๊ฐ ํฌํจ๋ ํ์ด ์๋ ๊ฒฝ์ฐ Dockerfile์ -1๋ก ์ข ๋ฃ๋๋ฏ๋ก ๋น๋๋ฅผ ์ด์ ๋ธํ ๋ ์คํจ ์ด์ ๋ฅผ ์ฆ์ ์ดํดํ ์ ์์ต๋๋ค.
์ผ๋๋ค์ ํฉ๋ฅํ๋ค
์์ ์์ : ์ผ์ฃผ์ผ ๋์ ์๋น์ค ์ด์ ์๊ฐ์ 95๋ฒ์งธ ๋ฐฑ๋ถ์์๋ฅผ ๊ฐ์ ธ์์ ๋ง์ง๋ง 10๋ถ์ ๊ฐ ๋ถ์์๋ฅผ ์ด ๊ฐ๊ณผ ๋น๊ตํด์ผ ํฉ๋๋ค.
์ผ๋๋ค ์กฐ์ธ์ ์ํํ ์ ์์ต๋๋ค. ํฌ์ธํธ ๊ทธ๋ฃน์ ๋ํ ๋ง์ง๋ง/ํ๊ท /์ค์๊ฐ์ ๋ ธ๋๋ฅผ ์คํธ๋ฆผ์ผ๋ก ์ ํํฉ๋๋ค. "์ผ์นํ์ง ์๋ ํ์ ๊ฐ์ฅ์๋ฆฌ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค: ๋ฐฐ์น -> ์คํธ๋ฆผ" ์ค๋ฅ๊ฐ ๋ฐํ๋ฉ๋๋ค.
๋๋ค ์์ ๋ณ์์ธ ์ผ๊ด ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ ๋์ฒด๋์ง ์์ต๋๋ค.
์ฒซ ๋ฒ์งธ ๋ฐฐ์น์์ ํ์ํ ์ซ์๋ฅผ udf๋ฅผ ํตํด ํ์ผ์ ์ ์ฅํ๊ณ ์ฌ์ด๋๋ก๋๋ฅผ ํตํด ์ด ํ์ผ์ ๋ก๋ํ๋ ์ต์ ์ด ์์ต๋๋ค.
์ด๊ฒ์ผ๋ก ๋ฌด์์ ํด๊ฒฐํ์ต๋๊น?
์ฐ๋ฆฌ๋ ์ฝ 100๊ฐ์ ํธํ ๊ณต๊ธ์ ์ฒด๋ฅผ ๋ณด์ ํ๊ณ ์์ผ๋ฉฐ ๊ฐ๊ฐ์ ์ฌ๋ฌ ์ฐ๊ฒฐ์ ๊ฐ์ง ์ ์์ต๋๋ค. ์ด๋ฅผ ์ฑ๋์ด๋ผ๊ณ ๋ถ๋ฅด๊ฒ ์ต๋๋ค. ์ด๋ฌํ ์ฑ๋์ ์ฝ 300๊ฐ๊ฐ ์์ผ๋ฉฐ, ๊ฐ ์ฑ๋์ด ๋์ด์ง ์ ์์ต๋๋ค. ๊ธฐ๋ก๋ ๋ชจ๋ ์งํ ์ค์์ ์ค๋ฅ์จ(์์ฒญ ๋ฐ ์ค๋ฅ)์ ๋ชจ๋ํฐ๋งํฉ๋๋ค.
๊ทธ๋ผํ๋๋ ์ ์๋๋์?
Grafana์ ๊ตฌ์ฑ๋ ์ค๋ฅ ๊ฒฝ๊ณ ์๋ ๋ช ๊ฐ์ง ๋จ์ ์ด ์์ต๋๋ค. ์ํฉ์ ๋ฐ๋ผ ์ผ๋ถ๋ ์ค์ํ๊ณ ์ผ๋ถ๋ ๋์ ๊ฐ์ ์ ์์ต๋๋ค.
Grafana๋ ์ธก์ + ์๋ฆผ ๊ฐ ๊ณ์ฐ ๋ฐฉ๋ฒ์ ๋ชจ๋ฅด์ง๋ง ๋น์จ(์์ฒญ-์ค๋ฅ)/์์ฒญ์ด ํ์ํฉ๋๋ค.
์ค๋ฅ๊ฐ ์ฌํด ๋ณด์ ๋๋ค.
์ฑ๊ณต์ ์ธ ์์ฒญ์ผ๋ก ๋ณผ ๋ ๋ ์
ํฉ๋๋ค.
์ข์ต๋๋ค. Grafana ์ด์ ์ ์๋น์ค ์๊ธ์ ๋ฏธ๋ฆฌ ๊ณ์ฐํ ์ ์์ผ๋ฉฐ ๊ฒฝ์ฐ์ ๋ฐ๋ผ ์ด๊ฒ์ด ์๋ํ ์๋ ์์ต๋๋ค. ํ์ง๋ง ์ฐ๋ฆฌ์ ๊ฒฝ์ฐ๋ ์๋๊ธฐ ๋๋ฌธ์... ๊ฐ ์ฑ๋๋ง๋ค ์์ฒด ๋น์จ์ด "์ ์"์ผ๋ก ๊ฐ์ฃผ๋๋ฉฐ ๊ฒฝ๊ณ ๋ ์ ์ ๊ฐ์ ๋ฐ๋ผ ์๋ํฉ๋๋ค(๋์ผ๋ก ์ฐพ๊ณ ๊ฒฝ๊ณ ๊ฐ ์์ฃผ ๋ฐ์ํ๋ฉด ๋ณ๊ฒฝํฉ๋๋ค).
๋ค์์ ๋ค์ํ ์ฑ๋์ ๋ํ "์ ์"์ ์์ ๋๋ค.
์ฐ๋ฆฌ๋ ์ด์ ์์ ์ ๋ฌด์ํ๊ณ "์ ์์ ์ธ" ๊ทธ๋ฆผ์ด ๋ชจ๋ ๊ณต๊ธ์
์ฒด์ ์ ์ฌํ๋ค๊ณ ๊ฐ์ ํฉ๋๋ค. ์ด์ ๋ชจ๋ ๊ฒ์ด ๊ด์ฐฎ์ต๋๋ค. Grafana์์ ๊ฒฝ๊ณ ๋ฅผ ํตํด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๊น?
ํ ์ ์์ง๋ง ์ค์ ๋ก๋ ์ํ์ง ์์ต๋๋ค. ์๋ํ๋ฉด ๋ค์ ์ต์
์ค ํ๋๋ฅผ ์ ํํด์ผ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
a) ๊ฐ ์ฑ๋์ ๋ํด ๊ฐ๋ณ์ ์ผ๋ก ๋ง์ ๊ทธ๋ํ๋ฅผ ๋ง๋ญ๋๋ค(๊ทธ๋ฆฌ๊ณ ๊ณ ํต์ค๋ฝ๊ฒ ๋๋ฐํฉ๋๋ค).
b) ๋ชจ๋ ์ฑ๋์ด ํฌํจ๋ ํ๋์ ์ฐจํธ๋ฅผ ๋จ๊น๋๋ค. (๊ทธ๋ฆฌ๊ณ ๋ค์ฑ๋ก์ด ์ ๊ณผ ๋ง์ถคํ ์๋ฆผ์ ๋น ์ ธ๋ค๊ฒ ๋ฉ๋๋ค.)
๋ ์ด๋ป๊ฒ ๊ทธ๊ฑธ ํ๋?
๋ค์ ํ ๋ฒ ๋ฌธ์์ ์ข์ ์์ ์์ ๊ฐ ์์ต๋๋ค(
์ฐ๋ฆฌ๊ฐ ๊ฒฐ๊ตญ ํ ์ผ์:
- ์ฑ๋๋ณ๋ก ๊ทธ๋ฃนํํ์ฌ ๋ช ์๊ฐ ์์ ๋ ๊ฐ์ ์๋ฆฌ์ฆ์ ์ฐธ์ฌํ์ธ์.
- ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ๊ทธ๋ฃน๋ณ๋ก ์๋ฆฌ์ฆ๋ฅผ ์ฑ์ฐ์ญ์์ค.
- ์ง๋ 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)๋ฅผ ์คํํ๋ ๋ฐ ํ์ํฉ๋๋ค.
์ง์
์ฅ๋ฒฝ์ ๊ทธ๋ค์ง ๋์ง ์์ต๋๋ค. grafana ๋๋ ๊ธฐํ ๋๊ตฌ๊ฐ ๊ทํ์ ์๊ตฌ๋ฅผ ์์ ํ ์ถฉ์กฑ์ํค์ง ๋ชปํ๋ค๋ฉด ์๋ํด ๋ณด์ญ์์ค.
์ถ์ฒ : habr.com