god 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/Announce.txt +6 -6
  2. data/Gemfile +2 -0
  3. data/History.txt +19 -2
  4. data/{README.txt → LICENSE} +0 -37
  5. data/README.md +31 -0
  6. data/Rakefile +80 -38
  7. data/bin/god +21 -21
  8. data/doc/god.asciidoc +1487 -0
  9. data/doc/intro.asciidoc +20 -0
  10. data/ext/god/extconf.rb +3 -3
  11. data/ext/god/kqueue_handler.c +18 -18
  12. data/ext/god/netlink_handler.c +31 -31
  13. data/god.gemspec +24 -16
  14. data/lib/god.rb +261 -204
  15. data/lib/god/behavior.rb +14 -14
  16. data/lib/god/behaviors/clean_pid_file.rb +5 -5
  17. data/lib/god/behaviors/clean_unix_socket.rb +10 -10
  18. data/lib/god/behaviors/notify_when_flapping.rb +12 -12
  19. data/lib/god/cli/command.rb +59 -46
  20. data/lib/god/cli/run.rb +33 -37
  21. data/lib/god/cli/version.rb +6 -6
  22. data/lib/god/compat19.rb +1 -4
  23. data/lib/god/condition.rb +21 -21
  24. data/lib/god/conditions/always.rb +19 -6
  25. data/lib/god/conditions/complex.rb +18 -18
  26. data/lib/god/conditions/cpu_usage.rb +14 -14
  27. data/lib/god/conditions/degrading_lambda.rb +8 -8
  28. data/lib/god/conditions/disk_usage.rb +5 -5
  29. data/lib/god/conditions/flapping.rb +23 -23
  30. data/lib/god/conditions/http_response_code.rb +35 -19
  31. data/lib/god/conditions/lambda.rb +2 -2
  32. data/lib/god/conditions/memory_usage.rb +13 -13
  33. data/lib/god/conditions/process_exits.rb +14 -20
  34. data/lib/god/conditions/process_running.rb +16 -25
  35. data/lib/god/conditions/socket_responding.rb +132 -0
  36. data/lib/god/conditions/tries.rb +10 -10
  37. data/lib/god/configurable.rb +10 -10
  38. data/lib/god/contact.rb +20 -20
  39. data/lib/god/contacts/email.rb +7 -4
  40. data/lib/god/contacts/jabber.rb +1 -1
  41. data/lib/god/driver.rb +96 -64
  42. data/lib/god/errors.rb +9 -9
  43. data/lib/god/event_handler.rb +19 -19
  44. data/lib/god/event_handlers/dummy_handler.rb +4 -4
  45. data/lib/god/event_handlers/kqueue_handler.rb +3 -3
  46. data/lib/god/event_handlers/netlink_handler.rb +2 -2
  47. data/lib/god/logger.rb +13 -13
  48. data/lib/god/metric.rb +50 -22
  49. data/lib/god/process.rb +53 -52
  50. data/lib/god/registry.rb +7 -7
  51. data/lib/god/simple_logger.rb +14 -14
  52. data/lib/god/socket.rb +11 -11
  53. data/lib/god/sugar.rb +30 -15
  54. data/lib/god/sys_logger.rb +2 -2
  55. data/lib/god/system/portable_poller.rb +8 -8
  56. data/lib/god/system/process.rb +8 -8
  57. data/lib/god/system/slash_proc_poller.rb +13 -13
  58. data/lib/god/task.rb +237 -188
  59. data/lib/god/timeline.rb +5 -5
  60. data/lib/god/trigger.rb +11 -11
  61. data/lib/god/watch.rb +205 -53
  62. data/test/configs/child_events/child_events.god +5 -5
  63. data/test/configs/child_events/simple_server.rb +1 -1
  64. data/test/configs/child_polls/child_polls.god +4 -4
  65. data/test/configs/child_polls/simple_server.rb +4 -4
  66. data/test/configs/complex/complex.god +7 -7
  67. data/test/configs/complex/simple_server.rb +1 -1
  68. data/test/configs/contact/contact.god +1 -1
  69. data/test/configs/contact/simple_server.rb +1 -1
  70. data/test/configs/daemon_events/daemon_events.god +5 -5
  71. data/test/configs/daemon_events/simple_server.rb +1 -1
  72. data/test/configs/daemon_events/simple_server_stop.rb +1 -1
  73. data/test/configs/daemon_polls/daemon_polls.god +3 -3
  74. data/test/configs/daemon_polls/simple_server.rb +1 -1
  75. data/test/configs/degrading_lambda/degrading_lambda.god +3 -3
  76. data/test/configs/keepalive/keepalive.god +9 -0
  77. data/test/configs/keepalive/keepalive.rb +12 -0
  78. data/test/configs/lifecycle/lifecycle.god +2 -2
  79. data/test/configs/matias/matias.god +6 -6
  80. data/test/configs/real.rb +7 -7
  81. data/test/configs/running_load/running_load.god +2 -2
  82. data/test/configs/stop_options/simple_server.rb +1 -1
  83. data/test/configs/stress/simple_server.rb +1 -1
  84. data/test/configs/stress/stress.god +2 -2
  85. data/test/configs/task/task.god +5 -5
  86. data/test/configs/test.rb +7 -7
  87. data/test/helper.rb +8 -8
  88. data/test/test_behavior.rb +3 -3
  89. data/test/test_campfire.rb +1 -2
  90. data/test/test_condition.rb +10 -10
  91. data/test/test_conditions_disk_usage.rb +12 -12
  92. data/test/test_conditions_http_response_code.rb +24 -24
  93. data/test/test_conditions_process_running.rb +7 -7
  94. data/test/test_conditions_socket_responding.rb +122 -0
  95. data/test/test_conditions_tries.rb +12 -12
  96. data/test/test_contact.rb +19 -19
  97. data/test/test_driver.rb +17 -3
  98. data/test/test_event_handler.rb +12 -12
  99. data/test/test_god.rb +195 -117
  100. data/test/test_handlers_kqueue_handler.rb +4 -4
  101. data/test/test_jabber.rb +1 -1
  102. data/test/test_logger.rb +17 -17
  103. data/test/test_metric.rb +16 -16
  104. data/test/test_process.rb +47 -41
  105. data/test/test_prowl.rb +1 -1
  106. data/test/test_registry.rb +2 -2
  107. data/test/test_socket.rb +3 -3
  108. data/test/test_sugar.rb +7 -7
  109. data/test/test_system_portable_poller.rb +1 -1
  110. data/test/test_system_process.rb +5 -5
  111. data/test/test_task.rb +57 -57
  112. data/test/test_timeline.rb +8 -8
  113. data/test/test_trigger.rb +16 -16
  114. data/test/test_watch.rb +69 -62
  115. metadata +182 -69
  116. data/lib/god/dependency_graph.rb +0 -41
  117. data/lib/god/diagnostics.rb +0 -37
  118. data/test/test_dependency_graph.rb +0 -62
@@ -1,261 +1,305 @@
1
1
  module God
2
-
2
+
3
3
  class Task
4
- attr_accessor :name, :interval, :group, :valid_states, :initial_state, :driver
5
-
6
- attr_writer :autostart
7
- def autostart?; @autostart; end
8
-
4
+ # Public: Gets/Sets the String name of the task.
5
+ attr_accessor :name
6
+
7
+ # Public: Gets/Sets the Numeric default interval to be used between poll
8
+ # events.
9
+ attr_accessor :interval
10
+
11
+ # Public: Gets/Sets the String group name of the task.
12
+ attr_accessor :group
13
+
14
+ # Public: Gets/Sets the Array of Symbol valid states for the state machine.
15
+ attr_accessor :valid_states
16
+
17
+ # Public: Gets/Sets the Symbol initial state of the state machine.
18
+ attr_accessor :initial_state
19
+
20
+ # Gets/Sets the Driver for this task.
21
+ attr_accessor :driver
22
+
23
+ # Public: Sets whether the task should autostart when god starts. Defaults
24
+ # to true (enabled).
25
+ attr_writer :autostart
26
+
27
+ # Returns true if autostart is enabled, false if not.
28
+ def autostart?
29
+ @autostart
30
+ end
31
+
9
32
  # api
10
33
  attr_accessor :state, :behaviors, :metrics, :directory
11
-
34
+
12
35
  def initialize
13
36
  @autostart ||= true
14
-
37
+
15
38
  # initial state is unmonitored
16
39
  self.state = :unmonitored
17
-
40
+
18
41
  # the list of behaviors
19
42
  self.behaviors = []
20
-
43
+
21
44
  # the list of conditions for each action
22
45
  self.metrics = {nil => [], :unmonitored => [], :stop => []}
23
-
46
+
24
47
  # the condition -> metric lookup
25
48
  self.directory = {}
26
-
49
+
27
50
  # driver
28
51
  self.driver = Driver.new(self)
29
52
  end
30
-
53
+
54
+ # Initialize the metrics to an empty state.
55
+ #
56
+ # Returns nothing.
31
57
  def prepare
32
58
  self.valid_states.each do |state|
33
59
  self.metrics[state] ||= []
34
60
  end
35
61
  end
36
-
62
+
63
+ # Verify that the minimum set of configuration requirements has been met.
64
+ #
65
+ # Returns true if valid, false if not.
37
66
  def valid?
38
67
  valid = true
39
-
40
- # a name must be specified
68
+
69
+ # A name must be specified.
41
70
  if self.name.nil?
42
71
  valid = false
43
- applog(self, :error, "No name was specified")
72
+ applog(self, :error, "No name String was specified.")
44
73
  end
45
-
46
- # valid_states must be specified
74
+
75
+ # Valid states must be specified.
47
76
  if self.valid_states.nil?
48
77
  valid = false
49
- applog(self, :error, "No valid_states array was specified")
78
+ applog(self, :error, "No valid_states Array or Symbols was specified.")
50
79
  end
51
-
52
- # valid_states must be specified
80
+
81
+ # An initial state must be specified.
53
82
  if self.initial_state.nil?
54
83
  valid = false
55
- applog(self, :error, "No initial_state was specified")
84
+ applog(self, :error, "No initial_state Symbol was specified.")
56
85
  end
57
-
86
+
58
87
  valid
59
88
  end
60
-
89
+
61
90
  ###########################################################################
62
91
  #
63
92
  # Advanced mode
64
93
  #
65
94
  ###########################################################################
66
-
95
+
96
+ # Convert the given input into canonical hash form which looks like:
97
+ #
98
+ # { true => :state } or { true => :state, false => :otherstate }
99
+ #
100
+ # to - The Symbol or Hash destination.
101
+ #
102
+ # Returns the canonical Hash.
67
103
  def canonical_hash_form(to)
68
104
  to.instance_of?(Symbol) ? {true => to} : to
69
105
  end
70
-
71
- # Define a transition handler which consists of a set of conditions
106
+
107
+ # Public: Define a transition handler which consists of a set of conditions
108
+ #
109
+ # start_states - The Symbol or Array of Symbols start state(s).
110
+ # end_states - The Symbol or Hash end states.
111
+ #
112
+ # Yields the Metric for this transition.
113
+ #
114
+ # Returns nothing.
72
115
  def transition(start_states, end_states)
73
- # convert end_states into canonical hash form
116
+ # Convert end_states into canonical hash form.
74
117
  canonical_end_states = canonical_hash_form(end_states)
75
-
118
+
76
119
  Array(start_states).each do |start_state|
77
- # validate start state
120
+ # Validate start state.
78
121
  unless self.valid_states.include?(start_state)
79
122
  abort "Invalid state :#{start_state}. Must be one of the symbols #{self.valid_states.map{|x| ":#{x}"}.join(', ')}"
80
123
  end
81
-
82
- # create a new metric to hold the watch, end states, and conditions
124
+
125
+ # Create a new metric to hold the task, end states, and conditions.
83
126
  m = Metric.new(self, canonical_end_states)
84
-
127
+
85
128
  if block_given?
86
- # let the config file define some conditions on the metric
129
+ # Let the config file define some conditions on the metric.
87
130
  yield(m)
88
131
  else
89
- # add an :always condition if no block
132
+ # Add an :always condition if no block was given.
90
133
  m.condition(:always) do |c|
91
134
  c.what = true
92
135
  end
93
136
  end
94
-
95
- # populate the condition -> metric directory
137
+
138
+ # Populate the condition -> metric directory.
96
139
  m.conditions.each do |c|
97
140
  self.directory[c] = m
98
141
  end
99
-
100
- # record the metric
142
+
143
+ # Record the metric.
101
144
  self.metrics[start_state] ||= []
102
145
  self.metrics[start_state] << m
103
146
  end
104
147
  end
105
-
148
+
149
+ # Public: Define a lifecycle handler. Conditions that belong to a
150
+ # lifecycle are active as long as the process is being monitored.
151
+ #
152
+ # Returns nothing.
106
153
  def lifecycle
107
- # create a new metric to hold the watch and conditions
154
+ # Create a new metric to hold the task and conditions.
108
155
  m = Metric.new(self)
109
-
110
- # let the config file define some conditions on the metric
156
+
157
+ # Let the config file define some conditions on the metric.
111
158
  yield(m)
112
-
113
- # populate the condition -> metric directory
159
+
160
+ # Populate the condition -> metric directory.
114
161
  m.conditions.each do |c|
115
162
  self.directory[c] = m
116
163
  end
117
-
118
- # record the metric
164
+
165
+ # Record the metric.
119
166
  self.metrics[nil] << m
120
167
  end
121
-
168
+
122
169
  ###########################################################################
123
170
  #
124
171
  # Lifecycle
125
172
  #
126
173
  ###########################################################################
127
-
128
- # Enable monitoring
174
+
175
+ # Enable monitoring.
129
176
  #
130
- # Returns nothing
177
+ # Returns nothing.
131
178
  def monitor
132
179
  self.move(self.initial_state)
133
180
  end
134
-
135
- # Disable monitoring
181
+
182
+ # Disable monitoring.
136
183
  #
137
- # Returns nothing
184
+ # Returns nothing.
138
185
  def unmonitor
139
186
  self.move(:unmonitored)
140
187
  end
141
-
142
- # Move to the givent state
143
- # +to_state+ is the Symbol representing the state to move to
188
+
189
+ # Move to the given state.
144
190
  #
145
- # Returns Task (self)
191
+ # to_state - The Symbol representing the state to move to.
192
+ #
193
+ # Returns this Task.
146
194
  def move(to_state)
147
195
  if !self.driver.in_driver_context?
148
- # called from outside Driver
149
-
150
- # send an async message to Driver
196
+ # Called from outside Driver. Send an async message to Driver.
151
197
  self.driver.message(:move, [to_state])
152
198
  else
153
- # called from within Driver
154
-
155
- # record original info
199
+ # Called from within Driver. Record original info.
156
200
  orig_to_state = to_state
157
201
  from_state = self.state
158
-
159
- # log
202
+
203
+ # Log.
160
204
  msg = "#{self.name} move '#{from_state}' to '#{to_state}'"
161
205
  applog(self, :info, msg)
162
-
163
- # cleanup from current state
206
+
207
+ # Cleanup from current state.
164
208
  self.driver.clear_events
165
209
  self.metrics[from_state].each { |m| m.disable }
166
210
  if to_state == :unmonitored
167
211
  self.metrics[nil].each { |m| m.disable }
168
212
  end
169
-
170
- # perform action
213
+
214
+ # Perform action.
171
215
  self.action(to_state)
172
-
173
- # enable simple mode
216
+
217
+ # Enable simple mode.
174
218
  if [:start, :restart].include?(to_state) && self.metrics[to_state].empty?
175
219
  to_state = :up
176
220
  end
177
-
178
- # move to new state
221
+
222
+ # Move to new state.
179
223
  self.metrics[to_state].each { |m| m.enable }
180
-
181
- # if no from state, enable lifecycle metric
224
+
225
+ # If no from state, enable lifecycle metric.
182
226
  if from_state == :unmonitored
183
227
  self.metrics[nil].each { |m| m.enable }
184
228
  end
185
-
186
- # set state
229
+
230
+ # Set state.
187
231
  self.state = to_state
188
-
189
- # broadcast to interested TriggerConditions
232
+
233
+ # Broadcast to interested TriggerConditions.
190
234
  Trigger.broadcast(self, :state_change, [from_state, orig_to_state])
191
-
192
- # log
235
+
236
+ # Log.
193
237
  msg = "#{self.name} moved '#{from_state}' to '#{to_state}'"
194
238
  applog(self, :info, msg)
195
239
  end
196
-
240
+
197
241
  self
198
242
  end
199
-
200
- # Notify the Driver that an EventCondition has triggered
243
+
244
+ # Notify the Driver that an EventCondition has triggered.
245
+ #
246
+ # condition - The Condition.
201
247
  #
202
- # Returns nothing
248
+ # Returns nothing.
203
249
  def trigger(condition)
204
250
  self.driver.message(:handle_event, [condition])
205
251
  end
206
-
252
+
207
253
  def signal(sig)
208
254
  # noop
209
255
  end
210
-
256
+
211
257
  ###########################################################################
212
258
  #
213
259
  # Actions
214
260
  #
215
261
  ###########################################################################
216
-
262
+
217
263
  def method_missing(sym, *args)
218
264
  unless (sym.to_s =~ /=$/)
219
265
  super
220
266
  end
221
-
267
+
222
268
  base = sym.to_s.chop.intern
223
-
269
+
224
270
  unless self.valid_states.include?(base)
225
271
  super
226
272
  end
227
-
273
+
228
274
  self.class.send(:attr_accessor, base)
229
275
  self.send(sym, *args)
230
276
  end
231
-
232
- # Perform the given action
233
- # +a+ is the action Symbol
234
- # +c+ is the Condition
277
+
278
+ # Perform the given action.
279
+ #
280
+ # a - The Symbol action.
281
+ # c - The Condition.
235
282
  #
236
- # Returns Task (self)
283
+ # Returns this Task.
237
284
  def action(a, c = nil)
238
285
  if !self.driver.in_driver_context?
239
- # called from outside Driver
240
-
241
- # send an async message to Driver
286
+ # Called from outside Driver. Send an async message to Driver.
242
287
  self.driver.message(:action, [a, c])
243
288
  else
244
- # called from within Driver
245
-
289
+ # Called from within Driver.
246
290
  if self.respond_to?(a)
247
291
  command = self.send(a)
248
-
292
+
249
293
  case command
250
294
  when String
251
295
  msg = "#{self.name} #{a}: #{command}"
252
296
  applog(self, :info, msg)
253
-
297
+
254
298
  system(command)
255
299
  when Proc
256
300
  msg = "#{self.name} #{a}: lambda"
257
301
  applog(self, :info, msg)
258
-
302
+
259
303
  command.call
260
304
  else
261
305
  raise NotImplementedError
@@ -263,13 +307,13 @@ module God
263
307
  end
264
308
  end
265
309
  end
266
-
310
+
267
311
  ###########################################################################
268
312
  #
269
313
  # Events
270
314
  #
271
315
  ###########################################################################
272
-
316
+
273
317
  def attach(condition)
274
318
  case condition
275
319
  when PollCondition
@@ -278,7 +322,7 @@ module God
278
322
  condition.register
279
323
  end
280
324
  end
281
-
325
+
282
326
  def detach(condition)
283
327
  case condition
284
328
  when PollCondition
@@ -287,37 +331,38 @@ module God
287
331
  condition.deregister
288
332
  end
289
333
  end
290
-
334
+
291
335
  ###########################################################################
292
336
  #
293
337
  # Registration
294
338
  #
295
339
  ###########################################################################
296
-
340
+
297
341
  def register!
298
342
  # override if necessary
299
343
  end
300
-
344
+
301
345
  def unregister!
302
346
  driver.shutdown
303
347
  end
304
-
348
+
305
349
  ###########################################################################
306
350
  #
307
351
  # Handlers
308
352
  #
309
353
  ###########################################################################
310
-
354
+
311
355
  # Evaluate and handle the given poll condition. Handles logging
312
- # notifications, and moving to the new state if necessary
313
- # +condition+ is the Condition to handle
356
+ # notifications, and moving to the new state if necessary.
314
357
  #
315
- # Returns nothing
358
+ # condition - The Condition to handle.
359
+ #
360
+ # Returns nothing.
316
361
  def handle_poll(condition)
317
- # lookup metric
362
+ # Lookup metric.
318
363
  metric = self.directory[condition]
319
-
320
- # run the test
364
+
365
+ # Run the test.
321
366
  begin
322
367
  result = condition.test
323
368
  rescue Object => e
@@ -327,105 +372,108 @@ module God
327
372
  applog(self, :error, message)
328
373
  result = false
329
374
  end
330
-
331
- # log
375
+
376
+ # Log.
332
377
  messages = self.log_line(self, metric, condition, result)
333
-
334
- # notify
378
+
379
+ # Notify.
335
380
  if result && condition.notify
336
381
  self.notify(condition, messages.last)
337
382
  end
338
-
339
- # after-condition
383
+
384
+ # After-condition.
340
385
  condition.after
341
-
342
- # get the destination
343
- dest =
386
+
387
+ # Get the destination.
388
+ dest =
344
389
  if result && condition.transition
345
- # condition override
390
+ # Condition override.
346
391
  condition.transition
347
392
  else
348
- # regular
393
+ # Regular.
349
394
  metric.destination && metric.destination[result]
350
395
  end
351
-
352
- # transition or reschedule
396
+
397
+ # Transition or reschedule.
353
398
  if dest
354
- # transition
399
+ # Transition.
355
400
  begin
356
401
  self.move(dest)
357
402
  rescue EventRegistrationFailedError
358
403
  msg = self.name + ' Event registration failed, moving back to previous state'
359
404
  applog(self, :info, msg)
360
-
405
+
361
406
  dest = self.state
362
407
  retry
363
408
  end
364
409
  else
365
- # reschedule
410
+ # Reschedule.
366
411
  self.driver.schedule(condition)
367
412
  end
368
413
  end
369
-
370
- # Asynchronously evaluate and handle the given event condition. Handles logging
371
- # notifications, and moving to the new state if necessary
372
- # +condition+ is the Condition to handle
414
+
415
+ # Asynchronously evaluate and handle the given event condition. Handles
416
+ # logging notifications, and moving to the new state if necessary.
417
+ #
418
+ # condition - The Condition to handle.
373
419
  #
374
- # Returns nothing
420
+ # Returns nothing.
375
421
  def handle_event(condition)
376
- # lookup metric
422
+ # Lookup metric.
377
423
  metric = self.directory[condition]
378
-
379
- # log
424
+
425
+ # Log.
380
426
  messages = self.log_line(self, metric, condition, true)
381
-
382
- # notify
427
+
428
+ # Notify.
383
429
  if condition.notify
384
430
  self.notify(condition, messages.last)
385
431
  end
386
-
387
- # get the destination
388
- dest =
432
+
433
+ # Get the destination.
434
+ dest =
389
435
  if condition.transition
390
- # condition override
436
+ # Condition override.
391
437
  condition.transition
392
438
  else
393
- # regular
439
+ # Regular.
394
440
  metric.destination && metric.destination[true]
395
441
  end
396
-
442
+
397
443
  if dest
398
444
  self.move(dest)
399
445
  end
400
446
  end
401
-
402
- # Determine whether a trigger happened
403
- # +metric+ is the Metric
404
- # +result+ is the result from the condition's test
447
+
448
+ # Determine whether a trigger happened.
449
+ #
450
+ # metric - The Metric.
451
+ # result - The Boolean result from the condition's test.
405
452
  #
406
453
  # Returns Boolean
407
454
  def trigger?(metric, result)
408
455
  metric.destination && metric.destination[result]
409
456
  end
410
-
411
- # Log info about the condition and return the list of messages logged
412
- # +watch+ is the Watch
413
- # +metric+ is the Metric
414
- # +condition+ is the Condition
415
- # +result+ is the Boolean result of the condition test evaluation
416
- #
417
- # Returns String[]
457
+
458
+ # Log info about the condition and return the list of messages logged.
459
+ #
460
+ # watch - The Watch.
461
+ # metric - The Metric.
462
+ # condition - The Condition.
463
+ # result - The Boolean result of the condition test evaluation.
464
+ #
465
+ # Returns the Array of String messages.
418
466
  def log_line(watch, metric, condition, result)
419
- status =
467
+ status =
420
468
  if self.trigger?(metric, result)
421
469
  "[trigger]"
422
470
  else
423
471
  "[ok]"
424
472
  end
425
-
473
+
426
474
  messages = []
427
-
428
- # log info if available
475
+
476
+ # Log info if available.
429
477
  if condition.info
430
478
  Array(condition.info).each do |condition_info|
431
479
  messages << "#{watch.name} #{status} #{condition_info} (#{condition.base_name})"
@@ -435,19 +483,20 @@ module God
435
483
  messages << "#{watch.name} #{status} (#{condition.base_name})"
436
484
  applog(watch, :info, messages.last)
437
485
  end
438
-
439
- # log
486
+
487
+ # Log.
440
488
  debug_message = watch.name + ' ' + condition.base_name + " [#{result}] " + self.dest_desc(metric, condition)
441
489
  applog(watch, :debug, debug_message)
442
-
490
+
443
491
  messages
444
492
  end
445
-
446
- # Format the destination specification for use in debug logging
447
- # +metric+ is the Metric
448
- # +condition+ is the Condition
493
+
494
+ # Format the destination specification for use in debug logging.
449
495
  #
450
- # Returns String
496
+ # metric - The Metric.
497
+ # condition - The Condition.
498
+ #
499
+ # Returns the formatted String.
451
500
  def dest_desc(metric, condition)
452
501
  if condition.transition
453
502
  {true => condition.transition}.inspect
@@ -459,17 +508,18 @@ module God
459
508
  end
460
509
  end
461
510
  end
462
-
463
- # Notify all recipeients of the given condition with the specified message
464
- # +condition+ is the Condition
465
- # +message+ is the String message to send
511
+
512
+ # Notify all recipients of the given condition with the specified message.
513
+ #
514
+ # condition - The Condition.
515
+ # message - The String message to send.
466
516
  #
467
- # Returns nothing
517
+ # Returns nothing.
468
518
  def notify(condition, message)
469
519
  spec = Contact.normalize(condition.notify)
470
520
  unmatched = []
471
-
472
- # resolve contacts
521
+
522
+ # Resolve contacts.
473
523
  resolved_contacts =
474
524
  spec[:contacts].inject([]) do |acc, contact_name_or_group|
475
525
  cons = Array(God.contacts[contact_name_or_group] || God.contact_groups[contact_name_or_group])
@@ -477,14 +527,14 @@ module God
477
527
  acc += cons
478
528
  acc
479
529
  end
480
-
481
- # warn about unmatched contacts
530
+
531
+ # Warn about unmatched contacts.
482
532
  unless unmatched.empty?
483
533
  msg = "#{condition.watch.name} no matching contacts for '#{unmatched.join(", ")}'"
484
534
  applog(condition.watch, :warn, msg)
485
535
  end
486
-
487
- # notify each contact
536
+
537
+ # Notify each contact.
488
538
  resolved_contacts.each do |c|
489
539
  host = `hostname`.chomp rescue 'none'
490
540
  begin
@@ -499,5 +549,4 @@ module God
499
549
  end
500
550
  end
501
551
  end
502
-
503
552
  end