目標:アラート状態の 5 分後に通知を受け取り、その後は 30 分ごとに通知を受け取るようにします。
私は.count()と時間関数をいじりましたが、それはどこにも行きませんでした。その混乱を計算する必要はなく、ユーザーフレンドリーで信頼できるものにする方法を見つけることができませんでした。
私が現在取り組んでいる解決策は、別々のウィンドウを持つ 2 つのストリームを持つことです。
var initialData = stream
|from()
.database(db)
.measurement(metricType)
.retentionPolicy(rPolicy)
.groupBy(group)
.where(lambda: "cpu" == 'cpu-total')
.where(lambda: "host" =~ hostFilter)
|mean(metric)
.as('initialStat')
|window()
.period(10m)
.every(5m)
.align()
var continuousData = stream
|from()
.database(db)
.measurement(metricType)
.retentionPolicy(rPolicy)
.groupBy(group)
.where(lambda: metricType == 'cpu-total')
.where(lambda: "host" =~ hostFilter)
|mean(metric)
.as('continuousStat')
|window()
.period(10m)
.every(30)
.align()
これは奇妙に思えるだけでなく、それぞれの値を計算する必要があり、個別の|alert()
ノードも必要です。最初のノードは状態の変化のみを通知しますが、2 番目のノードはこれを通知できないため、N 分ごとにアラート リマインダーを受け取ります。また、最初の|alert()
ノードがOK
通知を送信し、2 番目のノードもOK
N 分後に重複を送信するという問題があります。
これを行うためのより良い方法が必要だと感じています。最初のノードがそれを処理するのでif
、2 番目のノードでステートメントを使用|alert()
して通知を送信しないようにできるかもしれないと考えています。現時点では、これを行う方法さえまだわかっていませんが、可能であると確信しています。また、tickscript と戦いたくありません。Issue 741によると、tickscript が本格的な言語になるように設計されていないことはわかっています。OK
|window
完全なティックスクリプトは以下にあります
// CONFIGURATION PARAMETERS
// Alerting
var emailAddress = '$EMAIL'
var pagerdutyKey = '$PD'
var slackChannel = '$SLACK'
// Static Thresholds in percent cpu steal used
var warn = 85
var crit = 95
// Dynamic thresholds in number of std deviations
var warnSig = 2.5
var critSig = 3.5
// Print INFO level (every result will be an alert)
// AlertNode.StateChangesOnly will also need to be disabled
// NOTE:
// INFO level alerts will be disregarded by the pagerduty handler, this is not configurable.
var debug = FALSE
// Datastream
// Define the data that will be acted upon
var db = 'telegraf'
var group = 'host'
var metricType = 'cpu'
var metric = 'time_steal'
var rPolicy = 'default'
// Regex used to filter on a subset of hosts
var hostFilter = /.+/
// Window
var dataPeriod = 10m
var initialFrequency = 5m
var continuousFrequency = 30m
// DATAFRAME
var initialData = stream
|from()
.database(db)
.measurement(metricType)
.retentionPolicy(rPolicy)
.groupBy(group)
.where(lambda: metricType == 'cpu-total')
.where(lambda: "host" =~ hostFilter)
|mean(metric)
.as('initialStat')
|window()
.period(dataPeriod)
.every(initialFrequency)
.align()
var continuousData = stream
|from()
.database(db)
.measurement(metricType)
.retentionPolicy(rPolicy)
.groupBy(group)
.where(lambda: metricType == 'cpu-total')
.where(lambda: "host" =~ hostFilter)
|mean(metric)
.as('continuousStat')
|window()
.period(dataPeriod)
.every(continuousFrequency)
.align()
// Calculations
var initialCalculation = initialData
|eval(lambda: sigma("initialStat"))
.as('intialSigma')
.keep()
var continuousCalculation = continuousData
|eval(lambda: sigma("continuousStat"))
.as('continuousSigma')
.keep()
// ALERT CONDITIONS
var initialCondition = initialCalculation
|alert()
.id('{{ index .Tags "host" }}')
.message('{{ .ID }} is {{ .Level }}: CPU STEAL USAGE {{ index .Fields "initialStat" }}% SHORT')
.details('this is an alert')
.stateChangesOnly()
.info(lambda: debug)
.warn(lambda: "stat" < warn OR
"sigma" > warnSig)
.crit(lambda: "stat" < crit OR
"sigma" > critSig)
var continuousCondition = continuousCalculation
|alert()
.id('{{ index .Tags "host" }}')
.message('{{ .ID }} is {{ .Level }}: CPU STEAL USAGE {{ index .Fields "continuousStat" }}% LONG')
.details('this is an alert')
.info(lambda: debug)
.warn(lambda: "stat" < warn OR
"sigma" > warnSig)
.crit(lambda: "stat" < crit OR
"sigma" > critSig)
// ACTIONS
continuousCondition
// .log('/tmp/alerts/cpu_steal_usage_alerts')
// .slack()
// .channel(slackChannel)
.email(emailAddress)
.pagerDuty()
.serviceKey(pagerdutyKey)
initialCondition
// .log('/tmp/alerts/cpu_steal_usage_alerts')
// .slack()
// .channel(slackChannel)
.email(emailAddress)
.pagerDuty()
.serviceKey(pagerdutyKey)