Allow the notifier to be a regular object (non-class)
[god.git] / lib / god / behaviors / notify_when_flapping.rb
blob8b5162da59a212686b04feab1364acaa6db5c2d1
1 module God
2   module Behaviors
3     
4     class NotifyWhenFlapping < Behavior
5       attr_accessor :failures # number of failures 
6       attr_accessor :seconds  # number of seconds
7       attr_accessor :notifier # class to notify with
8       
9       def initialize
10         super
11         @startup_times = []
12       end
13       
14       def valid?
15         valid = true
16         valid &= complain("You must specify the 'failures' attribute for :notify_when_flapping") unless self.failures
17         valid &= complain("You must specify the 'seconds' attribute for :notify_when_flapping") unless self.seconds
18         valid &= complain("You must specify the 'notifier' attribute for :notify_when_flapping") unless self.notifier
19                 
20         # Must take one arg or variable args
21         unless self.notifier.respond_to?(:notify) and [1,-1].include?(self.notifier.method(:notify).arity)
22           valid &= complain("The 'notifier' must have a method 'notify' which takes 1 or variable args")
23         end
24         
25         valid
26       end
27   
28       def before_start
29         now = Time.now.to_i
30         @startup_times << now
31         check_for_flapping(now)
32       end
33       
34       def before_restart
35         now = Time.now.to_i
36         @startup_times << now
37         check_for_flapping(now)
38       end
39       
40       private
41         
42         def check_for_flapping(now)
43           @startup_times = @startup_times.select {|time| time >= now - self.seconds }
44           if @startup_times.length >= self.failures
45             self.notifier.notify("#{self.watch.name} has called start/restart #{@startup_times.length} times in #{self.seconds} seconds")
46           end
47         end
48     end
49   
50   end
51 end