require_relative 'logger' module Remon class Check def self.name @name || "undefined" end def self.name=(name) @name = name end def self.opts(h) @opts = h end def self.get_opts @opts ||= {} end WARNING = "warning".freeze CRITICAL = "critical".freeze OK = "ok".freeze attr_reader :mutex, :opts include Logger def initialize(*args, **kwargs, &block) @tags = kwargs[:tags] || [] @ttl = kwargs[:ttl] || 10 @host = kwargs[:host] || Remon.host opts = kwargs[:opts] || {} verfiy_opts(opts) default_opts = self.class.get_opts @opts = default_opts.merge opts @mutex = Mutex.new return if not respond_to? :init # propagate only those kwargs which are defined in "init" method definition filtered_kwargs = filtered_kwargs(kwargs) #workaround a bug in ruby for methods that take 0 args if filtered_kwargs.empty? init(*args, &block) if respond_to? :init else init(*args, **filtered_kwargs, &block) if respond_to? :init end end def run raise NotImplementedError.new "run method not implemented" end def run_mutex synchronize { run } end def check_name self.class.name end def to_s "" end private def event(**kwargs) kwargs[:time] = Time.now.to_i kwargs[:tags] = @tags kwargs[:ttl] = @ttl kwargs[:host] = @host if @host kwargs end def warning_event(service) event({ service: service, description: "failing to execute check", state: "warning", metric: 0.9 }) end def critical_event(service) event({ service: service, description: "failing to execute check", state: "critical", metric: 1 }) end def state(metric, warning:, critical:) if metric < warning OK elsif metric >= warning && metric < critical WARNING else CRITICAL end end def service_state(service = nil, metric) wkey = service ? "#{service}_warning".to_sym : :warning ckey = service ? "#{service}_critical".to_sym : :critical warning = opts.fetch wkey critical = opts.fetch ckey state(metric, warning: warning, critical: critical) end alias_method :o, :opts def filtered_kwargs(kwargs) params = method(:init).parameters init_kwargs = params.select { |i| i[0] == :key }.map { |i| i[1] } kwargs.select { |k,v| init_kwargs.include? k } end def verfiy_opts(opts) default_opts = self.class.get_opts valid_opts = default_opts.keys opts.keys.each do |k| raise Error, "invalid opt #{k}" if not valid_opts.include? k end end def synchronize locked = false locked = @mutex.try_lock if locked yield else logger.error "#{self} already running in another thread" return false end ensure @mutex.unlock if locked end end end