god 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +67 -1
- data/Manifest.txt +3 -4
- data/Rakefile +1 -1
- data/bin/god +19 -1
- data/lib/god.rb +86 -49
- data/lib/god/cli/command.rb +7 -1
- data/lib/god/cli/run.rb +58 -0
- data/lib/god/condition.rb +6 -2
- data/lib/god/conditions/cpu_usage.rb +7 -6
- data/lib/god/conditions/http_response_code.rb +5 -1
- data/lib/god/conditions/memory_usage.rb +7 -6
- data/lib/god/conditions/process_exits.rb +15 -10
- data/lib/god/conditions/process_running.rb +17 -13
- data/lib/god/diagnostics.rb +37 -0
- data/lib/god/driver.rb +108 -0
- data/lib/god/event_handler.rb +41 -1
- data/lib/god/logger.rb +69 -19
- data/lib/god/metric.rb +2 -2
- data/lib/god/process.rb +84 -27
- data/lib/god/task.rb +286 -29
- data/lib/god/timeline.rb +20 -31
- data/lib/god/watch.rb +26 -15
- data/test/configs/child_events/child_events.god +0 -5
- data/test/configs/child_polls/simple_server.rb +1 -1
- data/test/configs/daemon_events/simple_server_stop.rb +2 -0
- data/test/configs/stress/stress.god +1 -1
- data/test/configs/test.rb +12 -28
- data/test/test_condition.rb +8 -0
- data/test/test_conditions_http_response_code.rb +5 -5
- data/test/test_conditions_process_running.rb +6 -4
- data/test/test_driver.rb +11 -0
- data/test/test_event_handler.rb +7 -0
- data/test/test_god.rb +63 -62
- data/test/test_metric.rb +0 -16
- data/test/test_process.rb +29 -1
- data/test/test_task.rb +177 -1
- data/test/test_timeline.rb +2 -1
- data/test/test_watch.rb +24 -6
- metadata +6 -8
- data/lib/god/hub.rb +0 -222
- data/lib/god/timer.rb +0 -87
- data/test/test_hub.rb +0 -240
- data/test/test_timer.rb +0 -69
data/test/test_metric.rb
CHANGED
@@ -69,20 +69,4 @@ class TestMetric < Test::Unit::TestCase
|
|
69
69
|
@metric.condition(:invalid) { }
|
70
70
|
end
|
71
71
|
end
|
72
|
-
|
73
|
-
# enable
|
74
|
-
|
75
|
-
def test_enable_should_attach_conditions
|
76
|
-
@metric.condition(:fake_poll_condition)
|
77
|
-
Hub.expects(:attach).with(@metric.conditions.first, @metric)
|
78
|
-
@metric.enable
|
79
|
-
end
|
80
|
-
|
81
|
-
# disable
|
82
|
-
|
83
|
-
def test_disable_should_detach_conditions
|
84
|
-
@metric.condition(:fake_poll_condition)
|
85
|
-
Hub.expects(:detach).with(@metric.conditions.first)
|
86
|
-
@metric.disable
|
87
|
-
end
|
88
72
|
end
|
data/test/test_process.rb
CHANGED
@@ -144,6 +144,34 @@ class TestProcessDaemon < Test::Unit::TestCase
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
|
+
# pid
|
148
|
+
|
149
|
+
def test_pid_should_return_integer_for_valid_pid_files
|
150
|
+
File.stubs(:read).returns("123")
|
151
|
+
assert_equal 123, @p.pid
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_pid_should_return_nil_for_missing_files
|
155
|
+
@p.pid_file = ''
|
156
|
+
assert_equal nil, @p.pid
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_pid_should_return_nil_for_invalid_pid_files
|
160
|
+
File.stubs(:read).returns("four score and seven years ago")
|
161
|
+
assert_equal nil, @p.pid
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_pid_should_retain_last_pid_value_if_pid_file_is_removed
|
165
|
+
File.stubs(:read).returns("123")
|
166
|
+
assert_equal 123, @p.pid
|
167
|
+
|
168
|
+
File.stubs(:read).returns("")
|
169
|
+
assert_equal 123, @p.pid
|
170
|
+
|
171
|
+
File.stubs(:read).returns("246")
|
172
|
+
assert_equal 246, @p.pid
|
173
|
+
end
|
174
|
+
|
147
175
|
# defaul_pid_file
|
148
176
|
|
149
177
|
def test_default_pid_file
|
@@ -156,7 +184,7 @@ class TestProcessDaemon < Test::Unit::TestCase
|
|
156
184
|
def test_call_action_with_string_should_call_system
|
157
185
|
@p.start = "do something"
|
158
186
|
@p.expects(:fork)
|
159
|
-
Process.expects(:
|
187
|
+
Process.expects(:waitpid2).returns([123, 0])
|
160
188
|
@p.call_action(:start)
|
161
189
|
end
|
162
190
|
|
data/test/test_task.rb
CHANGED
@@ -67,20 +67,196 @@ class TestTask < Test::Unit::TestCase
|
|
67
67
|
|
68
68
|
def test_action_should_send_string_commands_to_system
|
69
69
|
@task.foo = 'foo'
|
70
|
+
Thread.current.stubs(:==).returns(true)
|
70
71
|
@task.expects(:system).with('foo')
|
71
72
|
no_stdout { @task.action(:foo, nil) }
|
72
73
|
end
|
73
74
|
|
74
|
-
def
|
75
|
+
def test_action_should_call_lambda_commands
|
75
76
|
@task.foo = lambda { }
|
77
|
+
Thread.current.stubs(:==).returns(true)
|
76
78
|
@task.foo.expects(:call)
|
77
79
|
no_stdout { @task.action(:foo, nil) }
|
78
80
|
end
|
79
81
|
|
80
82
|
def test_action_should_raise_not_implemented_on_non_string_or_lambda_action
|
83
|
+
Thread.current.stubs(:==).returns(true)
|
81
84
|
assert_raise NotImplementedError do
|
82
85
|
@task.foo = 7
|
83
86
|
@task.action(:foo, nil)
|
84
87
|
end
|
85
88
|
end
|
89
|
+
|
90
|
+
def test_action_from_outside_driver_should_send_message_to_driver
|
91
|
+
@task.foo = 'foo'
|
92
|
+
@task.driver.expects(:message).with(:action, [:foo, nil])
|
93
|
+
@task.action(:foo, nil)
|
94
|
+
end
|
95
|
+
|
96
|
+
# attach
|
97
|
+
|
98
|
+
def test_attach_should_schedule_for_poll_condition
|
99
|
+
c = Conditions::FakePollCondition.new
|
100
|
+
@task.driver.expects(:schedule).with(c, 0)
|
101
|
+
@task.attach(c)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_attach_should_regsiter_for_event_condition
|
105
|
+
c = Conditions::FakeEventCondition.new
|
106
|
+
c.expects(:register)
|
107
|
+
@task.attach(c)
|
108
|
+
end
|
109
|
+
|
110
|
+
# detach
|
111
|
+
|
112
|
+
def test_detach_should_reset_poll_condition
|
113
|
+
c = Conditions::FakePollCondition.new
|
114
|
+
c.expects(:reset)
|
115
|
+
c.expects(:deregister).never
|
116
|
+
@task.detach(c)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_detach_should_deregister_event_conditions
|
120
|
+
c = Conditions::FakeEventCondition.new
|
121
|
+
c.expects(:deregister).once
|
122
|
+
@task.detach(c)
|
123
|
+
end
|
124
|
+
|
125
|
+
# trigger
|
126
|
+
|
127
|
+
def test_trigger_should_send_message_to_driver
|
128
|
+
c = Conditions::FakePollCondition.new
|
129
|
+
@task.driver.expects(:message).with(:handle_event, [c])
|
130
|
+
@task.trigger(c)
|
131
|
+
end
|
132
|
+
|
133
|
+
# handle_poll
|
134
|
+
|
135
|
+
def test_handle_poll_no_change_should_reschedule
|
136
|
+
c = Conditions::FakePollCondition.new
|
137
|
+
c.watch = @task
|
138
|
+
c.interval = 10
|
139
|
+
|
140
|
+
m = Metric.new(@task, {true => :up})
|
141
|
+
@task.directory[c] = m
|
142
|
+
|
143
|
+
c.expects(:test).returns(false)
|
144
|
+
@task.driver.expects(:schedule)
|
145
|
+
|
146
|
+
no_stdout do
|
147
|
+
@task.handle_poll(c)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_handle_poll_change_should_move
|
152
|
+
c = Conditions::FakePollCondition.new
|
153
|
+
c.watch = @task
|
154
|
+
c.interval = 10
|
155
|
+
|
156
|
+
m = Metric.new(@task, {true => :up})
|
157
|
+
@task.directory[c] = m
|
158
|
+
|
159
|
+
c.expects(:test).returns(true)
|
160
|
+
@task.expects(:move).with(:up)
|
161
|
+
|
162
|
+
no_stdout do
|
163
|
+
@task.handle_poll(c)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_handle_poll_should_use_overridden_transition
|
168
|
+
c = Conditions::Tries.new
|
169
|
+
c.watch = @task
|
170
|
+
c.times = 1
|
171
|
+
c.transition = :start
|
172
|
+
c.prepare
|
173
|
+
|
174
|
+
m = Metric.new(@task, {true => :up})
|
175
|
+
@task.directory[c] = m
|
176
|
+
|
177
|
+
@task.expects(:move).with(:start)
|
178
|
+
|
179
|
+
no_stdout do
|
180
|
+
@task.handle_poll(c)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_handle_poll_should_notify_if_triggering
|
185
|
+
c = Conditions::FakePollCondition.new
|
186
|
+
c.watch = @task
|
187
|
+
c.interval = 10
|
188
|
+
c.notify = 'tom'
|
189
|
+
|
190
|
+
m = Metric.new(@task, {true => :up})
|
191
|
+
@task.directory[c] = m
|
192
|
+
|
193
|
+
c.expects(:test).returns(true)
|
194
|
+
@task.expects(:notify)
|
195
|
+
|
196
|
+
no_stdout do
|
197
|
+
@task.handle_poll(c)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_handle_poll_should_not_notify_if_not_triggering
|
202
|
+
c = Conditions::FakePollCondition.new
|
203
|
+
c.watch = @task
|
204
|
+
c.interval = 10
|
205
|
+
c.notify = 'tom'
|
206
|
+
|
207
|
+
m = Metric.new(@task, {true => :up})
|
208
|
+
@task.directory[c] = m
|
209
|
+
|
210
|
+
c.expects(:test).returns(false)
|
211
|
+
@task.expects(:notify).never
|
212
|
+
|
213
|
+
no_stdout do
|
214
|
+
@task.handle_poll(c)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# handle_event
|
219
|
+
|
220
|
+
def test_handle_event_should_move
|
221
|
+
c = Conditions::FakeEventCondition.new
|
222
|
+
c.watch = @task
|
223
|
+
|
224
|
+
m = Metric.new(@task, {true => :up})
|
225
|
+
@task.directory[c] = m
|
226
|
+
|
227
|
+
@task.expects(:move).with(:up)
|
228
|
+
|
229
|
+
no_stdout do
|
230
|
+
@task.handle_event(c)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_handle_event_should_notify_if_triggering
|
235
|
+
c = Conditions::FakeEventCondition.new
|
236
|
+
c.watch = @task
|
237
|
+
c.notify = 'tom'
|
238
|
+
|
239
|
+
m = Metric.new(@task, {true => :up})
|
240
|
+
@task.directory[c] = m
|
241
|
+
|
242
|
+
@task.expects(:notify)
|
243
|
+
|
244
|
+
no_stdout do
|
245
|
+
@task.handle_event(c)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_handle_event_should_not_notify_if_no_notify_set
|
250
|
+
c = Conditions::FakeEventCondition.new
|
251
|
+
c.watch = @task
|
252
|
+
|
253
|
+
m = Metric.new(@task, {true => :up})
|
254
|
+
@task.directory[c] = m
|
255
|
+
|
256
|
+
@task.expects(:notify).never
|
257
|
+
|
258
|
+
no_stdout do
|
259
|
+
@task.handle_event(c)
|
260
|
+
end
|
261
|
+
end
|
86
262
|
end
|
data/test/test_timeline.rb
CHANGED
data/test/test_watch.rb
CHANGED
@@ -37,12 +37,6 @@ class TestWatch < Test::Unit::TestCase
|
|
37
37
|
assert_equal :unmonitored, @watch.state
|
38
38
|
end
|
39
39
|
|
40
|
-
# mutex
|
41
|
-
|
42
|
-
def test_mutex_should_return_the_same_mutex_each_time
|
43
|
-
assert_equal @watch.mutex, @watch.mutex
|
44
|
-
end
|
45
|
-
|
46
40
|
# valid?
|
47
41
|
|
48
42
|
def test_valid?
|
@@ -132,6 +126,9 @@ class TestWatch < Test::Unit::TestCase
|
|
132
126
|
# move
|
133
127
|
|
134
128
|
def test_move_should_not_clean_up_if_from_state_is_nil
|
129
|
+
Thread.current.stubs(:==).returns(true)
|
130
|
+
@watch.driver.expects(:message).never
|
131
|
+
|
135
132
|
metric = nil
|
136
133
|
|
137
134
|
@watch.instance_eval do
|
@@ -150,6 +147,9 @@ class TestWatch < Test::Unit::TestCase
|
|
150
147
|
end
|
151
148
|
|
152
149
|
def test_move_should_clean_up_from_state_if_not_nil
|
150
|
+
Thread.current.stubs(:==).returns(true)
|
151
|
+
@watch.driver.expects(:message).never
|
152
|
+
|
153
153
|
metric = nil
|
154
154
|
|
155
155
|
@watch.instance_eval do
|
@@ -170,12 +170,18 @@ class TestWatch < Test::Unit::TestCase
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def test_move_should_call_action
|
173
|
+
Thread.current.stubs(:==).returns(true)
|
174
|
+
@watch.driver.expects(:message).never
|
175
|
+
|
173
176
|
@watch.expects(:action).with(:start)
|
174
177
|
|
175
178
|
no_stdout { @watch.move(:start) }
|
176
179
|
end
|
177
180
|
|
178
181
|
def test_move_should_move_to_up_state_if_no_start_or_restart_metric
|
182
|
+
Thread.current.stubs(:==).returns(true)
|
183
|
+
@watch.driver.expects(:message).never
|
184
|
+
|
179
185
|
[:start, :restart].each do |state|
|
180
186
|
@watch.expects(:action)
|
181
187
|
no_stdout { @watch.move(state) }
|
@@ -184,6 +190,9 @@ class TestWatch < Test::Unit::TestCase
|
|
184
190
|
end
|
185
191
|
|
186
192
|
def test_move_should_enable_destination_metric
|
193
|
+
Thread.current.stubs(:==).returns(true)
|
194
|
+
@watch.driver.expects(:message).never
|
195
|
+
|
187
196
|
metric = nil
|
188
197
|
|
189
198
|
@watch.instance_eval do
|
@@ -204,6 +213,9 @@ class TestWatch < Test::Unit::TestCase
|
|
204
213
|
# action
|
205
214
|
|
206
215
|
def test_action_should_pass_start_and_stop_actions_to_call_action
|
216
|
+
Thread.current.stubs(:==).returns(true)
|
217
|
+
@watch.driver.expects(:message).never
|
218
|
+
|
207
219
|
c = Conditions::FakePollCondition.new
|
208
220
|
[:start, :stop].each do |cmd|
|
209
221
|
@watch.expects(:call_action).with(c, cmd)
|
@@ -212,6 +224,9 @@ class TestWatch < Test::Unit::TestCase
|
|
212
224
|
end
|
213
225
|
|
214
226
|
def test_action_should_do_stop_then_start_if_no_restart_command
|
227
|
+
Thread.current.stubs(:==).returns(true)
|
228
|
+
@watch.driver.expects(:message).never
|
229
|
+
|
215
230
|
c = Conditions::FakePollCondition.new
|
216
231
|
@watch.expects(:call_action).with(c, :stop)
|
217
232
|
@watch.expects(:call_action).with(c, :start)
|
@@ -219,6 +234,9 @@ class TestWatch < Test::Unit::TestCase
|
|
219
234
|
end
|
220
235
|
|
221
236
|
def test_action_should_restart_to_call_action_if_present
|
237
|
+
Thread.current.stubs(:==).returns(true)
|
238
|
+
@watch.driver.expects(:message).never
|
239
|
+
|
222
240
|
@watch.restart = lambda { }
|
223
241
|
c = Conditions::FakePollCondition.new
|
224
242
|
@watch.expects(:call_action).with(c, :restart)
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: god
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date:
|
6
|
+
version: 0.7.0
|
7
|
+
date: 2008-02-01 00:00:00 -08:00
|
8
8
|
summary: Like monit, only awesome
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -66,12 +66,13 @@ files:
|
|
66
66
|
- lib/god/contact.rb
|
67
67
|
- lib/god/contacts/email.rb
|
68
68
|
- lib/god/dependency_graph.rb
|
69
|
+
- lib/god/diagnostics.rb
|
70
|
+
- lib/god/driver.rb
|
69
71
|
- lib/god/errors.rb
|
70
72
|
- lib/god/event_handler.rb
|
71
73
|
- lib/god/event_handlers/dummy_handler.rb
|
72
74
|
- lib/god/event_handlers/kqueue_handler.rb
|
73
75
|
- lib/god/event_handlers/netlink_handler.rb
|
74
|
-
- lib/god/hub.rb
|
75
76
|
- lib/god/logger.rb
|
76
77
|
- lib/god/metric.rb
|
77
78
|
- lib/god/process.rb
|
@@ -81,7 +82,6 @@ files:
|
|
81
82
|
- lib/god/system/process.rb
|
82
83
|
- lib/god/task.rb
|
83
84
|
- lib/god/timeline.rb
|
84
|
-
- lib/god/timer.rb
|
85
85
|
- lib/god/trigger.rb
|
86
86
|
- lib/god/watch.rb
|
87
87
|
- test/configs/child_events/child_events.god
|
@@ -116,10 +116,10 @@ files:
|
|
116
116
|
- test/test_conditions_tries.rb
|
117
117
|
- test/test_contact.rb
|
118
118
|
- test/test_dependency_graph.rb
|
119
|
+
- test/test_driver.rb
|
119
120
|
- test/test_event_handler.rb
|
120
121
|
- test/test_god.rb
|
121
122
|
- test/test_handlers_kqueue_handler.rb
|
122
|
-
- test/test_hub.rb
|
123
123
|
- test/test_logger.rb
|
124
124
|
- test/test_metric.rb
|
125
125
|
- test/test_process.rb
|
@@ -129,7 +129,6 @@ files:
|
|
129
129
|
- test/test_system_process.rb
|
130
130
|
- test/test_task.rb
|
131
131
|
- test/test_timeline.rb
|
132
|
-
- test/test_timer.rb
|
133
132
|
- test/test_trigger.rb
|
134
133
|
- test/test_watch.rb
|
135
134
|
test_files:
|
@@ -141,10 +140,10 @@ test_files:
|
|
141
140
|
- test/test_conditions_tries.rb
|
142
141
|
- test/test_contact.rb
|
143
142
|
- test/test_dependency_graph.rb
|
143
|
+
- test/test_driver.rb
|
144
144
|
- test/test_event_handler.rb
|
145
145
|
- test/test_god.rb
|
146
146
|
- test/test_handlers_kqueue_handler.rb
|
147
|
-
- test/test_hub.rb
|
148
147
|
- test/test_logger.rb
|
149
148
|
- test/test_metric.rb
|
150
149
|
- test/test_process.rb
|
@@ -154,7 +153,6 @@ test_files:
|
|
154
153
|
- test/test_system_process.rb
|
155
154
|
- test/test_task.rb
|
156
155
|
- test/test_timeline.rb
|
157
|
-
- test/test_timer.rb
|
158
156
|
- test/test_trigger.rb
|
159
157
|
- test/test_watch.rb
|
160
158
|
rdoc_options:
|
data/lib/god/hub.rb
DELETED
@@ -1,222 +0,0 @@
|
|
1
|
-
module God
|
2
|
-
|
3
|
-
class Hub
|
4
|
-
class << self
|
5
|
-
# directory to hold conditions and their corresponding metric
|
6
|
-
# {condition => metric}
|
7
|
-
attr_accessor :directory
|
8
|
-
end
|
9
|
-
|
10
|
-
self.directory = {}
|
11
|
-
|
12
|
-
def self.attach(condition, metric)
|
13
|
-
self.directory[condition] = metric
|
14
|
-
condition.reset
|
15
|
-
|
16
|
-
case condition
|
17
|
-
when PollCondition
|
18
|
-
Timer.get.schedule(condition, 0)
|
19
|
-
when EventCondition, TriggerCondition
|
20
|
-
condition.register
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.detach(condition)
|
25
|
-
self.directory.delete(condition)
|
26
|
-
|
27
|
-
case condition
|
28
|
-
when PollCondition
|
29
|
-
Timer.get.unschedule(condition)
|
30
|
-
when EventCondition, TriggerCondition
|
31
|
-
condition.deregister
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.trigger(condition)
|
36
|
-
case condition
|
37
|
-
when PollCondition
|
38
|
-
self.handle_poll(condition)
|
39
|
-
when EventCondition, TriggerCondition
|
40
|
-
self.handle_event(condition)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.handle_poll(condition)
|
45
|
-
Thread.new do
|
46
|
-
begin
|
47
|
-
metric = self.directory[condition]
|
48
|
-
|
49
|
-
# it's possible that the timer will trigger an event before it can be cleared
|
50
|
-
# by an exiting metric, in which case it should be ignored
|
51
|
-
unless metric.nil?
|
52
|
-
watch = metric.watch
|
53
|
-
|
54
|
-
watch.mutex.synchronize do
|
55
|
-
# run the test
|
56
|
-
result = condition.test
|
57
|
-
|
58
|
-
# log
|
59
|
-
messages = self.log(watch, metric, condition, result)
|
60
|
-
|
61
|
-
# notify
|
62
|
-
if condition.notify && self.trigger?(metric, result)
|
63
|
-
self.notify(condition, messages.last)
|
64
|
-
end
|
65
|
-
|
66
|
-
# after-condition
|
67
|
-
condition.after
|
68
|
-
|
69
|
-
# get the destination
|
70
|
-
dest =
|
71
|
-
if result && condition.transition
|
72
|
-
# condition override
|
73
|
-
condition.transition
|
74
|
-
else
|
75
|
-
# regular
|
76
|
-
metric.destination && metric.destination[result]
|
77
|
-
end
|
78
|
-
|
79
|
-
# transition or reschedule
|
80
|
-
if dest
|
81
|
-
# transition
|
82
|
-
begin
|
83
|
-
watch.move(dest)
|
84
|
-
rescue EventRegistrationFailedError
|
85
|
-
msg = watch.name + ' Event registration failed, moving back to previous state'
|
86
|
-
applog(watch, :info, msg)
|
87
|
-
|
88
|
-
dest = watch.state
|
89
|
-
retry
|
90
|
-
end
|
91
|
-
else
|
92
|
-
# reschedule
|
93
|
-
Timer.get.schedule(condition)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
rescue Exception => e
|
98
|
-
message = format("Unhandled exception (%s): %s\n%s",
|
99
|
-
e.class, e.message, e.backtrace.join("\n"))
|
100
|
-
applog(nil, :fatal, message)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def self.handle_event(condition)
|
106
|
-
Thread.new do
|
107
|
-
begin
|
108
|
-
metric = self.directory[condition]
|
109
|
-
|
110
|
-
unless metric.nil?
|
111
|
-
watch = metric.watch
|
112
|
-
|
113
|
-
watch.mutex.synchronize do
|
114
|
-
# log
|
115
|
-
messages = self.log(watch, metric, condition, true)
|
116
|
-
|
117
|
-
# notify
|
118
|
-
if condition.notify && self.trigger?(metric, true)
|
119
|
-
self.notify(condition, messages.last)
|
120
|
-
end
|
121
|
-
|
122
|
-
# get the destination
|
123
|
-
dest =
|
124
|
-
if condition.transition
|
125
|
-
# condition override
|
126
|
-
condition.transition
|
127
|
-
else
|
128
|
-
# regular
|
129
|
-
metric.destination && metric.destination[true]
|
130
|
-
end
|
131
|
-
|
132
|
-
if dest
|
133
|
-
watch.move(dest)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
rescue Exception => e
|
138
|
-
message = format("Unhandled exception (%s): %s\n%s",
|
139
|
-
e.class, e.message, e.backtrace.join("\n"))
|
140
|
-
applog(nil, :fatal, message)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
# helpers
|
146
|
-
|
147
|
-
def self.trigger?(metric, result)
|
148
|
-
(metric.destination && metric.destination.keys.size == 2) || result == true
|
149
|
-
end
|
150
|
-
|
151
|
-
def self.log(watch, metric, condition, result)
|
152
|
-
status =
|
153
|
-
if self.trigger?(metric, result)
|
154
|
-
"[trigger]"
|
155
|
-
else
|
156
|
-
"[ok]"
|
157
|
-
end
|
158
|
-
|
159
|
-
messages = []
|
160
|
-
|
161
|
-
# log info if available
|
162
|
-
if condition.info
|
163
|
-
Array(condition.info).each do |condition_info|
|
164
|
-
messages << "#{watch.name} #{status} #{condition_info} (#{condition.base_name})"
|
165
|
-
applog(watch, :info, messages.last)
|
166
|
-
end
|
167
|
-
else
|
168
|
-
messages << "#{watch.name} #{status} (#{condition.base_name})"
|
169
|
-
applog(watch, :info, messages.last)
|
170
|
-
end
|
171
|
-
|
172
|
-
# log
|
173
|
-
debug_message = watch.name + ' ' + condition.base_name + " [#{result}] " + self.dest_desc(metric, condition)
|
174
|
-
applog(watch, :debug, debug_message)
|
175
|
-
|
176
|
-
messages
|
177
|
-
end
|
178
|
-
|
179
|
-
def self.dest_desc(metric, condition)
|
180
|
-
if condition.transition
|
181
|
-
{true => condition.transition}.inspect
|
182
|
-
else
|
183
|
-
if metric.destination
|
184
|
-
metric.destination.inspect
|
185
|
-
else
|
186
|
-
'none'
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def self.notify(condition, message)
|
192
|
-
spec = Contact.normalize(condition.notify)
|
193
|
-
unmatched = []
|
194
|
-
|
195
|
-
# resolve contacts
|
196
|
-
resolved_contacts =
|
197
|
-
spec[:contacts].inject([]) do |acc, contact_name_or_group|
|
198
|
-
cons = Array(God.contacts[contact_name_or_group] || God.contact_groups[contact_name_or_group])
|
199
|
-
unmatched << contact_name_or_group if cons.empty?
|
200
|
-
acc += cons
|
201
|
-
acc
|
202
|
-
end
|
203
|
-
|
204
|
-
# warn about unmatched contacts
|
205
|
-
unless unmatched.empty?
|
206
|
-
msg = "#{condition.watch.name} no matching contacts for '#{unmatched.join(", ")}'"
|
207
|
-
applog(condition.watch, :warn, msg)
|
208
|
-
end
|
209
|
-
|
210
|
-
# notify each contact
|
211
|
-
resolved_contacts.each do |c|
|
212
|
-
host = `hostname`.chomp rescue 'none'
|
213
|
-
c.notify(message, Time.now, spec[:priority], spec[:category], host)
|
214
|
-
|
215
|
-
msg = "#{condition.watch.name} #{c.info ? c.info : "notification sent for contact: #{c.name}"} (#{c.base_name})"
|
216
|
-
|
217
|
-
applog(condition.watch, :info, msg % [])
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
end
|