resurrected_god 0.14.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +559 -0
- data/README.md +9 -4
- data/bin/god +26 -28
- data/ext/god/extconf.rb +9 -9
- data/lib/god/behavior.rb +3 -5
- data/lib/god/behaviors/clean_pid_file.rb +4 -6
- data/lib/god/behaviors/clean_unix_socket.rb +4 -6
- data/lib/god/behaviors/notify_when_flapping.rb +13 -15
- data/lib/god/cli/command.rb +109 -89
- data/lib/god/cli/run.rb +51 -75
- data/lib/god/cli/version.rb +2 -4
- data/lib/god/condition.rb +12 -14
- data/lib/god/conditions/always.rb +3 -2
- data/lib/god/conditions/complex.rb +23 -24
- data/lib/god/conditions/cpu_usage.rb +12 -16
- data/lib/god/conditions/degrading_lambda.rb +15 -19
- data/lib/god/conditions/disk_usage.rb +7 -8
- data/lib/god/conditions/file_mtime.rb +3 -7
- data/lib/god/conditions/file_touched.rb +4 -5
- data/lib/god/conditions/flapping.rb +57 -62
- data/lib/god/conditions/http_response_code.rb +27 -32
- data/lib/god/conditions/lambda.rb +3 -5
- data/lib/god/conditions/memory_usage.rb +12 -16
- data/lib/god/conditions/process_exits.rb +12 -12
- data/lib/god/conditions/process_running.rb +8 -10
- data/lib/god/conditions/socket_responding.rb +23 -28
- data/lib/god/conditions/tries.rb +12 -14
- data/lib/god/configurable.rb +7 -10
- data/lib/god/contact.rb +41 -52
- data/lib/god/contacts/airbrake.rb +10 -12
- data/lib/god/contacts/campfire.rb +18 -20
- data/lib/god/contacts/email.rb +27 -28
- data/lib/god/contacts/prowl.rb +16 -17
- data/lib/god/contacts/scout.rb +2 -5
- data/lib/god/contacts/sensu.rb +15 -11
- data/lib/god/contacts/slack.rb +23 -33
- data/lib/god/contacts/statsd.rb +8 -8
- data/lib/god/contacts/twitter.rb +2 -2
- data/lib/god/contacts/webhook.rb +21 -24
- data/lib/god/driver.rb +12 -18
- data/lib/god/errors.rb +0 -2
- data/lib/god/event_handler.rb +40 -49
- data/lib/god/event_handlers/dummy_handler.rb +1 -1
- data/lib/god/event_handlers/kqueue_handler.rb +2 -2
- data/lib/god/event_handlers/netlink_handler.rb +1 -1
- data/lib/god/logger.rb +5 -13
- data/lib/god/metric.rb +13 -15
- data/lib/god/process.rb +93 -98
- data/lib/god/simple_logger.rb +13 -15
- data/lib/god/socket.rb +21 -23
- data/lib/god/sugar.rb +8 -8
- data/lib/god/sys_logger.rb +6 -8
- data/lib/god/system/portable_poller.rb +1 -9
- data/lib/god/system/process.rb +4 -6
- data/lib/god/system/slash_proc_poller.rb +17 -19
- data/lib/god/task.rb +110 -136
- data/lib/god/timeline.rb +2 -4
- data/lib/god/trigger.rb +7 -11
- data/lib/god/version.rb +1 -1
- data/lib/god/watch.rb +51 -57
- data/lib/god.rb +122 -148
- metadata +17 -370
- data/Announce.txt +0 -135
- data/Gemfile +0 -5
- data/Rakefile +0 -129
- data/doc/god.asciidoc +0 -1592
- data/doc/intro.asciidoc +0 -20
- data/ext/god/.gitignore +0 -5
- data/lib/god/compat19.rb +0 -33
- data/lib/god/contacts/hipchat.rb +0 -117
- data/lib/god/contacts/jabber.rb +0 -75
- data/test/configs/child_events/child_events.god +0 -44
- data/test/configs/child_events/simple_server.rb +0 -3
- data/test/configs/child_polls/child_polls.god +0 -37
- data/test/configs/child_polls/simple_server.rb +0 -12
- data/test/configs/complex/complex.god +0 -59
- data/test/configs/complex/simple_server.rb +0 -3
- data/test/configs/contact/contact.god +0 -118
- data/test/configs/contact/simple_server.rb +0 -3
- data/test/configs/daemon_events/daemon_events.god +0 -37
- data/test/configs/daemon_events/simple_server.rb +0 -8
- data/test/configs/daemon_events/simple_server_stop.rb +0 -11
- data/test/configs/daemon_polls/daemon_polls.god +0 -17
- data/test/configs/daemon_polls/simple_server.rb +0 -6
- data/test/configs/degrading_lambda/degrading_lambda.god +0 -31
- data/test/configs/degrading_lambda/tcp_server.rb +0 -15
- data/test/configs/keepalive/keepalive.god +0 -9
- data/test/configs/keepalive/keepalive.rb +0 -12
- data/test/configs/lifecycle/lifecycle.god +0 -25
- data/test/configs/matias/matias.god +0 -50
- data/test/configs/real.rb +0 -59
- data/test/configs/running_load/running_load.god +0 -16
- data/test/configs/stop_options/simple_server.rb +0 -12
- data/test/configs/stop_options/stop_options.god +0 -39
- data/test/configs/stress/simple_server.rb +0 -3
- data/test/configs/stress/stress.god +0 -15
- data/test/configs/task/logs/.placeholder +0 -0
- data/test/configs/task/task.god +0 -26
- data/test/configs/test.rb +0 -61
- data/test/configs/usr1_trapper.rb +0 -10
- data/test/helper.rb +0 -172
- data/test/suite.rb +0 -6
- data/test/test_airbrake.rb +0 -14
- data/test/test_behavior.rb +0 -18
- data/test/test_campfire.rb +0 -22
- data/test/test_condition.rb +0 -52
- data/test/test_conditions_disk_usage.rb +0 -50
- data/test/test_conditions_http_response_code.rb +0 -109
- data/test/test_conditions_process_running.rb +0 -40
- data/test/test_conditions_socket_responding.rb +0 -176
- data/test/test_conditions_tries.rb +0 -67
- data/test/test_contact.rb +0 -109
- data/test/test_driver.rb +0 -26
- data/test/test_email.rb +0 -34
- data/test/test_event_handler.rb +0 -82
- data/test/test_god.rb +0 -710
- data/test/test_god_system.rb +0 -201
- data/test/test_handlers_kqueue_handler.rb +0 -16
- data/test/test_hipchat.rb +0 -23
- data/test/test_jabber.rb +0 -29
- data/test/test_logger.rb +0 -55
- data/test/test_metric.rb +0 -74
- data/test/test_process.rb +0 -263
- data/test/test_prowl.rb +0 -15
- data/test/test_registry.rb +0 -15
- data/test/test_sensu.rb +0 -11
- data/test/test_slack.rb +0 -57
- data/test/test_socket.rb +0 -34
- data/test/test_statsd.rb +0 -22
- data/test/test_sugar.rb +0 -42
- data/test/test_system_portable_poller.rb +0 -17
- data/test/test_system_process.rb +0 -30
- data/test/test_task.rb +0 -246
- data/test/test_timeline.rb +0 -37
- data/test/test_trigger.rb +0 -63
- data/test/test_watch.rb +0 -286
- data/test/test_webhook.rb +0 -22
data/lib/god/cli/run.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module God
|
2
2
|
module CLI
|
3
|
-
|
4
3
|
class Run
|
5
4
|
def initialize(options)
|
6
5
|
@options = options
|
@@ -12,9 +11,7 @@ module God
|
|
12
11
|
# have at_exit start god
|
13
12
|
$run = true
|
14
13
|
|
15
|
-
if @options[:syslog]
|
16
|
-
require 'god/sys_logger'
|
17
|
-
end
|
14
|
+
require 'god/sys_logger' if @options[:syslog]
|
18
15
|
|
19
16
|
# run
|
20
17
|
if @options[:daemonize]
|
@@ -42,29 +39,21 @@ module God
|
|
42
39
|
setup_logging
|
43
40
|
|
44
41
|
# start attached pid watcher if necessary
|
45
|
-
if @options[:attach]
|
46
|
-
self.attach
|
47
|
-
end
|
42
|
+
attach if @options[:attach]
|
48
43
|
|
49
|
-
if @options[:port]
|
50
|
-
God.port = @options[:port]
|
51
|
-
end
|
44
|
+
God.port = @options[:port] if @options[:port]
|
52
45
|
|
53
|
-
if @options[:events]
|
54
|
-
God::EventHandler.load
|
55
|
-
end
|
46
|
+
God::EventHandler.load if @options[:events]
|
56
47
|
|
57
48
|
# set log level, defaults to WARN
|
58
|
-
if @options[:log_level]
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
49
|
+
God.log_level = if @options[:log_level]
|
50
|
+
@options[:log_level]
|
51
|
+
else
|
52
|
+
@options[:daemonize] ? :warn : :info
|
53
|
+
end
|
63
54
|
|
64
55
|
if @options[:config]
|
65
|
-
if !@options[:config].include?('*') && !File.exist?(@options[:config])
|
66
|
-
abort "File not found: #{@options[:config]}"
|
67
|
-
end
|
56
|
+
abort "File not found: #{@options[:config]}" if !@options[:config].include?('*') && !File.exist?(@options[:config])
|
68
57
|
|
69
58
|
# start the event handler
|
70
59
|
God::EventHandler.start if God::EventHandler.loaded?
|
@@ -82,42 +71,35 @@ module God
|
|
82
71
|
|
83
72
|
def run_daemonized
|
84
73
|
# trap and ignore SIGHUP
|
85
|
-
Signal.trap('HUP') {}
|
74
|
+
Signal.trap('HUP') {} # block must be passed
|
86
75
|
# trap and log-reopen SIGUSR1
|
87
76
|
Signal.trap('USR1') { setup_logging }
|
88
77
|
|
89
78
|
pid = fork do
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
puts "*"
|
107
|
-
puts "***********************************************************************"
|
108
|
-
puts
|
109
|
-
end
|
110
|
-
|
111
|
-
rescue => e
|
112
|
-
puts e.message
|
113
|
-
puts e.backtrace.join("\n")
|
114
|
-
abort "There was a fatal system error while starting god (see above)"
|
79
|
+
require 'god'
|
80
|
+
|
81
|
+
# set pid if requested
|
82
|
+
God.pid = @options[:pid] if @options[:pid] # and as daemon
|
83
|
+
|
84
|
+
default_run
|
85
|
+
|
86
|
+
unless God::EventHandler.loaded?
|
87
|
+
puts
|
88
|
+
puts '***********************************************************************'
|
89
|
+
puts '*'
|
90
|
+
puts '* Event conditions are not available for your installation of god.'
|
91
|
+
puts '* You may still use and write custom conditions using the poll system'
|
92
|
+
puts '*'
|
93
|
+
puts '***********************************************************************'
|
94
|
+
puts
|
115
95
|
end
|
96
|
+
rescue => e
|
97
|
+
puts e.message
|
98
|
+
puts e.backtrace.join("\n")
|
99
|
+
abort 'There was a fatal system error while starting god (see above)'
|
116
100
|
end
|
117
101
|
|
118
|
-
if @options[:pid]
|
119
|
-
File.open(@options[:pid], 'w') { |f| f.write pid }
|
120
|
-
end
|
102
|
+
File.write(@options[:pid], pid) if @options[:pid]
|
121
103
|
|
122
104
|
::Process.detach pid
|
123
105
|
|
@@ -127,25 +109,23 @@ module God
|
|
127
109
|
def setup_logging
|
128
110
|
log_file = God.log_file
|
129
111
|
log_file = File.expand_path(@options[:log]) if @options[:log]
|
130
|
-
log_file =
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
112
|
+
log_file = '/dev/null' if !log_file && @options[:daemonize]
|
113
|
+
return unless log_file
|
114
|
+
|
115
|
+
puts "Sending output to log file: #{log_file}" unless @options[:daemonize]
|
116
|
+
|
117
|
+
# reset file descriptors
|
118
|
+
$stdin.reopen '/dev/null'
|
119
|
+
$stdout.reopen(log_file, 'a')
|
120
|
+
$stderr.reopen $stdout
|
121
|
+
$stdout.sync = true
|
140
122
|
end
|
141
123
|
|
142
124
|
def load_config(config)
|
143
125
|
files = File.directory?(config) ? Dir['**/*.god'] : Dir[config]
|
144
|
-
abort
|
126
|
+
abort 'No files could be found' if files.empty?
|
145
127
|
files.each do |god_file|
|
146
|
-
unless load_god_file(god_file)
|
147
|
-
abort "File '#{god_file}' could not be loaded"
|
148
|
-
end
|
128
|
+
abort "File '#{god_file}' could not be loaded" unless load_god_file(god_file)
|
149
129
|
end
|
150
130
|
end
|
151
131
|
|
@@ -154,17 +134,13 @@ module God
|
|
154
134
|
load File.expand_path(god_file)
|
155
135
|
true
|
156
136
|
rescue Exception => e
|
157
|
-
if e.instance_of?(SystemExit)
|
158
|
-
raise
|
159
|
-
else
|
160
|
-
puts "There was an error in #{god_file}"
|
161
|
-
puts "\t" + e.message
|
162
|
-
puts "\t" + e.backtrace.join("\n\t")
|
163
|
-
false
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
end # Run
|
137
|
+
raise if e.instance_of?(SystemExit)
|
168
138
|
|
139
|
+
puts "There was an error in #{god_file}"
|
140
|
+
puts "\t#{e.message}"
|
141
|
+
puts "\t#{e.backtrace.join("\n\t")}"
|
142
|
+
false
|
143
|
+
end
|
144
|
+
end
|
169
145
|
end
|
170
146
|
end
|
data/lib/god/cli/version.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module God
|
2
2
|
module CLI
|
3
|
-
|
4
3
|
class Version
|
5
4
|
def self.version
|
6
5
|
require 'god'
|
@@ -12,12 +11,11 @@ module God
|
|
12
11
|
|
13
12
|
def self.version_extended
|
14
13
|
puts "Version: #{God.version}"
|
15
|
-
puts
|
16
|
-
puts "Events:
|
14
|
+
puts 'Polls: enabled'
|
15
|
+
puts "Events: #{God::EventHandler.event_system}"
|
17
16
|
|
18
17
|
exit
|
19
18
|
end
|
20
19
|
end
|
21
|
-
|
22
20
|
end
|
23
21
|
end
|
data/lib/god/condition.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module God
|
2
|
-
|
3
2
|
class Condition < Behavior
|
4
3
|
attr_accessor :transition, :notify, :info, :phase
|
5
4
|
|
@@ -7,21 +6,21 @@ module God
|
|
7
6
|
# kind (which is given as an underscored symbol).
|
8
7
|
# +kind+ is the underscored symbol representing the class (e.g. :foo_bar for God::Conditions::FooBar)
|
9
8
|
def self.generate(kind, watch)
|
10
|
-
sym = kind.to_s.capitalize.gsub(/_(.)/){
|
9
|
+
sym = kind.to_s.capitalize.gsub(/_(.)/) { Regexp.last_match(1).upcase }.intern
|
11
10
|
c = God::Conditions.const_get(sym).new
|
12
11
|
|
13
|
-
unless c.
|
12
|
+
unless c.is_a?(PollCondition) || c.is_a?(EventCondition) || c.is_a?(TriggerCondition)
|
14
13
|
abort "Condition '#{c.class.name}' must subclass God::PollCondition, God::EventCondition, or God::TriggerCondition"
|
15
14
|
end
|
16
15
|
|
17
|
-
if !EventHandler.loaded? && c.
|
16
|
+
if !EventHandler.loaded? && c.is_a?(EventCondition)
|
18
17
|
abort "Condition '#{c.class.name}' requires an event system but none has been loaded"
|
19
18
|
end
|
20
19
|
|
21
20
|
c.watch = watch
|
22
21
|
c
|
23
22
|
rescue NameError
|
24
|
-
raise NoSuchConditionError
|
23
|
+
raise NoSuchConditionError, "No Condition found with the class name God::Conditions::#{sym}"
|
25
24
|
end
|
26
25
|
|
27
26
|
def self.valid?(condition)
|
@@ -30,7 +29,7 @@ module God
|
|
30
29
|
begin
|
31
30
|
Contact.normalize(condition.notify)
|
32
31
|
rescue ArgumentError => e
|
33
|
-
valid &= Configurable.complain("Attribute 'notify'
|
32
|
+
valid &= Configurable.complain("Attribute 'notify' #{e.message}", condition)
|
34
33
|
end
|
35
34
|
end
|
36
35
|
valid
|
@@ -40,7 +39,7 @@ module God
|
|
40
39
|
#
|
41
40
|
# Condition FooBar on Watch 'baz'
|
42
41
|
def friendly_name
|
43
|
-
"Condition #{self.class.name.split('::').last} on Watch '#{
|
42
|
+
"Condition #{self.class.name.split('::').last} on Watch '#{watch.name}'"
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
@@ -57,7 +56,7 @@ module God
|
|
57
56
|
# Return true if the test passes (everything is ok)
|
58
57
|
# Return false otherwise
|
59
58
|
def test
|
60
|
-
raise AbstractMethodNotOverriddenError
|
59
|
+
raise AbstractMethodNotOverriddenError, 'PollCondition#test must be overridden in subclasses'
|
61
60
|
end
|
62
61
|
|
63
62
|
# Override this method in your Conditions (optional)
|
@@ -67,21 +66,21 @@ module God
|
|
67
66
|
|
68
67
|
class EventCondition < Condition
|
69
68
|
def register
|
70
|
-
raise AbstractMethodNotOverriddenError
|
69
|
+
raise AbstractMethodNotOverriddenError, 'EventCondition#register must be overridden in subclasses'
|
71
70
|
end
|
72
71
|
|
73
72
|
def deregister
|
74
|
-
raise AbstractMethodNotOverriddenError
|
73
|
+
raise AbstractMethodNotOverriddenError, 'EventCondition#deregister must be overridden in subclasses'
|
75
74
|
end
|
76
75
|
end
|
77
76
|
|
78
77
|
class TriggerCondition < Condition
|
79
|
-
def process(event, payload)
|
80
|
-
raise AbstractMethodNotOverriddenError
|
78
|
+
def process(event, payload) # rubocop:disable Lint/UnusedMethodArgument
|
79
|
+
raise AbstractMethodNotOverriddenError, 'TriggerCondition#process must be overridden in subclasses'
|
81
80
|
end
|
82
81
|
|
83
82
|
def trigger
|
84
|
-
|
83
|
+
watch.trigger(self)
|
85
84
|
end
|
86
85
|
|
87
86
|
def register
|
@@ -92,5 +91,4 @@ module God
|
|
92
91
|
Trigger.deregister(self)
|
93
92
|
end
|
94
93
|
end
|
95
|
-
|
96
94
|
end
|
@@ -19,12 +19,13 @@ module God
|
|
19
19
|
attr_accessor :what
|
20
20
|
|
21
21
|
def initialize
|
22
|
-
|
22
|
+
super
|
23
|
+
self.info = 'always'
|
23
24
|
end
|
24
25
|
|
25
26
|
def valid?
|
26
27
|
valid = true
|
27
|
-
valid &= complain("Attribute 'what' must be specified", self) if
|
28
|
+
valid &= complain("Attribute 'what' must be specified", self) if what.nil?
|
28
29
|
valid
|
29
30
|
end
|
30
31
|
|
@@ -1,12 +1,11 @@
|
|
1
1
|
module God
|
2
2
|
module Conditions
|
3
|
-
|
4
3
|
class Complex < PollCondition
|
5
4
|
AND = 0x1
|
6
5
|
OR = 0x2
|
7
6
|
NOT = 0x4
|
8
7
|
|
9
|
-
def initialize
|
8
|
+
def initialize
|
10
9
|
super
|
11
10
|
|
12
11
|
@oper_stack = []
|
@@ -20,18 +19,18 @@ module God
|
|
20
19
|
end
|
21
20
|
|
22
21
|
def prepare
|
23
|
-
@oper_stack.each
|
22
|
+
@oper_stack.each(&:prepare)
|
24
23
|
end
|
25
24
|
|
26
|
-
def new_oper(kind,
|
27
|
-
oper = Condition.generate(kind,
|
25
|
+
def new_oper(kind, operand)
|
26
|
+
oper = Condition.generate(kind, watch)
|
28
27
|
@oper_stack.push(oper)
|
29
|
-
@op_stack.push(
|
28
|
+
@op_stack.push(operand)
|
30
29
|
oper
|
31
30
|
end
|
32
31
|
|
33
32
|
def this(kind)
|
34
|
-
@this = Condition.generate(kind,
|
33
|
+
@this = Condition.generate(kind, watch)
|
35
34
|
yield @this if block_given?
|
36
35
|
end
|
37
36
|
|
@@ -56,31 +55,31 @@ module God
|
|
56
55
|
end
|
57
56
|
|
58
57
|
def test
|
59
|
-
if @this.nil?
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
71
|
-
else
|
72
|
-
res = @this.test
|
73
|
-
end
|
58
|
+
res = if @this.nil?
|
59
|
+
# Although this() makes sense semantically and therefore
|
60
|
+
# encourages easy-to-read conditions, being able to omit it
|
61
|
+
# allows for more DRY code in some cases, so we deal with a
|
62
|
+
# nil @this here by initially setting res to true or false,
|
63
|
+
# depending on whether the first operator used is AND or OR
|
64
|
+
# respectively.
|
65
|
+
@op_stack[0] & AND > 0
|
66
|
+
else
|
67
|
+
@this.test
|
68
|
+
end
|
74
69
|
|
75
70
|
@op_stack.each do |op|
|
76
71
|
cond = @oper_stack.shift
|
77
|
-
|
72
|
+
value = op & NOT > 0 ? !cond.test : cond.test
|
73
|
+
if op & AND > 0
|
74
|
+
res &&= value
|
75
|
+
else
|
76
|
+
res ||= value
|
77
|
+
end
|
78
78
|
@oper_stack.push cond
|
79
79
|
end
|
80
80
|
|
81
81
|
res
|
82
82
|
end
|
83
83
|
end
|
84
|
-
|
85
84
|
end
|
86
85
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module God
|
2
2
|
module Conditions
|
3
|
-
|
4
3
|
# Condition Symbol :cpu_usage
|
5
4
|
# Type: Poll
|
6
5
|
#
|
7
6
|
# Trigger when the percent of CPU use of a process is above a specified limit.
|
8
7
|
# On multi-core systems, this number could conceivably be above 100.
|
9
8
|
#
|
10
|
-
#
|
9
|
+
# Parameters
|
11
10
|
# Required
|
12
11
|
# +pid_file+ is the pid file of the process in question. Automatically
|
13
12
|
# populated for Watches.
|
@@ -38,11 +37,9 @@ module God
|
|
38
37
|
end
|
39
38
|
|
40
39
|
def prepare
|
41
|
-
|
42
|
-
self.times = [self.times, self.times]
|
43
|
-
end
|
40
|
+
self.times = [times, times] if times.is_a?(Integer)
|
44
41
|
|
45
|
-
@timeline = Timeline.new(
|
42
|
+
@timeline = Timeline.new(times[1])
|
46
43
|
end
|
47
44
|
|
48
45
|
def reset
|
@@ -50,31 +47,30 @@ module God
|
|
50
47
|
end
|
51
48
|
|
52
49
|
def pid
|
53
|
-
|
50
|
+
pid_file ? File.read(pid_file).strip.to_i : watch.pid
|
54
51
|
end
|
55
52
|
|
56
53
|
def valid?
|
57
54
|
valid = true
|
58
|
-
valid &= complain("Attribute 'pid_file' must be specified", self) if
|
59
|
-
valid &= complain("Attribute 'above' must be specified", self) if
|
55
|
+
valid &= complain("Attribute 'pid_file' must be specified", self) if pid_file.nil? && watch.pid_file.nil?
|
56
|
+
valid &= complain("Attribute 'above' must be specified", self) if above.nil?
|
60
57
|
valid
|
61
58
|
end
|
62
59
|
|
63
60
|
def test
|
64
|
-
process = System::Process.new(
|
61
|
+
process = System::Process.new(pid)
|
65
62
|
@timeline.push(process.percent_cpu)
|
66
63
|
self.info = []
|
67
64
|
|
68
|
-
history =
|
65
|
+
history = @timeline.map { |x| "#{x > above ? '*' : ''}#{x}%%" }.join(', ')
|
69
66
|
|
70
|
-
if @timeline.
|
71
|
-
self.info = "cpu out of bounds #{history}"
|
72
|
-
|
67
|
+
if @timeline.count { |x| x > above } >= times.first
|
68
|
+
self.info = "cpu out of bounds [#{history}]"
|
69
|
+
true
|
73
70
|
else
|
74
|
-
|
71
|
+
false
|
75
72
|
end
|
76
73
|
end
|
77
74
|
end
|
78
|
-
|
79
75
|
end
|
80
76
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module God
|
2
2
|
module Conditions
|
3
|
-
|
4
3
|
# This condition degrades its interval by a factor of two for 3 tries before failing
|
5
4
|
class DegradingLambda < PollCondition
|
6
5
|
attr_accessor :lambda
|
@@ -17,36 +16,33 @@ module God
|
|
17
16
|
end
|
18
17
|
|
19
18
|
def test
|
20
|
-
puts "Calling test. Interval at #{
|
21
|
-
@original_interval ||=
|
22
|
-
|
19
|
+
puts "Calling test. Interval at #{interval}"
|
20
|
+
@original_interval ||= interval
|
21
|
+
if pass?
|
22
|
+
@tries = 0
|
23
|
+
self.interval = @original_interval
|
24
|
+
else
|
23
25
|
if @tries == 2
|
24
|
-
self.info =
|
26
|
+
self.info = 'lambda condition was satisfied'
|
25
27
|
return true
|
26
28
|
end
|
27
|
-
self.interval =
|
29
|
+
self.interval = interval / 2.0
|
28
30
|
@tries += 1
|
29
|
-
else
|
30
|
-
@tries = 0
|
31
|
-
self.interval = @original_interval
|
32
31
|
end
|
33
32
|
|
34
|
-
self.info =
|
33
|
+
self.info = 'lambda condition was not satisfied'
|
35
34
|
false
|
36
35
|
end
|
37
36
|
|
38
37
|
private
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
self.lambda.call()
|
44
|
-
}
|
45
|
-
rescue Timeout::Error
|
46
|
-
false
|
47
|
-
end
|
39
|
+
def pass?
|
40
|
+
Timeout.timeout(@interval) do
|
41
|
+
self.lambda.call
|
48
42
|
end
|
43
|
+
rescue Timeout::Error
|
44
|
+
false
|
45
|
+
end
|
49
46
|
end
|
50
|
-
|
51
47
|
end
|
52
48
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module God
|
2
2
|
module Conditions
|
3
|
-
|
4
3
|
class DiskUsage < PollCondition
|
5
4
|
attr_accessor :above, :mount_point
|
6
5
|
|
@@ -12,19 +11,19 @@ module God
|
|
12
11
|
|
13
12
|
def valid?
|
14
13
|
valid = true
|
15
|
-
valid &= complain("Attribute 'mount_point' must be specified", self) if
|
16
|
-
valid &= complain("Attribute 'above' must be specified", self) if
|
14
|
+
valid &= complain("Attribute 'mount_point' must be specified", self) if mount_point.nil?
|
15
|
+
valid &= complain("Attribute 'above' must be specified", self) if above.nil?
|
17
16
|
valid
|
18
17
|
end
|
19
18
|
|
20
19
|
def test
|
21
20
|
self.info = []
|
22
|
-
usage = `df -P | grep -i " #{
|
23
|
-
if usage.to_i >
|
24
|
-
self.info =
|
25
|
-
|
21
|
+
usage = `df -P | grep -i " #{mount_point}$" | awk '{print $5}' | sed 's/%//'`
|
22
|
+
if usage.to_i > above
|
23
|
+
self.info = 'disk space out of bounds'
|
24
|
+
true
|
26
25
|
else
|
27
|
-
|
26
|
+
false
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module God
|
2
2
|
module Conditions
|
3
|
-
|
4
3
|
class FileMtime < PollCondition
|
5
4
|
attr_accessor :path, :max_age
|
6
5
|
|
@@ -12,17 +11,14 @@ module God
|
|
12
11
|
|
13
12
|
def valid?
|
14
13
|
valid = true
|
15
|
-
valid &= complain("Attribute 'path' must be specified", self) if
|
16
|
-
valid &= complain("Attribute 'max_age' must be specified", self) if
|
14
|
+
valid &= complain("Attribute 'path' must be specified", self) if path.nil?
|
15
|
+
valid &= complain("Attribute 'max_age' must be specified", self) if max_age.nil?
|
17
16
|
valid
|
18
17
|
end
|
19
18
|
|
20
19
|
def test
|
21
|
-
(Time.now - File.mtime(
|
20
|
+
(Time.now - File.mtime(path)) > max_age
|
22
21
|
end
|
23
22
|
end
|
24
|
-
|
25
23
|
end
|
26
24
|
end
|
27
|
-
|
28
|
-
|
@@ -1,12 +1,11 @@
|
|
1
1
|
module God
|
2
2
|
module Conditions
|
3
|
-
|
4
3
|
# Condition Symbol :file_touched
|
5
4
|
# Type: Poll
|
6
5
|
#
|
7
6
|
# Trigger when a specified file is touched.
|
8
7
|
#
|
9
|
-
#
|
8
|
+
# Parameters
|
10
9
|
# Required
|
11
10
|
# +path+ is the path to the file to watch.
|
12
11
|
#
|
@@ -28,13 +27,13 @@ module God
|
|
28
27
|
|
29
28
|
def valid?
|
30
29
|
valid = true
|
31
|
-
valid &= complain("Attribute 'path' must be specified", self) if
|
30
|
+
valid &= complain("Attribute 'path' must be specified", self) if path.nil?
|
32
31
|
valid
|
33
32
|
end
|
34
33
|
|
35
34
|
def test
|
36
|
-
if File.
|
37
|
-
(Time.now - File.mtime(
|
35
|
+
if File.exist?(path)
|
36
|
+
(Time.now - File.mtime(path)) <= interval
|
38
37
|
else
|
39
38
|
false
|
40
39
|
end
|