prevent carry-over conditions
[god.git] / lib / god / conditions / cpu_usage.rb
blob3057502930d317fa14e55a788f60cf94b333433e
1 module God
2   module Conditions
3     
4     # Condition Symbol :cpu_usage
5     # Type: Poll
6     # 
7     # Trigger when the percent of CPU use of a process is above a specified limit.
8     # On multi-core systems, this number could conceivably be above 100.
9     #
10     # Paramaters
11     #   Required
12     #     +pid_file+ is the pid file of the process in question. Automatically
13     #                populated for Watches.
14     #     +above+ is the percent CPU above which to trigger the condition. You 
15     #             may use #percent to clarify this amount (see examples).
16     #
17     # Examples
18     #
19     # Trigger if the process is using more than 25 percent of the cpu (from a Watch):
20     #
21     #   on.condition(:cpu_usage) do |c|
22     #     c.above = 25.percent
23     #   end
24     #
25     # Non-Watch Tasks must specify a PID file:
26     #
27     #   on.condition(:cpu_usage) do |c|
28     #     c.above = 25.percent
29     #     c.pid_file = "/var/run/mongrel.3000.pid"
30     #   end
31     class CpuUsage < PollCondition
32       attr_accessor :above, :times, :pid_file
33     
34       def initialize
35         super
36         self.above = nil
37         self.times = [1, 1]
38       end
39       
40       def prepare
41         if self.times.kind_of?(Integer)
42           self.times = [self.times, self.times]
43         end
44         
45         @timeline = Timeline.new(self.times[1])
46       end
47       
48       def reset
49         @timeline.clear
50       end
51       
52       def pid
53         self.watch.pid || File.read(self.pid_file).strip.to_i
54       end
55       
56       def valid?
57         valid = true
58         valid &= complain("Attribute 'pid_file' must be specified", self) if self.watch.pid_file.nil? && self.pid_file.nil?
59         valid &= complain("Attribute 'above' must be specified", self) if self.above.nil?
60         valid
61       end
62       
63       def test
64         pid = self.watch.pid
65         process = System::Process.new(pid)
66         @timeline.push(process.percent_cpu)
67         
68         history = "[" + @timeline.map { |x| "#{x > self.above ? '*' : ''}#{x}%%" }.join(", ") + "]"
69         
70         if @timeline.select { |x| x > self.above }.size >= self.times.first
71           self.info = "cpu out of bounds #{history}"
72           return true
73         else
74           self.info = "cpu within bounds #{history}"
75           return false
76         end
77       end
78     end
79     
80   end
81 end