#!/usr/bin/ruby
OUTDIR = "/var/www/html/rrd"
RRD = "#{OUTDIR}/wis.rrd"
THR_FILE = "#{OUTDIR}/wis-thr.txt"
START = "-604800" # 7日
END_T = "now"
UPPER_LIMIT = 500.0
MARGIN = 1.1
# ----------------------------
# 閾値読み込み
# ----------------------------
t_wnm, t_top, t_brw = File.read(THR_FILE).split.map(&:to_f)
# ----------------------------
# RRD fetch
# ----------------------------
raw = `rrdtool fetch #{RRD} AVERAGE --start #{START} --end #{END_T}`
data = []
raw.each_line do |line|
next unless line =~ /^\d+:/
ts, wnm, top, brw = line.split
next if wnm == "nan"
data << [ts.to_i, wnm.to_f, top.to_f, brw.to_f]
end
# ----------------------------
# 単発スパイク検出
# ----------------------------
def detect_spikes(series, threshold)
spikes = []
(1...(series.size - 1)).each do |i|
prev = series[i - 1]
curr = series[i]
nxt = series[i + 1]
if curr > threshold && prev <= threshold && nxt <= threshold
spikes << curr
end
end
spikes
end
wnm_series = data.map { |r| r[1] }
top_series = data.map { |r| r[2] }
brw_series = data.map { |r| r[3] }
wnm_spikes = detect_spikes(wnm_series, t_wnm)
top_spikes = detect_spikes(top_series, t_top)
brw_spikes = detect_spikes(brw_series, t_brw)
# ----------------------------
# 新しい閾値計算
# ----------------------------
def calc_new_threshold(spikes, current)
return current if spikes.empty?
max = spikes.max
new_val = max * MARGIN
# 上限適用
new_val = UPPER_LIMIT if new_val > UPPER_LIMIT
new_val
end
new_wnm = calc_new_threshold(wnm_spikes, t_wnm)
new_top = calc_new_threshold(top_spikes, t_top)
new_brw = calc_new_threshold(brw_spikes, t_brw)
fmsg=''
# ----------------------------
# 書き込み
# ----------------------------
begin
File.write(
THR_FILE,
format("%.1f %.1f %.1f\n", new_wnm, new_top, new_brw)
)
rescue Errno::EACCES => e
fmsg=e.to_s
end
# ----------------------------
# ログ出力
# ----------------------------
open("|/usr/sbin/sendmail -t","wt"){|mail|
mail.puts "Subject: [Adjusted]WIS Monitor\r"
mail.puts "To: news\r"
mail.puts "\r"
mail.puts "---- Threshold Update ----"
mail.puts "WNM: #{t_wnm} -> #{new_wnm} (spikes=#{wnm_spikes.size})"
mail.puts "TOP: #{t_top} -> #{new_top} (spikes=#{top_spikes.size})"
mail.puts "BRW: #{t_brw} -> #{new_brw} (spikes=#{brw_spikes.size})"
mail.puts "Upper limit applied: #{UPPER_LIMIT}"
unless fmsg.empty?
mail.puts ""
mail.puts fmsg
end
}