์ค๋๋ ์๋ ์๋น์ค ์งํ๋ฅผ ์์งํ๋ ๊ฒ์ด ์ ํ์ํ์ง ์๋ฌธ์ ํ์ ์ฌ๋์ ์๋ฌด๋ ์์ ๊ฒ์ ๋๋ค. ๋ค์ ๋ ผ๋ฆฌ์ ๋จ๊ณ๋ ์์ง๋ ์งํ์ ๋ํ ์๋ฆผ์ ์ค์ ํ๋ ๊ฒ์ ๋๋ค. ์ด๋ฅผ ํตํด ํธ๋ฆฌํ ์ฑ๋(๋ฉ์ผ, Slack, Telegram)์ ํตํด ๋ฐ์ดํฐ์ ํธ์ฐจ๋ฅผ ์๋ ค์ค๋๋ค. ์จ๋ผ์ธ ํธํ ์์ฝ ์๋น์ค์์ ๋ชจ๋ ์๋น์ค ์งํ๋ InfluxDB๋ก ์คํธ๋ฆฌ๋ฐ๋๊ณ Grafana์ ํ์๋๋ฉฐ, ๊ธฐ๋ณธ ์๋ฆผ๋ ๊ตฌ์ฑ๋ฉ๋๋ค. "๋ฌด์ธ๊ฐ๋ฅผ ๊ณ์ฐํด์ ์ด๊ฒ๊ณผ ๋น๊ตํด์ผ ํฉ๋๋ค"์ ๊ฐ์ ์์ ์๋ Kapacitor๋ฅผ ์ฌ์ฉํฉ๋๋ค.

Kapacitor๋ InfluxDB์ ๋ฉํธ๋ฆญ์ ์ฒ๋ฆฌํ ์ ์๋ TICK ์คํ์ ์ผ๋ถ์
๋๋ค. ์ฌ๋ฌ ์ฐจ์์ ์ฐ๊ฒฐ(์กฐ์ธ)ํ๊ณ , ์์ ๋ ๋ฐ์ดํฐ์์ ์ ์ฉํ ๊ฒ์ ๊ณ์ฐํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ InfluxDB์ ์ฐ๊ณ , Slack/Telegram/๋ฉ์ผ์ ์๋ฆผ์ ๋ณด๋ผ ์ ์์ต๋๋ค.
์ ์ฒด ์คํ์๋ ๋ฉ์ง๊ณ ์์ธํ ๋ด์ฉ์ด ์์ต๋๋ค. ํ์ง๋ง ๋งค๋ด์ผ์ ๋ช ํํ๊ฒ ํ์๋์ด ์์ง ์์ ์ ์ฉํ ์ ๋ณด๋ ํญ์ ์์ต๋๋ค. ์ด ๊ธฐ์ฌ์์๋ 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)
์กฐ์ธ ์ฑ์ฐ๊ธฐ(๋ด๋ถ ๋ ์ธ๋ถ)
๊ธฐ๋ณธ์ ์ผ๋ก join์ ๋ฐ์ดํฐ๊ฐ ์๋ ์ง์ (๋ด๋ถ)์ ์ญ์ ํฉ๋๋ค.
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)
ํ์ดํ๋ผ์ธ์ ๋ง์ง๋ง 5๋ถ ๋์์ ๊ธฐ๊ฐ
์๋ฅผ ๋ค์ด, ์ง๋ 5๋ถ ๋์์ ๊ฐ์ ์ง๋์ฃผ ๊ฐ๊ณผ ๋น๊ตํด์ผ ํฉ๋๋ค. ๋ ๊ฐ์ ๋ณ๋ ๋ฐฐ์น๋ก ๋ ๊ฐ์ ๋ฐ์ดํฐ ๋ฐฐ์น๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ๋ ๊ธด ๊ธฐ๊ฐ์ ๋ฐ์ดํฐ ์ผ๋ถ๋ฅผ ์ถ์ถํ ์ ์์ต๋๋ค.
|where(lambda: duration((unixNano(now()) - unixNano("time"))/1000, 1u) < 5m)
๋ง์ง๋ง 5๋ถ์ ๋ํ ๋์์ ์ง์ ๋ ์๊ฐ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ฐจ๋จํ๋ 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์ ์๋ฆผ์ ๋ณด๋ด๊ธฐ ์ํ ์์ ํ์ด์ฌ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋๋ ๊ฒ์
๋๋ค.
์ฒ์์๋ 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 :9092 ๋ก๊ทธ ๋ ๋ฒจ=์ค๋ฅ
httpOut ์ต์
ํ์ฌ ํ์ดํ๋ผ์ธ์ ๋ฐ์ดํฐ๋ฅผ ํ์ํฉ๋๋ค.
|httpOut('something')
์์ฒญ(๋ฐ๊ธฐ): :9092/kapacitor/v1/์์ /์์ _์ด๋ฆ/๋ญ๊ฐ
๊ตฌํ ๊ณํ
- ๊ฐ ์์ ์ ๋ค์ ํ์์ผ๋ก ์ ์ฉํ ์ซ์๊ฐ ํฌํจ๋ ์คํ ํธ๋ฆฌ๋ฅผ ๋ฐํํฉ๋๋ค. .
- ์ฐ๋ฆฌ๋ ๋ธ๋ก์ ๊ฐ์ ธ๊ฐ๋๋ค .
- ๋ทฐ์ด์ ๋ถ์ฌ๋ฃ๊ธฐ .
๋ ์ด๋์์ ๊ธ์ด๋ชจ์ ์ ์๋์?
influxdb์ writeback ํ์์คํฌํ
์๋ฅผ ๋ค์ด, ์ฐ๋ฆฌ๋ ์๊ฐ๋น ์์ฒญ ํฉ๊ณ์ ๋ํ ์๋ฆผ์ ์ค์ ํ๊ณ (groupBy(1h)) ๋ฐ์ํ ์๋ฆผ์ influxdb์ ๊ธฐ๋กํ๋ ค๊ณ ํฉ๋๋ค(grafana์ ๊ทธ๋ํ์์ ๋ฌธ์ ์ ์ฌ์ค์ ์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด).
influxDBOut()์ ๊ฒฝ๊ณ ์ ์๊ฐ ๊ฐ์ ํ์์คํฌํ์ ๊ธฐ๋กํ๋ฏ๋ก ์ฐจํธ์ ์ง์ ์ ๊ฒฝ๊ณ ๊ฐ ๋์ฐฉํ๊ธฐ ์ /ํ๋ก ๊ธฐ๋ก๋ฉ๋๋ค.
์ ๋ฐ๋๊ฐ ์๊ตฌ๋๋ ๊ฒฝ์ฐ ์ฌ์ฉ์ ์ ์ ํธ๋ค๋ฌ๋ฅผ ํธ์ถํ์ฌ ํ์ฌ ํ์์คํฌํ์ ํจ๊ป influxdb์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋กํจ์ผ๋ก์จ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค.
๋์ปค, ๋น๋ ๋ฐ ๋ฐฐํฌ
์์ํ ๋ kapacitor๋ config์ [load] ๋ธ๋ก์์ ์ง์ ๋ ๋๋ ํ ๋ฆฌ์์ ์์ , ํ ํ๋ฆฟ ๋ฐ ํธ๋ค๋ฌ๋ฅผ ๋ก๋ํ ์ ์์ต๋๋ค.
์์ ์ ์ฌ๋ฐ๋ฅด๊ฒ ์์ฑํ๋ ค๋ฉด ๋ค์ ์ฌํญ์ด ํ์ํฉ๋๋ค.
- ํ์ผ ์ด๋ฆ - ID/์คํฌ๋ฆฝํธ ์ด๋ฆ์ผ๋ก ํ์ฅ๋ฉ๋๋ค.
- ์ ํ โ ์คํธ๋ฆผ/๋ฐฐ์น
- dbrp โ ์คํฌ๋ฆฝํธ๊ฐ ์๋ํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค + ์ ์ฑ ์ ์ง์ ํ๊ธฐ ์ํ ํค์๋(dbrp "supplier"."autogen")
์ผ๋ถ ๋ฐฐ์น ์์ ์ dbrp๊ฐ ํฌํจ๋ ์ค์ด ์์ผ๋ฉด ์ ์ฒด ์๋น์ค๊ฐ ์์์ ๊ฑฐ๋ถํ๊ณ ๋ก๊ทธ์ ์์งํ๊ฒ ๊ธฐ๋กํ์ง ์์ต๋๋ค.
๋ฐ๋ฉด์ ํฌ๋ก๋ ธ๊ทธ๋ํผ์์๋ ์ด๋ฐ ์ ์ด ์กด์ฌํด์๋ ์ ๋ฉ๋๋ค. ์ธํฐํ์ด์ค๋ฅผ ํตํด ํ์ฉ๋์ง ์์ผ๋ฉฐ ์ค๋ฅ๋ฅผ ๋ฐํํฉ๋๋ค.
์ปจํ ์ด๋ ๋น๋ ํดํน: Dockerfile์ //.+dbrp๊ฐ ํฌํจ๋ ์ค์ด ์๋ ๊ฒฝ์ฐ -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
