reel-eye 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGES.md +6 -0
- data/README.md +44 -32
- data/examples/puma.eye +1 -1
- data/examples/test.eye +32 -30
- data/examples/unicorn.eye +1 -1
- data/lib/eye.rb +1 -1
- data/lib/eye/checker.rb +24 -1
- data/lib/eye/checker/cpu.rb +4 -14
- data/lib/eye/checker/cputime.rb +2 -12
- data/lib/eye/checker/file_ctime.rb +2 -3
- data/lib/eye/checker/file_size.rb +8 -8
- data/lib/eye/checker/http.rb +2 -2
- data/lib/eye/checker/memory.rb +4 -14
- data/lib/eye/checker/runtime.rb +2 -12
- data/lib/eye/checker/socket.rb +1 -1
- data/lib/eye/cli.rb +6 -0
- data/lib/eye/cli/commands.rb +2 -3
- data/lib/eye/cli/render.rb +4 -4
- data/lib/eye/cli/server.rb +4 -4
- data/lib/eye/controller.rb +1 -1
- data/lib/eye/controller/load.rb +14 -13
- data/lib/eye/controller/send_command.rb +4 -4
- data/lib/eye/controller/status.rb +2 -1
- data/lib/eye/dsl.rb +1 -1
- data/lib/eye/dsl/child_process_opts.rb +2 -2
- data/lib/eye/dsl/opts.rb +5 -1
- data/lib/eye/dsl/validation.rb +2 -2
- data/lib/eye/group/chain.rb +2 -2
- data/lib/eye/notify.rb +3 -3
- data/lib/eye/process.rb +7 -7
- data/lib/eye/process/children.rb +60 -0
- data/lib/eye/process/commands.rb +40 -37
- data/lib/eye/process/config.rb +5 -5
- data/lib/eye/process/controller.rb +8 -8
- data/lib/eye/process/data.rb +4 -4
- data/lib/eye/process/monitor.rb +17 -17
- data/lib/eye/process/scheduler.rb +1 -1
- data/lib/eye/process/states.rb +3 -3
- data/lib/eye/process/system.rb +3 -3
- data/lib/eye/process/validate.rb +1 -1
- data/lib/eye/process/watchers.rb +6 -6
- data/lib/eye/server.rb +1 -1
- data/lib/eye/system.rb +4 -4
- data/lib/eye/system_resources.rb +3 -3
- data/lib/eye/trigger.rb +4 -6
- data/lib/eye/trigger/flapping.rb +2 -2
- data/lib/eye/trigger/stop_children.rb +14 -0
- metadata +4 -4
- data/lib/eye/process/child.rb +0 -60
- data/lib/eye/trigger/stop_childs.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8d7151c4d07968c95923d5e03e98479d9c5e2d2
|
4
|
+
data.tar.gz: 107ec65c2f5698d6402335517c5959d7a7599c36
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a76c23dca14051ce14bf3f2d20c101cfdd0a8490b0afe81e8c83f2f54fc2bd06604be27de462b07de5f6ef7bbe8ce2b54e024a1f3eeca3e5719594997c753ba8
|
7
|
+
data.tar.gz: 331eccf87ef153b6c0241f9b5963a597bc1f28c5584e873633c80a2721b79c29dd01cfd6097eca2f73e6121b690a023ea6b1d828242ec0f0e5178d3e0c41ba15
|
data/.gitignore
CHANGED
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -16,69 +16,81 @@ Recommended installation on the server (system wide):
|
|
16
16
|
$ sudo ln -sf /usr/local/ruby/1.9.3/bin/eye /usr/local/bin/eye
|
17
17
|
|
18
18
|
|
19
|
-
|
19
|
+
### Why?
|
20
|
+
|
21
|
+
We have used god and bluepill in production and always ran into bugs (segfaults, crashes, lost processes, kill not-related processes, load problems, deploy problems, ...)
|
22
|
+
|
23
|
+
We wanted something more robust and production stable.
|
24
|
+
|
25
|
+
We wanted the features of bluepill and god, with a few extras like chains, nested configuring, mask matching, easy debug configs
|
26
|
+
|
27
|
+
I hope we've success, we're using eye in production and are quite happy.
|
28
|
+
|
29
|
+
### Config example
|
20
30
|
|
21
31
|
examples/test.eye
|
22
32
|
```ruby
|
23
33
|
# load submodules, here just for example
|
24
|
-
Eye.load(
|
34
|
+
Eye.load('./eye/*.rb')
|
25
35
|
|
26
36
|
# Eye self-configuration section
|
27
37
|
Eye.config do
|
28
|
-
logger
|
38
|
+
logger '/tmp/eye.log'
|
29
39
|
end
|
30
40
|
|
31
41
|
# Adding application
|
32
|
-
Eye.application
|
42
|
+
Eye.application 'test' do
|
33
43
|
# All options inherits down to the config leafs.
|
34
44
|
# except `env`, which merging down
|
35
45
|
|
36
46
|
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
37
|
-
stdall
|
38
|
-
env
|
39
|
-
trigger :flapping, :
|
40
|
-
check :cpu, :below
|
47
|
+
stdall 'trash.log' # stdout,err logs for processes by default
|
48
|
+
env 'APP_ENV' => 'production' # global env for each processes
|
49
|
+
trigger :flapping, times: 10, within: 1.minute, retry_in: 10.minutes
|
50
|
+
check :cpu, every: 10.seconds, below: 100, times: 3 # global check for all processes
|
41
51
|
|
42
|
-
group
|
43
|
-
chain :
|
52
|
+
group 'samples' do
|
53
|
+
chain grace: 5.seconds # chained start-restart with 5s interval, one by one.
|
44
54
|
|
45
55
|
# eye daemonized process
|
46
56
|
process :sample1 do
|
47
|
-
pid_file
|
48
|
-
start_command
|
57
|
+
pid_file '1.pid' # pid_path will be expanded with the working_dir
|
58
|
+
start_command 'ruby ./sample.rb'
|
49
59
|
|
50
60
|
# when no stop_command or stop_signals, default stop is [:TERM, 0.5, :KILL]
|
51
61
|
# default `restart` command is `stop; start`
|
52
62
|
|
53
63
|
daemonize true
|
54
|
-
stdall
|
64
|
+
stdall 'sample1.log'
|
55
65
|
|
56
|
-
|
66
|
+
# ensure the CPU is below 30% at least 3 out of the last 5 times checked
|
67
|
+
check :cpu, below: 30, times: [3, 5]
|
57
68
|
end
|
58
69
|
|
59
70
|
# self daemonized process
|
60
71
|
process :sample2 do
|
61
|
-
pid_file
|
62
|
-
start_command
|
63
|
-
stop_command
|
72
|
+
pid_file '2.pid'
|
73
|
+
start_command 'ruby ./sample.rb -d --pid 2.pid --log sample2.log'
|
74
|
+
stop_command 'kill -9 {PID}'
|
64
75
|
|
65
|
-
|
76
|
+
# ensure the memory is below 300Mb the last 3 times checked
|
77
|
+
check :memory, every: 20.seconds, below: 300.megabytes, times: 3
|
66
78
|
end
|
67
79
|
end
|
68
80
|
|
69
|
-
# daemon with 3
|
81
|
+
# daemon with 3 children
|
70
82
|
process :forking do
|
71
|
-
pid_file
|
72
|
-
start_command
|
73
|
-
stop_command
|
74
|
-
stdall
|
83
|
+
pid_file 'forking.pid'
|
84
|
+
start_command 'ruby ./forking.rb start'
|
85
|
+
stop_command 'ruby forking.rb stop'
|
86
|
+
stdall 'forking.log'
|
75
87
|
|
76
88
|
start_timeout 10.seconds
|
77
89
|
stop_timeout 5.seconds
|
78
90
|
|
79
91
|
monitor_children do
|
80
|
-
restart_command
|
81
|
-
check :memory, :
|
92
|
+
restart_command 'kill -2 {PID}' # for this child process
|
93
|
+
check :memory, below: 300.megabytes, times: 3
|
82
94
|
end
|
83
95
|
end
|
84
96
|
|
@@ -90,18 +102,18 @@ Eye.application "test" do
|
|
90
102
|
daemonize true
|
91
103
|
stop_signals [:QUIT, 2.seconds, :KILL]
|
92
104
|
|
93
|
-
check :socket, :
|
94
|
-
:
|
105
|
+
check :socket, addr: 'tcp://127.0.0.1:33221', every: 10.seconds, times: 2,
|
106
|
+
timeout: 1.second, send_data: 'ping', expect_data: /pong/
|
95
107
|
end
|
96
108
|
|
97
109
|
# thin process, self daemonized
|
98
110
|
process :thin do
|
99
|
-
pid_file
|
100
|
-
start_command
|
111
|
+
pid_file 'thin.pid'
|
112
|
+
start_command 'bundle exec thin start -R thin.ru -p 33233 -d -l thin.log -P thin.pid'
|
101
113
|
stop_signals [:QUIT, 2.seconds, :TERM, 1.seconds, :KILL]
|
102
114
|
|
103
|
-
check :http, :
|
104
|
-
:
|
115
|
+
check :http, url: 'http://127.0.0.1:33233/hello', pattern: /World/,
|
116
|
+
every: 5.seconds, times: [2, 3], timeout: 1.second
|
105
117
|
end
|
106
118
|
|
107
119
|
end
|
@@ -120,7 +132,7 @@ foreground load:
|
|
120
132
|
|
121
133
|
$ eye l CONF -f
|
122
134
|
|
123
|
-
If eye daemon already started and you call `load` command, config will be updated (into eye daemon). New objects(applications, groups, processes) will be added and monitored.
|
135
|
+
If the eye daemon has already started and you call the `load` command, the config will be updated (into eye daemon). New objects(applications, groups, processes) will be added and monitored. Processes removed from the config will be removed (and stopped if the process has `stop_on_delete true`). Other objects will update their configs.
|
124
136
|
|
125
137
|
|
126
138
|
Process statuses:
|
data/examples/puma.eye
CHANGED
@@ -18,7 +18,7 @@ Eye.application :puma do
|
|
18
18
|
|
19
19
|
start_command "#{BUNDLE} exec puma --port 33280 --environment #{RAILS_ENV} thin.ru"
|
20
20
|
stop_signals [:TERM, 5.seconds, :KILL]
|
21
|
-
restart_command "kill -USR2 {
|
21
|
+
restart_command "kill -USR2 {PID}"
|
22
22
|
|
23
23
|
restart_grace 10.seconds # just sleep this until process get up status
|
24
24
|
# (maybe enought to puma soft restart)
|
data/examples/test.eye
CHANGED
@@ -1,62 +1,64 @@
|
|
1
1
|
# load submodules, here just for example
|
2
|
-
Eye.load(
|
2
|
+
Eye.load('./eye/*.rb')
|
3
3
|
|
4
4
|
# Eye self-configuration section
|
5
5
|
Eye.config do
|
6
|
-
logger
|
6
|
+
logger '/tmp/eye.log'
|
7
7
|
end
|
8
8
|
|
9
9
|
# Adding application
|
10
|
-
Eye.application
|
10
|
+
Eye.application 'test' do
|
11
11
|
# All options inherits down to the config leafs.
|
12
12
|
# except `env`, which merging down
|
13
13
|
|
14
14
|
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
15
|
-
stdall
|
16
|
-
env
|
17
|
-
trigger :flapping, :
|
18
|
-
check :cpu, :below
|
15
|
+
stdall 'trash.log' # stdout,err logs for processes by default
|
16
|
+
env 'APP_ENV' => 'production' # global env for each processes
|
17
|
+
trigger :flapping, times: 10, within: 1.minute, retry_in: 10.minutes
|
18
|
+
check :cpu, every: 10.seconds, below: 100, times: 3 # global check for all processes
|
19
19
|
|
20
|
-
group
|
21
|
-
chain :
|
20
|
+
group 'samples' do
|
21
|
+
chain grace: 5.seconds # chained start-restart with 5s interval, one by one.
|
22
22
|
|
23
23
|
# eye daemonized process
|
24
24
|
process :sample1 do
|
25
|
-
pid_file
|
26
|
-
start_command
|
25
|
+
pid_file '1.pid' # pid_path will be expanded with the working_dir
|
26
|
+
start_command 'ruby ./sample.rb'
|
27
27
|
|
28
28
|
# when no stop_command or stop_signals, default stop is [:TERM, 0.5, :KILL]
|
29
29
|
# default `restart` command is `stop; start`
|
30
30
|
|
31
31
|
daemonize true
|
32
|
-
stdall
|
32
|
+
stdall 'sample1.log'
|
33
33
|
|
34
|
-
|
34
|
+
# ensure the CPU is below 30% at least 3 out of the last 5 times checked
|
35
|
+
check :cpu, below: 30, times: [3, 5]
|
35
36
|
end
|
36
37
|
|
37
38
|
# self daemonized process
|
38
39
|
process :sample2 do
|
39
|
-
pid_file
|
40
|
-
start_command
|
41
|
-
stop_command
|
40
|
+
pid_file '2.pid'
|
41
|
+
start_command 'ruby ./sample.rb -d --pid 2.pid --log sample2.log'
|
42
|
+
stop_command 'kill -9 {PID}'
|
42
43
|
|
43
|
-
|
44
|
+
# ensure the memory is below 300Mb the last 3 times checked
|
45
|
+
check :memory, every: 20.seconds, below: 300.megabytes, times: 3
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
47
|
-
# daemon with 3
|
49
|
+
# daemon with 3 children
|
48
50
|
process :forking do
|
49
|
-
pid_file
|
50
|
-
start_command
|
51
|
-
stop_command
|
52
|
-
stdall
|
51
|
+
pid_file 'forking.pid'
|
52
|
+
start_command 'ruby ./forking.rb start'
|
53
|
+
stop_command 'ruby forking.rb stop'
|
54
|
+
stdall 'forking.log'
|
53
55
|
|
54
56
|
start_timeout 10.seconds
|
55
57
|
stop_timeout 5.seconds
|
56
58
|
|
57
59
|
monitor_children do
|
58
|
-
restart_command
|
59
|
-
check :memory, :
|
60
|
+
restart_command 'kill -2 {PID}' # for this child process
|
61
|
+
check :memory, below: 300.megabytes, times: 3
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
@@ -68,18 +70,18 @@ Eye.application "test" do
|
|
68
70
|
daemonize true
|
69
71
|
stop_signals [:QUIT, 2.seconds, :KILL]
|
70
72
|
|
71
|
-
check :socket, :
|
72
|
-
:
|
73
|
+
check :socket, addr: 'tcp://127.0.0.1:33221', every: 10.seconds, times: 2,
|
74
|
+
timeout: 1.second, send_data: 'ping', expect_data: /pong/
|
73
75
|
end
|
74
76
|
|
75
77
|
# thin process, self daemonized
|
76
78
|
process :thin do
|
77
|
-
pid_file
|
78
|
-
start_command
|
79
|
+
pid_file 'thin.pid'
|
80
|
+
start_command 'bundle exec thin start -R thin.ru -p 33233 -d -l thin.log -P thin.pid'
|
79
81
|
stop_signals [:QUIT, 2.seconds, :TERM, 1.seconds, :KILL]
|
80
82
|
|
81
|
-
check :http, :
|
82
|
-
:
|
83
|
+
check :http, url: 'http://127.0.0.1:33233/hello', pattern: /World/,
|
84
|
+
every: 5.seconds, times: [2, 3], timeout: 1.second
|
83
85
|
end
|
84
86
|
|
85
87
|
end
|
data/examples/unicorn.eye
CHANGED
data/lib/eye.rb
CHANGED
data/lib/eye/checker.rb
CHANGED
@@ -131,7 +131,7 @@ class Eye::Checker
|
|
131
131
|
end
|
132
132
|
|
133
133
|
def get_value
|
134
|
-
raise
|
134
|
+
raise NotImplementedError
|
135
135
|
end
|
136
136
|
|
137
137
|
def human_value(value)
|
@@ -220,4 +220,27 @@ class Eye::Checker
|
|
220
220
|
register(base)
|
221
221
|
end
|
222
222
|
end
|
223
|
+
|
224
|
+
class Measure < Eye::Checker
|
225
|
+
param :below, [Fixnum, Float]
|
226
|
+
param :above, [Fixnum, Float]
|
227
|
+
|
228
|
+
def good?(value)
|
229
|
+
return false if below && (value > below)
|
230
|
+
return false if above && (value < above)
|
231
|
+
true
|
232
|
+
end
|
233
|
+
|
234
|
+
def measure_str
|
235
|
+
if below && above
|
236
|
+
">#{human_value(above)}<#{human_value(below)}"
|
237
|
+
elsif below
|
238
|
+
"<#{human_value(below)}"
|
239
|
+
elsif above
|
240
|
+
">#{human_value(above)}"
|
241
|
+
else
|
242
|
+
'-'
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
223
246
|
end
|
data/lib/eye/checker/cpu.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
class Eye::Checker::Cpu < Eye::Checker
|
1
|
+
class Eye::Checker::Cpu < Eye::Checker::Measure
|
2
2
|
|
3
|
-
#
|
4
|
-
|
5
|
-
param :below, [Fixnum, Float], true
|
3
|
+
# check :cpu, :every => 3.seconds, :below => 80, :times => [3,5]
|
6
4
|
|
7
5
|
def check_name
|
8
|
-
@check_name ||= "cpu(#{
|
6
|
+
@check_name ||= "cpu(#{measure_str})"
|
9
7
|
end
|
10
8
|
|
11
9
|
def get_value
|
@@ -16,12 +14,4 @@ class Eye::Checker::Cpu < Eye::Checker
|
|
16
14
|
"#{value}%"
|
17
15
|
end
|
18
16
|
|
19
|
-
|
20
|
-
if below
|
21
|
-
value < below
|
22
|
-
else
|
23
|
-
true
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
17
|
+
end
|
data/lib/eye/checker/cputime.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
class Eye::Checker::Cputime < Eye::Checker
|
1
|
+
class Eye::Checker::Cputime < Eye::Checker::Measure
|
2
2
|
|
3
3
|
# check :cputime, :every => 1.minute, :below => 120.minutes
|
4
4
|
|
5
|
-
param :below, [Fixnum, Float], true
|
6
|
-
|
7
5
|
def get_value
|
8
6
|
Eye::SystemResources.cputime(@pid).to_f
|
9
7
|
end
|
@@ -12,12 +10,4 @@ class Eye::Checker::Cputime < Eye::Checker
|
|
12
10
|
"#{value / 60}m"
|
13
11
|
end
|
14
12
|
|
15
|
-
|
16
|
-
if below
|
17
|
-
value < below
|
18
|
-
else
|
19
|
-
true
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
end
|
13
|
+
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
class Eye::Checker::FileCTime < Eye::Checker
|
2
2
|
|
3
3
|
# Check that file changes (log for example)
|
4
|
-
|
5
|
-
# checks :ctime, :every => 5.seconds, :file => "/tmp/1.log", :times => [3,5]
|
4
|
+
# check :ctime, :every => 5.seconds, :file => "/tmp/1.log", :times => [3,5]
|
6
5
|
|
7
6
|
param :file, [String], true
|
8
7
|
|
@@ -22,4 +21,4 @@ class Eye::Checker::FileCTime < Eye::Checker
|
|
22
21
|
value.to_i > previous_value.to_i
|
23
22
|
end
|
24
23
|
|
25
|
-
end
|
24
|
+
end
|
@@ -1,13 +1,14 @@
|
|
1
|
-
class Eye::Checker::FileSize < Eye::Checker
|
1
|
+
class Eye::Checker::FileSize < Eye::Checker::Measure
|
2
2
|
|
3
3
|
# Check that file size changed (log for example)
|
4
|
-
|
5
|
-
# checks :fsize, :every => 5.seconds, :file => "/tmp/1.log", :times => [3,5],
|
4
|
+
# check :fsize, :every => 5.seconds, :file => "/tmp/1.log", :times => [3,5],
|
6
5
|
# :below => 30.kilobytes, :above => 10.kilobytes
|
7
6
|
|
8
7
|
param :file, [String], true
|
9
|
-
|
10
|
-
|
8
|
+
|
9
|
+
def check_name
|
10
|
+
@check_name ||= "fsize(#{measure_str})"
|
11
|
+
end
|
11
12
|
|
12
13
|
def get_value
|
13
14
|
File.size(file) rescue nil
|
@@ -24,11 +25,10 @@ class Eye::Checker::FileSize < Eye::Checker
|
|
24
25
|
|
25
26
|
return true if diff < 0 # case when logger nulled
|
26
27
|
|
27
|
-
return false
|
28
|
-
return false if above && diff < above
|
28
|
+
return false unless super(diff)
|
29
29
|
return false if diff == 0
|
30
30
|
|
31
31
|
true
|
32
32
|
end
|
33
33
|
|
34
|
-
end
|
34
|
+
end
|