god binary status, log, terminate, logging system improvements
[god.git] / lib / god / hub.rb
blob278d8dcf8f5b12e344ffe24c65233cf180317402
1 module God
2   
3   class Hub
4     class << self
5       # directory to hold conditions and their corresponding metric
6       #   key: condition
7       #   val: metric
8       attr_accessor :directory
9     end
10     
11     self.directory = {}
12     
13     def self.attach(condition, metric)
14       # add the condition to the directory
15       self.directory[condition] = metric
16       
17       # schedule poll condition
18       # register event condition
19       if condition.kind_of?(PollCondition)
20         Timer.get.schedule(condition, 0)
21       else
22         condition.register
23       end
24     end
25     
26     def self.detach(condition)
27       # remove the condition from the directory
28       self.directory.delete(condition)
29       
30       # unschedule any pending polls
31       Timer.get.unschedule(condition)
32       
33       # deregister event condition
34       if condition.kind_of?(EventCondition)
35         condition.deregister
36       end
37     end
38     
39     def self.trigger(condition)
40       if condition.kind_of?(PollCondition)
41         self.handle_poll(condition)
42       elsif condition.kind_of?(EventCondition)
43         self.handle_event(condition)
44       end
45     end
46     
47     def self.handle_poll(condition)
48       Thread.new do
49         begin
50           metric = self.directory[condition]
51           
52           # it's possible that the timer will trigger an event before it can be cleared
53           # by an exiting metric, in which case it should be ignored
54           exit if metric.nil?
55           
56           watch = metric.watch
57         
58           watch.mutex.synchronize do
59             # run the test
60             result = condition.test
61           
62             # log
63             msg = watch.name + ' ' + condition.class.name + " [#{result}] " + metric.destination.inspect
64             Syslog.debug(msg)
65             LOG.log(watch, :info, msg)
66           
67             # after-condition
68             condition.after
69           
70             # get the destination
71             dest = 
72             if result && condition.transition
73               # condition override
74               condition.transition
75             else
76               # regular
77               metric.destination[result]
78             end
79             
80             # transition or reschedule
81             if dest
82               # transition
83               watch.move(dest)
84             else
85               # reschedule
86               Timer.get.schedule(condition)
87             end
88           end
89         rescue => e
90           message = format("Unhandled exception (%s): %s\n%s",
91                            e.class, e.message, e.backtrace.join("\n"))
92           Syslog.crit message
93           abort message
94         end
95       end
96     end
97     
98     def self.handle_event(condition)
99       Thread.new do
100         metric = self.directory[condition]
101         watch = metric.watch
102         
103         watch.mutex.synchronize do
104           msg = watch.name + ' ' + condition.class.name + " [true] " + metric.destination.inspect
105           Syslog.debug(msg)
106           LOG.log(watch, :info, msg)
107           
108           dest = metric.destination[true]
109           watch.move(dest)
110         end
111       end
112     end
113   end
114