Skip to content

Writing Custom Conditions

Gurpartap edited this page Dec 25, 2012 · 8 revisions

Writing conditions for Cognizant is easy. Cognizant provides a PollCondition class which can be subclassed to write custom conditions.

module Cognizant
  class Process
    module Conditions
      class PollCondition
        def initialize(options = {})
          @options = options
        end

        def run(pid)
          raise "Implement in subclass!"
        end

        def check(value)
          raise "Implement in subclass!"
        end

        def format_value(value)
          value
        end
      end
    end
  end
end

PollCondition accepts :times and :every options, which check for condition values for n times, each every m seconds. Cognizant caches the last n values given by #run on each call.

A return value of false from #check means that the value returned by #run is acceptable. true means that the calculated value is above or below threshold and is not acceptable, and is marked for action execution.

PollCondition also accepts either :do option or a block as an action, which is run when the condition value goes above threshold value for n times within a timeframe.

You can optionally implement a format_value method that gets the value returned from run and formats it for the log file. You can use this to change the scale from KB to MB, or add units, or whatever else makes sense for logging your condition.

When using your condition for a process, Cognizant looks for a camel case condition class. e.g. :memory_usage would become MemoryUsage.

Here are a few examples to follow:

Always True

module Cognizant
  class Process
    module Conditions
      class AlwaysTrue < PollCondition
        def run(pid)
          1
        end

        def check(value)
          true
        end
      end
    end
  end
end
# Implementation
# Restart every 6 seconds.
process.check :always_true, :every => 2.seconds, :times => 3, :do => :restart

CPU Usage

module Cognizant
  class Process
    module Conditions
      class CpuUsage < PollCondition
        def initialize(options = {})
          # Accept a custom argument for condition. e.g. threshold.
          @above = options[:above].to_f
        end

        def run(pid)
          # Check for current value for the given process pid.
          Cognizant::System.cpu_usage(pid).to_f
        end

        def check(value)
          # Evaluate the value with threshold.
          # The result of this decides condition invoking.
          value > @above
        end
      end
    end
  end
end
# Implementation
# Stop process if cpu usage is above 60 percent in 3 out of 5 times from checks run every 3 seconds.
process.check :cpu_usage, :every => 3.seconds, :above => 60, :times => [3, 5], :do => :stop