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