module Mutx class Alert module Script def ok! puts "Result: OK" exit STATUS[:ok] end def skip! puts "Result: SKIP" exit STATUS[:skip] end def unknown! puts "Result: UNKNOWN" exit STATUS[:unknown] end def warning! puts "Result: WARNING" exit STATUS[:warning] end def critical! puts "Result: CRITICAL" exit STATUS[:critical] end end ALERT_FOLDER = File.join("#{Dir.pwd}", 'alerts') STATUS = { ok: 0, unknown: 1, skip: 2, warning: 3, critical: 4 } def self.all alerts = Dir.entries(ALERT_FOLDER).select { |file| file.match(/_alert.rb$/) }.map {|file| self.new(file) } end def self.find(args={}) if args.is_a? Hash filename = "#{args[:name]}_alert.rb" if File.exists?(File.join(ALERT_FOLDER, filename)) return self.new(filename) else return nil end else return nil end end attr_reader :filename, :attributes, :job, :notification def initialize(filename) @filename = filename extract_info @enqueue = true @job = Sidekiq::Cron::Job.find(name) || ((@enqueue = false) || create_job ) end def name filename.gsub('_alert.rb', '') end def email attributes['email'] end def telegram attributes['telegram'] end def slack attributes['slack'] end def cron attributes['cron'] end def last_enqueue @job.last_enqueue_time end def enqueue? @enqueue end def on! if @job.valid? @job.save @enqueue = true end return self.enqueue? end def off! @job.destroy @enqueue = false end def status STATUS.invert[self.result.to_i] || :unknown end def update_status(a_new_status, info: nil) last_result = self.result return if ((last_result.to_s == a_new_status.to_s) or (a_new_status.to_i == STATUS[:skip])) self.result = a_new_status notify(info) if last_result || a_new_status.to_i == STATUS[:unknown] end def result Sidekiq.redis do |redis| redis.get("alerts:#{name}") end end def result=(value) Sidekiq.redis do |redis| redis.set("alerts:#{name}", value.to_s) end end def clear Sidekiq.redis do |redis| redis.del("alerts:#{name}") end end private def extract_info content = File.read(File.join(ALERT_FOLDER, filename)) lines = content.split("\n").select {|line| line.match(/^\s*\#\s\w[\w_]+\:.+/) && !line.match(/TODO/)} attributes = lines.map{ |line| line.gsub(/^\s*\#/,'').split(':',2).map(&:strip) } @attributes = Hash[attributes] @notification = @attributes.select do |k,v| [:email, :slack, :telegram].include?(k.to_sym) end end def create_job Sidekiq::Cron::Job.new(name: name, cron: attributes['cron'], class: 'Mutx::Workers::AlertsWorker', args: { name: name, file: filename, path: File.join(ALERT_FOLDER, filename), email: attributes['email'] }) end def notify(info) notify_telegram(self.telegram, info) if self.telegram notify_email(self.email, info) if self.email end def notify_telegram(group_id, info) return unless group_id Notification.send_telegram(group_id, message: "Alert #{name} is #{status.upcase}") Notification.send_telegram(group_id, message: info) end def notify_email(mail_to, info) return unless mail_to Notification.send_email(mail_to, subject: "Alert #{name} is #{status.upcase}", body: info) end end end