god 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +14 -0
- data/Rakefile +42 -26
- data/ext/god/kqueue_handler.c +6 -4
- data/ext/god/netlink_handler.c +6 -6
- data/god.gemspec +127 -151
- data/lib/god.rb +26 -5
- data/lib/god/cli/command.rb +1 -1
- data/lib/god/cli/run.rb +5 -5
- data/lib/god/compat19.rb +36 -0
- data/lib/god/contacts/prowl.rb +77 -0
- data/lib/god/contacts/scout.rb +64 -0
- data/lib/god/driver.rb +5 -0
- data/lib/god/logger.rb +8 -29
- data/lib/god/process.rb +8 -2
- data/lib/god/simple_logger.rb +7 -1
- data/lib/god/socket.rb +13 -2
- data/lib/god/sys_logger.rb +45 -0
- data/lib/god/watch.rb +2 -1
- data/test/configs/contact/contact.god +7 -1
- data/test/configs/task/logs/.placeholder +0 -0
- data/test/helper.rb +2 -1
- data/test/test_behavior.rb +1 -1
- data/test/test_logger.rb +1 -1
- data/test/test_prowl.rb +15 -0
- metadata +6 -27
- data/.gitignore +0 -8
- data/VERSION.yml +0 -5
- data/ideas/execve/execve.c +0 -29
- data/ideas/execve/extconf.rb +0 -11
- data/ideas/execve/go.rb +0 -8
- data/ideas/future.god +0 -82
- data/init/god +0 -42
- data/init/lsb_compliant_god +0 -109
- data/site/images/banner.jpg +0 -0
- data/site/images/bg.gif +0 -0
- data/site/images/bg_grey.gif +0 -0
- data/site/images/bullet.jpg +0 -0
- data/site/images/corner_green.gif +0 -0
- data/site/images/corner_green.psd +0 -0
- data/site/images/corner_pink.gif +0 -0
- data/site/images/god_logo.png +0 -0
- data/site/images/header_bg.gif +0 -0
- data/site/images/header_bg.jpg +0 -0
- data/site/images/red_dot.gif +0 -0
- data/site/images/top_bg.gif +0 -0
- data/site/index.html +0 -563
- data/site/install.html +0 -2
- data/site/javascripts/code_highlighter.js +0 -188
- data/site/javascripts/ruby.js +0 -18
- data/site/stylesheets/layout.css +0 -174
@@ -0,0 +1,45 @@
|
|
1
|
+
begin
|
2
|
+
require 'syslog'
|
3
|
+
|
4
|
+
# Ensure that Syslog is open
|
5
|
+
begin
|
6
|
+
Syslog.open('god')
|
7
|
+
rescue RuntimeError
|
8
|
+
Syslog.reopen('god')
|
9
|
+
end
|
10
|
+
|
11
|
+
Syslog.info("Syslog enabled.")
|
12
|
+
|
13
|
+
module God
|
14
|
+
|
15
|
+
class SysLogger
|
16
|
+
SYMBOL_EQUIVALENTS = { :fatal => Syslog::LOG_CRIT,
|
17
|
+
:error => Syslog::LOG_ERR,
|
18
|
+
:warn => Syslog::LOG_WARNING,
|
19
|
+
:info => Syslog::LOG_INFO,
|
20
|
+
:debug => Syslog::LOG_DEBUG }
|
21
|
+
|
22
|
+
# Set the log level
|
23
|
+
# +level+ is the Symbol level to set as maximum. One of:
|
24
|
+
# [:fatal | :error | :warn | :info | :debug ]
|
25
|
+
#
|
26
|
+
# Returns Nothing
|
27
|
+
def self.level=(level)
|
28
|
+
Syslog.mask = Syslog::LOG_UPTO(SYMBOL_EQUIVALENTS[level])
|
29
|
+
end
|
30
|
+
|
31
|
+
# Log a message to syslog.
|
32
|
+
# +level+ is the Symbol level of the message. One of:
|
33
|
+
# [:fatal | :error | :warn | :info | :debug ]
|
34
|
+
# +text+ is the String text of the message
|
35
|
+
#
|
36
|
+
# Returns Nothing
|
37
|
+
def self.log(level, text)
|
38
|
+
Syslog.log(SYMBOL_EQUIVALENTS[level], text)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
rescue Object => e
|
44
|
+
puts "Syslog could not be enabled: #{e.message}"
|
45
|
+
end
|
data/lib/god/watch.rb
CHANGED
@@ -13,7 +13,8 @@ module God
|
|
13
13
|
extend Forwardable
|
14
14
|
def_delegators :@process, :name, :uid, :gid, :start, :stop, :restart, :dir,
|
15
15
|
:name=, :uid=, :gid=, :start=, :stop=, :restart=, :dir=,
|
16
|
-
:pid_file, :pid_file=, :log, :log=, :log_cmd, :log_cmd=,
|
16
|
+
:pid_file, :pid_file=, :log, :log=, :log_cmd, :log_cmd=,
|
17
|
+
:err_log, :err_log=, :err_log_cmd, :err_log_cmd=, :alive?, :pid,
|
17
18
|
:unix_socket, :unix_socket=, :chroot, :chroot=, :env, :env=, :signal
|
18
19
|
#
|
19
20
|
def initialize
|
@@ -36,6 +36,12 @@ God.contact(:twitter) do |c|
|
|
36
36
|
c.group = 'developers'
|
37
37
|
end
|
38
38
|
|
39
|
+
God.contact(:prowl) do |c|
|
40
|
+
c.name = 'tom3'
|
41
|
+
c.apikey = 'd31c1f31f7af0f69e263c2f12167263127eab608'
|
42
|
+
c.group = 'developers'
|
43
|
+
end
|
44
|
+
|
39
45
|
God.watch do |w|
|
40
46
|
w.name = "contact"
|
41
47
|
w.interval = 5.seconds
|
@@ -65,7 +71,7 @@ God.watch do |w|
|
|
65
71
|
# start if process is not running
|
66
72
|
w.transition(:up, :start) do |on|
|
67
73
|
on.condition(:process_exits) do |c|
|
68
|
-
c.notify = {:contacts => ['tom2', 'foobar'], :priority => 1, :category => 'product'}
|
74
|
+
c.notify = {:contacts => ['tom2', 'tom3', 'foobar'], :priority => 1, :category => 'product'}
|
69
75
|
end
|
70
76
|
end
|
71
77
|
|
File without changes
|
data/test/helper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require File.join(File.dirname(__FILE__), *%w[.. lib god sys_logger])
|
2
3
|
require File.join(File.dirname(__FILE__), *%w[.. lib god])
|
3
4
|
God::EventHandler.load
|
4
5
|
|
@@ -122,7 +123,7 @@ end
|
|
122
123
|
class Object
|
123
124
|
class Bypass
|
124
125
|
instance_methods.each do |m|
|
125
|
-
undef_method m unless m =~ /^__/
|
126
|
+
undef_method m unless m =~ /^(__|object_id)/
|
126
127
|
end
|
127
128
|
|
128
129
|
def initialize(ref)
|
data/test/test_behavior.rb
CHANGED
data/test/test_logger.rb
CHANGED
data/test/test_prowl.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.dirname(__FILE__) + '/helper'
|
3
|
+
|
4
|
+
class TestProwl < Test::Unit::TestCase
|
5
|
+
def test_live_notify
|
6
|
+
prowl = God::Contacts::Prowl.new
|
7
|
+
prowl.name = "Prowly"
|
8
|
+
prowl.apikey = 'put_your_apikey_here'
|
9
|
+
|
10
|
+
Prowly.expects(:notify).returns(mock(:succeeded? => true))
|
11
|
+
|
12
|
+
prowl.notify("Test", Time.now, "Test", "Test", "")
|
13
|
+
assert_equal "sent prowl notification to #{prowl.name}", prowl.info
|
14
|
+
end
|
15
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: god
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Preston-Werner
|
@@ -23,12 +23,10 @@ extensions:
|
|
23
23
|
extra_rdoc_files:
|
24
24
|
- README.txt
|
25
25
|
files:
|
26
|
-
- .gitignore
|
27
26
|
- Announce.txt
|
28
27
|
- History.txt
|
29
28
|
- README.txt
|
30
29
|
- Rakefile
|
31
|
-
- VERSION.yml
|
32
30
|
- bin/god
|
33
31
|
- examples/events.god
|
34
32
|
- examples/gravatar.god
|
@@ -38,13 +36,6 @@ files:
|
|
38
36
|
- ext/god/kqueue_handler.c
|
39
37
|
- ext/god/netlink_handler.c
|
40
38
|
- god.gemspec
|
41
|
-
- ideas/execve/.DS_Store
|
42
|
-
- ideas/execve/execve.c
|
43
|
-
- ideas/execve/extconf.rb
|
44
|
-
- ideas/execve/go.rb
|
45
|
-
- ideas/future.god
|
46
|
-
- init/god
|
47
|
-
- init/lsb_compliant_god
|
48
39
|
- lib/god.rb
|
49
40
|
- lib/god/behavior.rb
|
50
41
|
- lib/god/behaviors/clean_pid_file.rb
|
@@ -53,6 +44,7 @@ files:
|
|
53
44
|
- lib/god/cli/command.rb
|
54
45
|
- lib/god/cli/run.rb
|
55
46
|
- lib/god/cli/version.rb
|
47
|
+
- lib/god/compat19.rb
|
56
48
|
- lib/god/condition.rb
|
57
49
|
- lib/god/conditions/always.rb
|
58
50
|
- lib/god/conditions/complex.rb
|
@@ -72,6 +64,8 @@ files:
|
|
72
64
|
- lib/god/contacts/campfire.rb
|
73
65
|
- lib/god/contacts/email.rb
|
74
66
|
- lib/god/contacts/jabber.rb
|
67
|
+
- lib/god/contacts/prowl.rb
|
68
|
+
- lib/god/contacts/scout.rb
|
75
69
|
- lib/god/contacts/twitter.rb
|
76
70
|
- lib/god/contacts/webhook.rb
|
77
71
|
- lib/god/dependency_graph.rb
|
@@ -89,6 +83,7 @@ files:
|
|
89
83
|
- lib/god/simple_logger.rb
|
90
84
|
- lib/god/socket.rb
|
91
85
|
- lib/god/sugar.rb
|
86
|
+
- lib/god/sys_logger.rb
|
92
87
|
- lib/god/system/portable_poller.rb
|
93
88
|
- lib/god/system/process.rb
|
94
89
|
- lib/god/system/slash_proc_poller.rb
|
@@ -96,23 +91,6 @@ files:
|
|
96
91
|
- lib/god/timeline.rb
|
97
92
|
- lib/god/trigger.rb
|
98
93
|
- lib/god/watch.rb
|
99
|
-
- site/images/banner.jpg
|
100
|
-
- site/images/bg.gif
|
101
|
-
- site/images/bg_grey.gif
|
102
|
-
- site/images/bullet.jpg
|
103
|
-
- site/images/corner_green.gif
|
104
|
-
- site/images/corner_green.psd
|
105
|
-
- site/images/corner_pink.gif
|
106
|
-
- site/images/god_logo.png
|
107
|
-
- site/images/header_bg.gif
|
108
|
-
- site/images/header_bg.jpg
|
109
|
-
- site/images/red_dot.gif
|
110
|
-
- site/images/top_bg.gif
|
111
|
-
- site/index.html
|
112
|
-
- site/install.html
|
113
|
-
- site/javascripts/code_highlighter.js
|
114
|
-
- site/javascripts/ruby.js
|
115
|
-
- site/stylesheets/layout.css
|
116
94
|
- test/configs/child_events/child_events.god
|
117
95
|
- test/configs/child_events/simple_server.rb
|
118
96
|
- test/configs/child_polls/child_polls.god
|
@@ -157,6 +135,7 @@ files:
|
|
157
135
|
- test/test_logger.rb
|
158
136
|
- test/test_metric.rb
|
159
137
|
- test/test_process.rb
|
138
|
+
- test/test_prowl.rb
|
160
139
|
- test/test_registry.rb
|
161
140
|
- test/test_socket.rb
|
162
141
|
- test/test_sugar.rb
|
data/.gitignore
DELETED
data/VERSION.yml
DELETED
data/ideas/execve/execve.c
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#include "ruby.h"
|
2
|
-
|
3
|
-
static VALUE mKernel;
|
4
|
-
void Init_execve();
|
5
|
-
VALUE method_execve(VALUE self, VALUE cmd, VALUE env);
|
6
|
-
|
7
|
-
void Init_execve() {
|
8
|
-
mKernel = rb_const_get(rb_cObject, rb_intern("Kernel"));
|
9
|
-
rb_define_method(mKernel, "execve", method_execve, 2);
|
10
|
-
}
|
11
|
-
|
12
|
-
VALUE method_execve(VALUE self, VALUE r_cmd, VALUE r_env) {
|
13
|
-
char *shell = (char *)dln_find_exe("sh", 0);
|
14
|
-
char *arg[] = { "sh", "-c", StringValuePtr(r_cmd), (char *)0 };
|
15
|
-
|
16
|
-
struct RArray *env_array;
|
17
|
-
env_array = RARRAY(r_env);
|
18
|
-
char *env[env_array->len + 1];
|
19
|
-
|
20
|
-
int i;
|
21
|
-
for(i = 0; i < env_array->len; i++) {
|
22
|
-
env[i] = StringValuePtr(env_array->ptr[i]);
|
23
|
-
}
|
24
|
-
|
25
|
-
env[env_array->len] = (char *)0;
|
26
|
-
|
27
|
-
execve(shell, arg, env);
|
28
|
-
return Qnil;
|
29
|
-
}
|
data/ideas/execve/extconf.rb
DELETED
data/ideas/execve/go.rb
DELETED
data/ideas/future.god
DELETED
@@ -1,82 +0,0 @@
|
|
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::Contacts::Email.delivery_method = :smtp
|
10
|
-
God::Contacts::Email.server_settings = {}
|
11
|
-
|
12
|
-
God.contact(:email) do |c|
|
13
|
-
c.name = 'tom'
|
14
|
-
c.email = 'tom@powerset.com'
|
15
|
-
c.group = 'developers'
|
16
|
-
c.throttle = 30.minutes
|
17
|
-
end
|
18
|
-
|
19
|
-
God.watch do |w|
|
20
|
-
w.name = "local-3000"
|
21
|
-
w.interval = 5.seconds
|
22
|
-
w.start = "mongrel_rails start -P ./log/mongrel.pid -c #{RAILS_ROOT} -d"
|
23
|
-
w.stop = "mongrel_rails stop -P ./log/mongrel.pid -c #{RAILS_ROOT}"
|
24
|
-
w.pid_file = File.join(RAILS_ROOT, "log/mongrel.pid")
|
25
|
-
|
26
|
-
# clean pid files before start if necessary
|
27
|
-
w.behavior(:clean_pid_file)
|
28
|
-
|
29
|
-
# determine the state on startup
|
30
|
-
w.transition(:init, { true => :up, false => :start }) do |on|
|
31
|
-
on.condition(:process_running) do |c|
|
32
|
-
c.running = true
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# determine when process has finished starting
|
37
|
-
w.transition([:start, :restart], :up) do |on|
|
38
|
-
on.condition(:process_running) do |c|
|
39
|
-
c.running = true
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
# start if process is not running
|
44
|
-
w.transition(:up, :start) do |on|
|
45
|
-
on.condition(:process_exits)
|
46
|
-
end
|
47
|
-
|
48
|
-
# restart if memory or cpu is too high
|
49
|
-
w.transition(:up, :restart) do |on|
|
50
|
-
on.condition(:memory_usage) do |c|
|
51
|
-
c.interval = 20
|
52
|
-
c.above = 50.megabytes
|
53
|
-
c.times = [3, 5]
|
54
|
-
end
|
55
|
-
|
56
|
-
on.condition(:cpu_usage) do |c|
|
57
|
-
c.interval = 10
|
58
|
-
c.above = 10.percent
|
59
|
-
c.times = [3, 5]
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# lifecycle
|
64
|
-
w.lifecycle do |on|
|
65
|
-
on.condition(:flapping) do |c|
|
66
|
-
c.to_state = [:start, :restart]
|
67
|
-
c.times = 5
|
68
|
-
c.within = 30.seconds
|
69
|
-
c.transition = nil
|
70
|
-
c.retry = 60.seconds
|
71
|
-
c.giveup_tries = 5
|
72
|
-
c.notify = 'tom'
|
73
|
-
end
|
74
|
-
|
75
|
-
on.condition(:memory_usage) do |c|
|
76
|
-
c.interval = 20
|
77
|
-
c.above = 40.megabytes
|
78
|
-
c.times = [3, 5]
|
79
|
-
c.notify = 'tom'
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
data/init/god
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
#!/bin/bash
|
2
|
-
#
|
3
|
-
# god Startup script for god (http://god.rubyforge.org)
|
4
|
-
#
|
5
|
-
# chkconfig: - 85 15
|
6
|
-
# description: God is an easy to configure, easy to extend monitoring \
|
7
|
-
# framework written in Ruby.
|
8
|
-
#
|
9
|
-
|
10
|
-
CONF_DIR=/etc/god
|
11
|
-
|
12
|
-
RETVAL=0
|
13
|
-
|
14
|
-
# Go no further if config directory is missing.
|
15
|
-
[ -d "$CONF_DIR" ] || exit 0
|
16
|
-
|
17
|
-
case "$1" in
|
18
|
-
start)
|
19
|
-
# Create pid directory
|
20
|
-
ruby /usr/bin/god -c $CONF_DIR/master.conf
|
21
|
-
RETVAL=$?
|
22
|
-
;;
|
23
|
-
stop)
|
24
|
-
ruby /usr/bin/god terminate
|
25
|
-
RETVAL=$?
|
26
|
-
;;
|
27
|
-
restart)
|
28
|
-
ruby /usr/bin/god terminate
|
29
|
-
ruby /usr/bin/god -c $CONF_DIR/master.conf
|
30
|
-
RETVAL=$?
|
31
|
-
;;
|
32
|
-
status)
|
33
|
-
ruby /usr/bin/god status
|
34
|
-
RETVAL=$?
|
35
|
-
;;
|
36
|
-
*)
|
37
|
-
echo "Usage: god {start|stop|restart|status}"
|
38
|
-
exit 1
|
39
|
-
;;
|
40
|
-
esac
|
41
|
-
|
42
|
-
exit $RETVAL
|
data/init/lsb_compliant_god
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# see http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
|
4
|
-
|
5
|
-
PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
|
6
|
-
DESC="god daemon"
|
7
|
-
NAME="god"
|
8
|
-
DAEMON="/usr/bin/#{NAME}"
|
9
|
-
CONFIGFILE="/etc/god/god.conf"
|
10
|
-
PIDFILE="/var/run/#{NAME}.pid"
|
11
|
-
SCRIPTNAME="/etc/init.d/#{NAME}"
|
12
|
-
START_FLAGS="--no-syslog -P #{PIDFILE}"
|
13
|
-
|
14
|
-
ENV["PATH"] = PATH
|
15
|
-
|
16
|
-
def read_pid
|
17
|
-
begin
|
18
|
-
@pid = File.read(PIDFILE).to_i
|
19
|
-
@pid = nil if @pid == 0
|
20
|
-
rescue
|
21
|
-
@pid = nil
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def kill(code)
|
26
|
-
Process.kill(code, @pid)
|
27
|
-
true
|
28
|
-
rescue
|
29
|
-
false
|
30
|
-
end
|
31
|
-
|
32
|
-
def running?
|
33
|
-
@pid && kill(0)
|
34
|
-
end
|
35
|
-
|
36
|
-
def dead?
|
37
|
-
@pid && !kill(0)
|
38
|
-
end
|
39
|
-
|
40
|
-
def start
|
41
|
-
if running?
|
42
|
-
puts "already running (#{@pid})"
|
43
|
-
exit
|
44
|
-
end
|
45
|
-
|
46
|
-
if dead?
|
47
|
-
clean_pid
|
48
|
-
end
|
49
|
-
|
50
|
-
puts "starting #{NAME}"
|
51
|
-
system("#{DAEMON} -c #{CONFIGFILE} #{START_FLAGS}")
|
52
|
-
end
|
53
|
-
|
54
|
-
def stop
|
55
|
-
if not running?
|
56
|
-
puts "not running"
|
57
|
-
exit
|
58
|
-
end
|
59
|
-
|
60
|
-
system("god quit")
|
61
|
-
end
|
62
|
-
|
63
|
-
def restart
|
64
|
-
if running?
|
65
|
-
stop
|
66
|
-
read_pid
|
67
|
-
end
|
68
|
-
start
|
69
|
-
end
|
70
|
-
|
71
|
-
def force_reload
|
72
|
-
if running?
|
73
|
-
restart
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def clean_pid
|
78
|
-
File.delete(PIDFILE)
|
79
|
-
end
|
80
|
-
|
81
|
-
read_pid
|
82
|
-
case ARGV[0]
|
83
|
-
when 'start'
|
84
|
-
start
|
85
|
-
when 'stop'
|
86
|
-
stop
|
87
|
-
when 'restart'
|
88
|
-
if not running?
|
89
|
-
start
|
90
|
-
else
|
91
|
-
restart
|
92
|
-
end
|
93
|
-
when 'force-reload'
|
94
|
-
force_reload
|
95
|
-
when 'status'
|
96
|
-
if running?
|
97
|
-
puts "running (#{@pid})"
|
98
|
-
elsif dead?
|
99
|
-
puts "dead (#{@pid})"
|
100
|
-
exit!(1)
|
101
|
-
else
|
102
|
-
puts "not running"
|
103
|
-
exit!(3)
|
104
|
-
end
|
105
|
-
else
|
106
|
-
puts "Usage: #{SCRIPTNAME} start|stop|restart|force-reload|status"
|
107
|
-
end
|
108
|
-
|
109
|
-
exit
|