god 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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