god 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. data/History.txt +26 -2
  2. data/Manifest.txt +19 -5
  3. data/Rakefile +7 -2
  4. data/bin/god +131 -11
  5. data/examples/events.god +52 -0
  6. data/examples/gravatar.god +29 -35
  7. data/ext/god/extconf.rb +49 -2
  8. data/ext/god/kqueue_handler.c +2 -2
  9. data/ext/god/netlink_handler.c +17 -4
  10. data/lib/god.rb +127 -25
  11. data/lib/god/behavior.rb +8 -3
  12. data/lib/god/behaviors/clean_pid_file.rb +2 -8
  13. data/lib/god/condition.rb +6 -5
  14. data/lib/god/conditions/cpu_usage.rb +4 -4
  15. data/lib/god/conditions/lambda.rb +19 -0
  16. data/lib/god/conditions/memory_usage.rb +4 -4
  17. data/lib/god/conditions/process_exits.rb +5 -7
  18. data/lib/god/conditions/process_running.rb +4 -4
  19. data/lib/god/errors.rb +3 -0
  20. data/lib/god/event_handler.rb +28 -3
  21. data/lib/god/event_handlers/dummy_handler.rb +13 -0
  22. data/lib/god/event_handlers/kqueue_handler.rb +2 -0
  23. data/lib/god/event_handlers/netlink_handler.rb +2 -0
  24. data/lib/god/hub.rb +40 -23
  25. data/lib/god/metric.rb +4 -4
  26. data/lib/god/process.rb +105 -0
  27. data/lib/god/registry.rb +28 -0
  28. data/lib/god/server.rb +3 -4
  29. data/lib/god/sugar.rb +47 -0
  30. data/lib/god/system/process.rb +1 -2
  31. data/lib/god/timer.rb +13 -6
  32. data/lib/god/watch.rb +61 -29
  33. data/test/configs/child_events/child_events.god +25 -0
  34. data/test/configs/child_events/simple_server.rb +3 -0
  35. data/test/configs/child_polls/child_polls.god +15 -0
  36. data/test/configs/child_polls/simple_server.rb +3 -0
  37. data/test/configs/daemon_events/daemon_events.god +30 -0
  38. data/test/configs/daemon_events/simple_server.rb +6 -0
  39. data/test/configs/real.rb +47 -49
  40. data/test/configs/test.rb +52 -62
  41. data/test/helper.rb +44 -14
  42. data/test/test_behavior.rb +10 -2
  43. data/test/test_condition.rb +19 -3
  44. data/test/test_conditions_process_running.rb +42 -0
  45. data/test/test_event_handler.rb +73 -0
  46. data/test/test_god.rb +206 -9
  47. data/test/test_handlers_kqueue_handler.rb +12 -0
  48. data/test/test_hub.rb +157 -0
  49. data/test/test_metric.rb +30 -2
  50. data/test/test_process.rb +84 -0
  51. data/test/test_registry.rb +14 -0
  52. data/test/test_server.rb +3 -2
  53. data/test/test_sugar.rb +42 -0
  54. data/test/test_system_process.rb +1 -1
  55. data/test/test_timer.rb +8 -1
  56. data/test/test_watch.rb +137 -2
  57. metadata +28 -17
  58. data/examples/local.god +0 -60
  59. data/ext/god/Makefile +0 -149
  60. data/lib/god/base.rb +0 -13
  61. data/lib/god/meddle.rb +0 -38
  62. data/test/test_meddle.rb +0 -46
@@ -1,10 +1,34 @@
1
- == 0.2.0
1
+ == 0.3.0 / 2007-08-17
2
+
3
+ * Fix netlink header problem on Ubuntu Edgy [Dan Sully]
4
+ * Add uid/gid setting for processes [kevinclark]
5
+ * Add autostart flag for watches so they don't necessarily startup with god [kevinclark]
6
+ * Change command line call options for god binary to accommodate watch start/stop functionality
7
+ * Add individual start/stop/restart grace periods for finer grained control
8
+ * Change default DRb port to 17165 ('god'.to_i(32))
9
+ * Implement command line control to start/restart/stop/monitor/unmonitor watches/groups by name
10
+ * Watches can now belong to a group that can be controlled as a whole
11
+ * Allow god to be installed (sans events) on systems that don't support events
12
+ * Daemonize and handle PID files for non-daemonizing scripts [kevinclark]
13
+ * Fix simple mode lifecycle gap
14
+ * Remove necessity to specify pid_file for conditions
15
+ * Change config file to use God.init and God.watch directly instead of God.meddle block
16
+ * Move god binary command logic to main library
17
+ * Enhance god binary with better reporting
18
+ * Fix synchronization bug in Timer (reported by Srini Panguluri)
19
+ * Add Lambda condition for easy custom conditions [Mike Mintz]
20
+ * Add sugar for numerics (seconds, minutes, kilobytes, megabytes, percent, etc)
21
+ * Add optional PID and log file generation to god binary for daemon mode
22
+ * Add God.load to do glob enabled loading
23
+ * Add -V option to god binary for detailed version/build info
24
+
25
+ == 0.2.0 / 2007-07-18
2
26
 
3
27
  * Rewrote innards to use a state and event based lifecycle
4
28
  * Basic support for events via kqueue (bsd/darwin) and netlink/pec (linux) [kevinclark]
5
29
  * Added advanced syntax (simple syntax calls advanced api underneath)
6
30
  * Condition returns have changed meaning. With simple syntax, a true return activates block
7
- * Updated http://god.rubygorge.org with updated simple config and new advanced config
31
+ * Updated http://god.rubyforge.org with updated simple config and new advanced config
8
32
 
9
33
  == 0.1.0 / 2007-07-07
10
34
 
@@ -3,46 +3,60 @@ Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
5
  bin/god
6
+ examples/events.god
6
7
  examples/gravatar.god
7
- examples/local.god
8
- ext/god/Makefile
9
8
  ext/god/extconf.rb
10
9
  ext/god/kqueue_handler.c
11
10
  ext/god/netlink_handler.c
12
11
  lib/god.rb
13
- lib/god/base.rb
14
12
  lib/god/behavior.rb
15
13
  lib/god/behaviors/clean_pid_file.rb
16
14
  lib/god/condition.rb
17
15
  lib/god/conditions/always.rb
18
16
  lib/god/conditions/cpu_usage.rb
17
+ lib/god/conditions/lambda.rb
19
18
  lib/god/conditions/memory_usage.rb
20
19
  lib/god/conditions/process_exits.rb
21
20
  lib/god/conditions/process_running.rb
22
21
  lib/god/conditions/timeline.rb
23
22
  lib/god/errors.rb
24
23
  lib/god/event_handler.rb
24
+ lib/god/event_handlers/dummy_handler.rb
25
25
  lib/god/event_handlers/kqueue_handler.rb
26
26
  lib/god/event_handlers/netlink_handler.rb
27
27
  lib/god/hub.rb
28
- lib/god/meddle.rb
29
28
  lib/god/metric.rb
29
+ lib/god/process.rb
30
+ lib/god/registry.rb
30
31
  lib/god/reporter.rb
31
32
  lib/god/server.rb
33
+ lib/god/sugar.rb
32
34
  lib/god/system/process.rb
33
35
  lib/god/timer.rb
34
36
  lib/god/watch.rb
37
+ test/configs/child_events/child_events.god
38
+ test/configs/child_events/simple_server.rb
39
+ test/configs/child_polls/child_polls.god
40
+ test/configs/child_polls/simple_server.rb
41
+ test/configs/daemon_events/daemon_events.god
42
+ test/configs/daemon_events/simple_server.rb
35
43
  test/configs/real.rb
36
44
  test/configs/test.rb
37
45
  test/helper.rb
38
46
  test/suite.rb
39
47
  test/test_behavior.rb
40
48
  test/test_condition.rb
49
+ test/test_conditions_process_running.rb
50
+ test/test_event_handler.rb
41
51
  test/test_god.rb
42
- test/test_meddle.rb
52
+ test/test_handlers_kqueue_handler.rb
53
+ test/test_hub.rb
43
54
  test/test_metric.rb
55
+ test/test_process.rb
56
+ test/test_registry.rb
44
57
  test/test_reporter.rb
45
58
  test/test_server.rb
59
+ test/test_sugar.rb
46
60
  test/test_system_process.rb
47
61
  test/test_timeline.rb
48
62
  test/test_timer.rb
data/Rakefile CHANGED
@@ -3,7 +3,7 @@
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
5
 
6
- Hoe.new('god', '0.2.0') do |p|
6
+ Hoe.new('god', '0.3.0') do |p|
7
7
  p.rubyforge_name = 'god'
8
8
  p.author = 'Tom Preston-Werner'
9
9
  p.email = 'tom@rubyisawesome.com'
@@ -11,7 +11,7 @@ Hoe.new('god', '0.2.0') do |p|
11
11
  p.summary = 'Like monit, only awesome'
12
12
  p.description = "God is an easy to configure, easy to extend monitoring framework written in Ruby."
13
13
  p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
14
- p.extra_deps << ['daemons', '>=1.0.7']
14
+ # p.extra_deps << ['daemons', '>=1.0.7']
15
15
  p.spec_extras = {:extensions => ['ext/god/extconf.rb']}
16
16
  end
17
17
 
@@ -25,4 +25,9 @@ task :site do
25
25
  sh "scp -r site/* mojombo@god.rubyforge.org:/var/www/gforge-projects/god"
26
26
  end
27
27
 
28
+ desc "Upload site to Rubyforge"
29
+ task :site_edge do
30
+ sh "scp -r site/* mojombo@god.rubyforge.org:/var/www/gforge-projects/god/edge"
31
+ end
32
+
28
33
  # vim: syntax=Ruby
data/bin/god CHANGED
@@ -3,24 +3,144 @@
3
3
  $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
4
 
5
5
  require 'rubygems'
6
- require 'daemons'
7
6
  require 'optparse'
8
- require 'god'
7
+ require 'drb'
8
+
9
+ options = {:daemonize => true, :port => 17165}
9
10
 
10
- options = {}
11
11
  OptionParser.new do |opts|
12
- opts.banner = "Usage: god command [options]"
12
+ opts.banner = <<-EOF
13
+ Usage: god [command] [options]
14
+
15
+ Commands:
16
+ start <watch or group name>
17
+ stop <watch or group name>
18
+ monitor <watch or group name>
19
+ unmonitor <watch or group name>
20
+
21
+ Options:
22
+ EOF
13
23
 
14
24
  opts.on("-cCONFIG", "--config-file CONFIG", "Configuration file") do |x|
15
25
  options[:config] = x
16
26
  end
17
- end.parse!
18
27
 
19
- options[:config] = File.expand_path(options[:config]) if options[:config]
20
-
21
- # p options
22
- # p ARGV
28
+ opts.on("-pPORT", "--port PORT", "Communications port") do |x|
29
+ options[:port] = x
30
+ end
31
+
32
+ opts.on("-PFILE", "--pid FILE", "Where to write the PID file") do |x|
33
+ options[:pid] = x
34
+ end
35
+
36
+ opts.on("-lFILE", "--log FILE", "Where to write the log file") do |x|
37
+ options[:log] = x
38
+ end
39
+
40
+ opts.on("-D", "--no-daemonize", "Don't daemonize") do
41
+ options[:daemonize] = false
42
+ end
43
+
44
+ opts.on("-v", "--version", "Print the version number and exit") do
45
+ options[:version] = true
46
+ end
47
+
48
+ opts.on("-V", "Print extended version and build information") do
49
+ options[:info] = true
50
+ end
51
+ end.parse!
23
52
 
24
- Daemons.run_proc('god') do
25
- load options[:config]
53
+ if options[:version]
54
+ require 'god'
55
+
56
+ # print version
57
+ puts "Version #{God::VERSION}"
58
+ exit!
59
+ elsif options[:info]
60
+ require 'god'
61
+
62
+ puts "Version: #{God::VERSION}"
63
+ puts "Polls: enabled"
64
+ puts "Events: " + God::EventHandler.event_system
65
+
66
+ exit!
67
+ elsif command = ARGV[0]
68
+ require 'god'
69
+
70
+ # a command was specified
71
+
72
+ # disable at_exit
73
+ # module God; def self.at_exit; end; end
74
+
75
+ # get the name of the watch/group
76
+ name = ARGV[1]
77
+
78
+ # connect to remote drb
79
+ DRb.start_service
80
+ server = DRbObject.new nil, "druby://localhost:#{options[:port]}"
81
+
82
+ begin
83
+ puts "Sending '#{command}' command"
84
+
85
+ # send command
86
+ watches = server.control(name, command)
87
+
88
+ # output response
89
+ puts 'The following watches were affected:'
90
+ watches.each do |w|
91
+ puts ' ' + w.name
92
+ end
93
+ rescue God::InvalidCommandError
94
+ abort "Command '#{command}' is not valid. Run 'god --help' for usage"
95
+ end
96
+
97
+ exit!
98
+ else
99
+ # start god
100
+ if !options[:daemonize]
101
+ require 'god'
102
+ load File.expand_path(options[:config])
103
+ else
104
+ pid = fork do
105
+ begin
106
+ require 'god'
107
+
108
+ log_file = options[:log] || "/dev/null"
109
+
110
+ STDIN.reopen "/dev/null"
111
+ STDOUT.reopen(log_file, "a")
112
+ STDERR.reopen STDOUT
113
+
114
+ puts "Starting god"
115
+
116
+ unless God::EventHandler.loaded?
117
+ puts
118
+ puts "***********************************************************************"
119
+ puts "*"
120
+ puts "* Event conditions are not available for your installation of god."
121
+ puts "* You may still use and write custom conditions using the poll system"
122
+ puts "*"
123
+ puts "***********************************************************************"
124
+ puts
125
+ end
126
+
127
+ puts "Resetting file descriptors"
128
+
129
+ puts "Loading config"
130
+
131
+ load File.expand_path(options[:config])
132
+ rescue => e
133
+ File.open('god.log', 'a') { |f| f.puts e.message + "\n" + e.backtrace }
134
+ abort "!!! ERROR !!!"
135
+ end
136
+ end
137
+
138
+ if options[:pid]
139
+ File.open(options[:pid], 'w') { |f| f.write pid }
140
+ end
141
+
142
+ ::Process.detach pid
143
+
144
+ exit!
145
+ end
26
146
  end
@@ -0,0 +1,52 @@
1
+ # This example shows how you might keep a local development Rails server up
2
+ # and running on your Mac.
3
+
4
+ # Run with:
5
+ # god -c /path/to/events.god
6
+
7
+ RAILS_ROOT = "/Users/tom/dev/helloworld"
8
+
9
+ God.watch do |w|
10
+ w.name = "local-3000"
11
+ w.interval = 5 # seconds
12
+ w.start = "mongrel_rails start -P ./log/mongrel.pid -c #{RAILS_ROOT} -d"
13
+ w.stop = "mongrel_rails stop -P ./log/mongrel.pid -c #{RAILS_ROOT}"
14
+ w.pid_file = File.join(RAILS_ROOT, "log/mongrel.pid")
15
+
16
+ # clean pid files before start if necessary
17
+ w.behavior(:clean_pid_file)
18
+
19
+ # determine the state on startup
20
+ w.transition(:init, { true => :up, false => :start }) do |on|
21
+ on.condition(:process_running) do |c|
22
+ c.running = true
23
+ end
24
+ end
25
+
26
+ # determine when process has finished starting
27
+ w.transition([:start, :restart], :up) do |on|
28
+ on.condition(:process_running) do |c|
29
+ c.running = true
30
+ end
31
+ end
32
+
33
+ # start if process is not running
34
+ w.transition(:up, :start) do |on|
35
+ on.condition(:process_exits)
36
+ end
37
+
38
+ # restart if memory or cpu is too high
39
+ w.transition(:up, :restart) do |on|
40
+ on.condition(:memory_usage) do |c|
41
+ c.interval = 20
42
+ c.above = (50 * 1024) # 50mb
43
+ c.times = [3, 5]
44
+ end
45
+
46
+ on.condition(:cpu_usage) do |c|
47
+ c.interval = 10
48
+ c.above = 10 # percent
49
+ c.times = [3, 5]
50
+ end
51
+ end
52
+ end
@@ -1,46 +1,40 @@
1
- # run with: god start -c /path/to/gravatar.god
1
+ # run with: god -c /path/to/gravatar.god
2
2
  #
3
3
  # This is the actual config file used to keep the mongrels of
4
4
  # gravatar.com running.
5
5
 
6
6
  RAILS_ROOT = "/var/www/gravatar2/current"
7
7
 
8
- God.meddle do |god|
9
- %w{8200 8201 8202}.each do |port|
10
- god.watch do |w|
11
- w.name = "gravatar2-mongrel-#{port}"
12
- w.interval = 30 # seconds
13
- w.start = "mongrel_rails cluster::start --only #{port} \
14
- -C #{RAILS_ROOT}/config/mongrel_cluster.yml"
15
- w.stop = "mongrel_rails cluster::stop --only #{port} \
16
- -C #{RAILS_ROOT}/config/mongrel_cluster.yml"
17
- w.grace = 10 # seconds
18
-
19
- pid_file = File.join(RAILS_ROOT, "log/mongrel.#{port}.pid")
20
-
21
- w.behavior(:clean_pid_file) do |b|
22
- b.pid_file = pid_file
23
- end
8
+ %w{8200 8201 8202}.each do |port|
9
+ God.watch do |w|
10
+ w.name = "gravatar2-mongrel-#{port}"
11
+ w.interval = 30 # seconds
12
+ w.start = "mongrel_rails cluster::start --only #{port} \
13
+ -C #{RAILS_ROOT}/config/mongrel_cluster.yml"
14
+ w.stop = "mongrel_rails cluster::stop --only #{port} \
15
+ -C #{RAILS_ROOT}/config/mongrel_cluster.yml"
16
+ w.grace = 10 # seconds
17
+
18
+ pid_file = File.join(RAILS_ROOT, "log/mongrel.#{port}.pid")
19
+
20
+ w.behavior(:clean_pid_file)
24
21
 
25
- w.start_if do |start|
26
- start.condition(:process_not_running) do |c|
27
- c.interval = 5 # seconds
28
- c.pid_file = pid_file
29
- end
22
+ w.start_if do |start|
23
+ start.condition(:process_running) do |c|
24
+ c.interval = 5 # seconds
25
+ c.running = false
26
+ end
27
+ end
28
+
29
+ w.restart_if do |restart|
30
+ restart.condition(:memory_usage) do |c|
31
+ c.above = (150 * 1024) # 150mb
32
+ c.times = [3, 5] # 3 out of 5 intervals
30
33
  end
31
-
32
- w.restart_if do |restart|
33
- restart.condition(:memory_usage) do |c|
34
- c.pid_file = pid_file
35
- c.above = (150 * 1024) # 150mb
36
- c.times = [3, 5] # 3 out of 5 intervals
37
- end
38
-
39
- restart.condition(:cpu_usage) do |c|
40
- c.pid_file = pid_file
41
- c.above = 50 # percent
42
- c.times = 5
43
- end
34
+
35
+ restart.condition(:cpu_usage) do |c|
36
+ c.above = 50 # percent
37
+ c.times = 5
44
38
  end
45
39
  end
46
40
  end
@@ -1,8 +1,55 @@
1
1
  require 'mkmf'
2
2
 
3
+ fail = false
4
+
5
+ def create_dummy_makefile
6
+ File.open("Makefile", 'w') do |f|
7
+ f.puts "all:"
8
+ f.puts "install:"
9
+ end
10
+ end
11
+
3
12
  case RUBY_PLATFORM
4
13
  when /bsd/i, /darwin/i
5
- create_makefile 'kqueue_handler_ext'
14
+ unless have_header('sys/event.h')
15
+ puts
16
+ puts "Missing 'sys/event.h' header"
17
+ fail = true
18
+ end
19
+
20
+ if fail
21
+ puts
22
+ puts "Events handler could not be compiled (see above error). Your god installation will not support event conditions."
23
+ create_dummy_makefile
24
+ else
25
+ create_makefile 'kqueue_handler_ext'
26
+ end
6
27
  when /linux/i
7
- create_makefile 'netlink_handler_ext'
28
+ unless have_header('linux/netlink.h')
29
+ puts
30
+ puts "Missing 'linux/netlink.h' header(s)"
31
+ puts "You may need to install a header package for your system"
32
+ fail = true
33
+ end
34
+
35
+ unless have_header('linux/connector.h') && have_header('linux/cn_proc.h')
36
+ puts
37
+ puts "Missing 'linux/connector.h', or 'linux/cn_proc.h' header(s)"
38
+ puts "These are only available in Linux kernel 2.6.15 and later (run `uname -a` to find yours)"
39
+ puts "You may need to install a header package for your system"
40
+ fail = true
41
+ end
42
+
43
+ if fail
44
+ puts
45
+ puts "Events handler could not be compiled (see above error). Your god installation will not support event conditions."
46
+ create_dummy_makefile
47
+ else
48
+ create_makefile 'netlink_handler_ext'
49
+ end
50
+ else
51
+ puts
52
+ puts "Unsupported platform '#{RUBY_PLATFORM}'. Supported platforms are BSD, DARWIN, and LINUX."
53
+ puts "Your god installation will not support event conditions."
54
+ create_dummy_makefile
8
55
  end