#!/usr/bin/env ruby require 'sqlite3' require 'syslog' DB_FILE = "metrics.db" facility= if STDERR.tty? then Syslog::LOG_USER else Syslog::LOG_NEWS end Syslog.open('iwg_watch', Syslog::LOG_PID, facility) db = SQLite3::Database.new(DB_FILE) now_ts = db.get_first_value( "select max(ts) from metrics" ) abort("metrics table empty") unless now_ts $nolog=true def sys_info msg $nolog=false Syslog.info(msg) puts msg end class Time def show self.utc.strftime('%Y-%m-%dT%H:%M:%SZ') end end thresholds = db.execute( <<~SQL SELECT t.center_id, t.metric, t.low1, t.low3, t.low24, t.high1, t.high3, s.last_zero_time, s.last_nonzero_time FROM thresholds t LEFT JOIN last_state s USING(center_id, metric); SQL ) thresholds.each do |row| center_id, metric, low1, low3, low24, high1, high3, last_zero_time, last_nonzero_time = row # # 最新24時間分取得 # data = db.execute( <<~SQL, [center_id, metric, now_ts - 24 * 3600] select ts, value from metrics where center_id = ? and metric = ? and ts >= ? order by ts SQL ) next if data.empty? values = data.map { |_, value| value.to_f } # # v1 # next if values.size < 2 prev_v1 = values[-2] curr_v1 = values[-1] # # v3 # prev_v3 = nil curr_v3 = nil if values.size >= 3 curr_v3 = values.last(3).sum end if values.size >= 4 prev_v3 = values[-4, 3].sum end # # v24 # curr_v24 = values.sum prev_v24 = values[0...-1].sum # # low1 # if low1 > 0 then if prev_v1 >= low1 && curr_v1 < low1 then msg= "ALERT low1 "\ "#{center_id}.#{metric} "\ "current=#{curr_v1} threshold=#{low1}" if curr_v1==0 then if last_zero_time then age=((now_ts-last_zero_time)/86400.0).round(1) msg += " last_zero=#{Time.at(last_zero_time).show}"\ " days_since_zero=#{age}" else msg += " last_zero=(null)" end end sys_info(msg) end if prev_v1 < low1 && curr_v1 >= low1 then msg= "RECOVER low1 "\ "#{center_id}.#{metric} "\ "current=#{curr_v1} threshold=#{low1}" if last_nonzero_time then age=((now_ts-last_nonzero_time)/86400.0).round(2) msg += " last_nonzero=#{Time.at(last_nonzero_time).show}"\ " days_since_nonzero=#{age}" else msg += " last_nonzero=(null)" end sys_info(msg) end end # # high1 # if prev_v1 <= high1 && curr_v1 > high1 msg= "ALERT high1 "\ "#{center_id}.#{metric} "\ "current=#{curr_v1} threshold=#{high1.round(2)}" if high1==0.0 then if last_nonzero_time then age=((now_ts-last_nonzero_time)/86400.0).round(1) msg += " last_nonzero=#{Time.at(last_nonzero_time).show}"\ " days_since_nonzero=#{age}" else msg += " last_nonzero=(null)" end end sys_info(msg) end # # low3 # if prev_v3 && curr_v3 if prev_v3 >= low3 && curr_v3 < low3 msg= "ALERT low3 "\ "#{center_id}.#{metric} "\ "current=#{curr_v3} threshold=#{low3}" if curr_v3==0 then if last_zero_time then age=((now_ts-last_zero_time)/86400.0).round(1) msg += " last_zero=#{Time.at(last_zero_time).show}"\ " days_since_zero=#{age}" else msg += " last_zero=(null)" end end sys_info(msg) end end # # high3 # if prev_v3 && curr_v3 if prev_v3 <= high3 && curr_v3 > high3 msg= "ALERT high3 "\ "#{center_id}.#{metric} "\ "current=#{curr_v3} threshold=#{high3.round(2)}" if high3==0.0 then if last_nonzero_time then age=((now_ts-last_nonzero_time)/86400.0).round(1) msg += " last_nonzero=#{Time.at(last_nonzero_time).show}"\ " days_since_nonzero=#{age}" else msg += " last_nonzero=(null)" end end sys_info(msg) end end # # low24 # if low24 > 0 if prev_v24 >= low24 && curr_v24 < low24 msg= "ALERT low24 "\ "#{center_id}.#{metric} "\ "current=#{curr_v24} threshold=#{low24}" if curr_v24==0 then if last_zero_time then age=((now_ts-last_zero_time)/86400.0).round(1) msg += " last_zero=#{Time.at(last_zero_time).show}"\ " days_since_zero=#{age}" else msg += " last_zero=(null)" end end sys_info(msg) end end end Syslog.info('okay no alert this time') if $nolog db.close Syslog.close