eye 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -17
- data/bin/eye +5 -0
- data/examples/notify.eye +18 -0
- data/examples/process_thin.rb +29 -0
- data/examples/sidekiq.eye +5 -1
- data/examples/test.eye +24 -17
- data/examples/thin-farm.eye +29 -0
- data/examples/unicorn.eye +2 -0
- data/eye.gemspec +1 -1
- data/lib/eye.rb +1 -1
- data/lib/eye/checker.rb +3 -5
- data/lib/eye/checker/http.rb +1 -2
- data/lib/eye/checker/socket.rb +2 -2
- data/lib/eye/controller/commands.rb +2 -0
- data/lib/eye/controller/send_command.rb +8 -2
- data/lib/eye/dsl.rb +1 -0
- data/lib/eye/dsl/opts.rb +36 -2
- data/lib/eye/dsl/pure_opts.rb +17 -39
- data/lib/eye/{checker → dsl}/validation.rb +15 -5
- data/lib/eye/group.rb +13 -4
- data/lib/eye/group/chain.rb +11 -0
- data/lib/eye/notify.rb +1 -1
- data/lib/eye/notify/mail.rb +1 -1
- data/lib/eye/process/child.rb +0 -2
- data/lib/eye/process/commands.rb +11 -14
- data/lib/eye/process/monitor.rb +10 -16
- data/lib/eye/process/scheduler.rb +8 -3
- data/lib/eye/process/states.rb +1 -2
- data/lib/eye/process/system.rb +38 -7
- data/lib/eye/process/watchers.rb +3 -3
- data/lib/eye/settings.rb +1 -1
- data/lib/eye/system.rb +33 -16
- data/lib/eye/trigger.rb +1 -1
- data/lib/eye/utils/celluloid_chain.rb +2 -0
- data/spec/checker/cpu_spec.rb +1 -1
- data/spec/checker/http_spec.rb +2 -2
- data/spec/checker/memory_spec.rb +2 -2
- data/spec/checker_spec.rb +1 -1
- data/spec/controller/controller_spec.rb +6 -0
- data/spec/controller/find_objects_spec.rb +6 -0
- data/spec/controller/intergration_spec.rb +24 -0
- data/spec/dsl/checks_spec.rb +2 -2
- data/spec/dsl/notify_spec.rb +12 -3
- data/spec/dsl/with_server_spec.rb +26 -2
- data/spec/process/checks/child_checks_spec.rb +1 -1
- data/spec/process/checks/memory_spec.rb +14 -0
- data/spec/process/scheduler_spec.rb +8 -0
- data/spec/process/system_spec.rb +27 -4
- data/spec/spec_helper.rb +3 -1
- data/spec/system_spec.rb +12 -5
- data/spec/utils/celluloid_chain_spec.rb +8 -0
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec5135b6c531e9451f98ec8b9d36a54d2e57e3f9
|
4
|
+
data.tar.gz: fd8011e705ee96d0d24dffbe03be598a18b285c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59237be9adb524bdc90ddb9203d3246e7e6fc03f4b9c7398df2380fba2423e68592a996ac720ff04cd8a813b34ed8a27a1c259421907dd1103b18ad508c9decd
|
7
|
+
data.tar.gz: b741a332f8888e3f5a2dd50af91e0dbafebed8f8dcc406f9f8cab270b565f3ce2624adef2e4b9c2b3be0a01ff18dcbaf28159d4ba55b6d532e37711b8c9fa5cd
|
data/README.md
CHANGED
@@ -14,26 +14,31 @@ Config example, shows some typical processes and most of the options (see in exa
|
|
14
14
|
|
15
15
|
examples/test.eye
|
16
16
|
```ruby
|
17
|
-
|
17
|
+
# load submodules, here just for example
|
18
|
+
Eye.load("./eye/*.rb")
|
18
19
|
|
20
|
+
# Eye self-configuration section
|
19
21
|
Eye.config do
|
20
|
-
logger "/tmp/eye.log"
|
21
|
-
logger_level Logger::DEBUG
|
22
|
+
logger "/tmp/eye.log"
|
22
23
|
end
|
23
24
|
|
25
|
+
# Adding application
|
24
26
|
Eye.application "test" do
|
27
|
+
# All options inherits down to the config leafs.
|
28
|
+
# except `env`, which merging down
|
29
|
+
|
25
30
|
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
26
31
|
stdall "trash.log" # stdout,err logs for processes by default
|
27
32
|
env "APP_ENV" => "production" # global env for each processes
|
28
|
-
triggers :flapping, :times => 10, :within => 1.minute
|
33
|
+
triggers :flapping, :times => 10, :within => 1.minute #
|
34
|
+
checks :cpu, :below => 100, :times => 3 # global check for all processes
|
29
35
|
|
30
36
|
group "samples" do
|
31
|
-
|
32
|
-
chain :grace => 5.seconds, :action => :restart # restarting with 5s interval, one by one.
|
37
|
+
chain :grace => 5.seconds # chained start-restart with 5s interval, one by one.
|
33
38
|
|
34
39
|
# eye daemonized process
|
35
|
-
process
|
36
|
-
pid_file "1.pid" # will be expanded with working_dir
|
40
|
+
process :sample1 do
|
41
|
+
pid_file "1.pid" # pid_path will be expanded with the working_dir
|
37
42
|
start_command "ruby ./sample.rb"
|
38
43
|
daemonize true
|
39
44
|
stdall "sample1.log"
|
@@ -42,7 +47,7 @@ Eye.application "test" do
|
|
42
47
|
end
|
43
48
|
|
44
49
|
# self daemonized process
|
45
|
-
process
|
50
|
+
process :sample2 do
|
46
51
|
pid_file "2.pid"
|
47
52
|
start_command "ruby ./sample.rb -d --pid 2.pid --log sample2.log"
|
48
53
|
stop_command "kill -9 {PID}"
|
@@ -52,7 +57,7 @@ Eye.application "test" do
|
|
52
57
|
end
|
53
58
|
|
54
59
|
# daemon with 3 childs
|
55
|
-
process
|
60
|
+
process :forking do
|
56
61
|
pid_file "forking.pid"
|
57
62
|
start_command "ruby ./forking.rb start"
|
58
63
|
stop_command "ruby forking.rb stop"
|
@@ -67,17 +72,19 @@ Eye.application "test" do
|
|
67
72
|
end
|
68
73
|
end
|
69
74
|
|
75
|
+
# eventmachine process, daemonized with eye
|
70
76
|
process :event_machine do |p|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
77
|
+
pid_file 'em.pid'
|
78
|
+
start_command 'ruby em.rb'
|
79
|
+
stdout 'em.log'
|
80
|
+
daemonize true
|
81
|
+
stop_signals [:QUIT, 2.seconds, :KILL]
|
76
82
|
|
77
|
-
|
78
|
-
|
83
|
+
checks :socket, :addr => "tcp://127.0.0.1:33221", :every => 10.seconds, :times => 2,
|
84
|
+
:timeout => 1.second, :send_data => "ping", :expect_data => /pong/
|
79
85
|
end
|
80
86
|
|
87
|
+
# thin process, self daemonized
|
81
88
|
process :thin do
|
82
89
|
pid_file "thin.pid"
|
83
90
|
start_command "bundle exec thin start -R thin.ru -p 33233 -d -l thin.log -P thin.pid"
|
data/bin/eye
CHANGED
@@ -78,6 +78,11 @@ class Cli < Thor
|
|
78
78
|
send_command(:signal, sig, *targets)
|
79
79
|
end
|
80
80
|
|
81
|
+
desc "break TARGET[,...]", "break group chain executing"
|
82
|
+
def break(*targets)
|
83
|
+
send_command(:break_chain, *targets)
|
84
|
+
end
|
85
|
+
|
81
86
|
desc "trace [TARGET]", "tracing log for app,group or process"
|
82
87
|
def trace(target = "")
|
83
88
|
log_trace(target)
|
data/examples/notify.eye
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Notify example
|
2
|
+
|
3
|
+
Eye.config do
|
4
|
+
mail :host => "mx.some.host", :port => 25, :domain => "some.host"
|
5
|
+
contact :errors, :mail, 'error@some.host'
|
6
|
+
contact :dev, :mail, 'dev@some.host'
|
7
|
+
end
|
8
|
+
|
9
|
+
Eye.application :some do
|
10
|
+
notify :errors
|
11
|
+
|
12
|
+
process :some_process do
|
13
|
+
notify :dev, :warn
|
14
|
+
|
15
|
+
...
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
def thin(proxy, port)
|
3
|
+
name = "thin-#{port}"
|
4
|
+
|
5
|
+
opts = [
|
6
|
+
"-l thins.log",
|
7
|
+
"-p #{port}",
|
8
|
+
"-P #{name}.pid",
|
9
|
+
"-d",
|
10
|
+
"-R thin.ru",
|
11
|
+
"--tag #{proxy.app.name}.#{proxy.name}",
|
12
|
+
"-t 60",
|
13
|
+
"-e #{proxy.env["RAILS_ENV"]}",
|
14
|
+
"-c #{proxy.working_dir}",
|
15
|
+
"-a 127.0.0.1"
|
16
|
+
]
|
17
|
+
|
18
|
+
proxy.process(name) do
|
19
|
+
pid_file "#{name}.pid"
|
20
|
+
|
21
|
+
start_command "#{BUNDLE} exec thin start #{opts * ' '}"
|
22
|
+
stop_signals [:QUIT, 2.seconds, :TERM, 1.seconds, :KILL]
|
23
|
+
|
24
|
+
stdall "thin.stdall.log"
|
25
|
+
|
26
|
+
checks :http, :url => "http://127.0.0.1:#{port}/hello", :pattern => /World/,
|
27
|
+
:every => 5.seconds, :times => [2, 3], :timeout => 1.second
|
28
|
+
end
|
29
|
+
end
|
data/examples/sidekiq.eye
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
# Example: how to run sidekiq daemon
|
2
|
+
|
1
3
|
def sidekiq_process(proxy, name)
|
4
|
+
rails_env = proxy.env['RAILS_ENV']
|
5
|
+
|
2
6
|
proxy.process(name) do
|
3
|
-
start_command "ruby ./bin/sidekiq -e #{
|
7
|
+
start_command "ruby ./bin/sidekiq -e #{rails_env} -C ./config/sidekiq.#{rails_env}.yml"
|
4
8
|
pid_file "tmp/pids/#{name}.pid"
|
5
9
|
stdall "log/#{name}.log"
|
6
10
|
daemonize true
|
data/examples/test.eye
CHANGED
@@ -1,23 +1,28 @@
|
|
1
|
-
|
1
|
+
# load submodules, here just for example
|
2
|
+
Eye.load("./eye/*.rb")
|
2
3
|
|
4
|
+
# Eye self-configuration section
|
3
5
|
Eye.config do
|
4
|
-
logger "/tmp/eye.log"
|
5
|
-
logger_level Logger::DEBUG
|
6
|
+
logger "/tmp/eye.log"
|
6
7
|
end
|
7
8
|
|
9
|
+
# Adding application
|
8
10
|
Eye.application "test" do
|
11
|
+
# All options inherits down to the config leafs.
|
12
|
+
# except `env`, which merging down
|
13
|
+
|
9
14
|
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
10
15
|
stdall "trash.log" # stdout,err logs for processes by default
|
11
16
|
env "APP_ENV" => "production" # global env for each processes
|
12
|
-
triggers :flapping, :times => 10, :within => 1.minute
|
17
|
+
triggers :flapping, :times => 10, :within => 1.minute #
|
18
|
+
checks :cpu, :below => 100, :times => 3 # global check for all processes
|
13
19
|
|
14
20
|
group "samples" do
|
15
|
-
|
16
|
-
chain :grace => 5.seconds, :action => :restart # restarting with 5s interval, one by one.
|
21
|
+
chain :grace => 5.seconds # chained start-restart with 5s interval, one by one.
|
17
22
|
|
18
23
|
# eye daemonized process
|
19
|
-
process
|
20
|
-
pid_file "1.pid" # will be expanded with working_dir
|
24
|
+
process :sample1 do
|
25
|
+
pid_file "1.pid" # pid_path will be expanded with the working_dir
|
21
26
|
start_command "ruby ./sample.rb"
|
22
27
|
daemonize true
|
23
28
|
stdall "sample1.log"
|
@@ -26,7 +31,7 @@ Eye.application "test" do
|
|
26
31
|
end
|
27
32
|
|
28
33
|
# self daemonized process
|
29
|
-
process
|
34
|
+
process :sample2 do
|
30
35
|
pid_file "2.pid"
|
31
36
|
start_command "ruby ./sample.rb -d --pid 2.pid --log sample2.log"
|
32
37
|
stop_command "kill -9 {PID}"
|
@@ -36,7 +41,7 @@ Eye.application "test" do
|
|
36
41
|
end
|
37
42
|
|
38
43
|
# daemon with 3 childs
|
39
|
-
process
|
44
|
+
process :forking do
|
40
45
|
pid_file "forking.pid"
|
41
46
|
start_command "ruby ./forking.rb start"
|
42
47
|
stop_command "ruby forking.rb stop"
|
@@ -51,17 +56,19 @@ Eye.application "test" do
|
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
59
|
+
# eventmachine process, daemonized with eye
|
54
60
|
process :event_machine do |p|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
61
|
+
pid_file 'em.pid'
|
62
|
+
start_command 'ruby em.rb'
|
63
|
+
stdout 'em.log'
|
64
|
+
daemonize true
|
65
|
+
stop_signals [:QUIT, 2.seconds, :KILL]
|
60
66
|
|
61
|
-
|
62
|
-
|
67
|
+
checks :socket, :addr => "tcp://127.0.0.1:33221", :every => 10.seconds, :times => 2,
|
68
|
+
:timeout => 1.second, :send_data => "ping", :expect_data => /pong/
|
63
69
|
end
|
64
70
|
|
71
|
+
# thin process, self daemonized
|
65
72
|
process :thin do
|
66
73
|
pid_file "thin.pid"
|
67
74
|
start_command "bundle exec thin start -R thin.ru -p 33233 -d -l thin.log -P thin.pid"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
RUBY = 'ruby'
|
2
|
+
BUNDLE = 'bundle'
|
3
|
+
|
4
|
+
Eye.load("process_thin.rb")
|
5
|
+
|
6
|
+
Eye.config do
|
7
|
+
logger "/tmp/eye.log"
|
8
|
+
end
|
9
|
+
|
10
|
+
Eye.app 'thin-farm' do
|
11
|
+
working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
|
12
|
+
env "RAILS_ENV" => "production"
|
13
|
+
|
14
|
+
stop_on_delete true # this option means, when we change pids and load config,
|
15
|
+
# deleted processes will be stops
|
16
|
+
|
17
|
+
triggers :flapping, :times => 10, :within => 1.minute
|
18
|
+
checks :memory, :below => 60.megabytes, :every => 30.seconds, :times => 5
|
19
|
+
|
20
|
+
group :web do
|
21
|
+
chain :action => :restart, :grace => 5.seconds
|
22
|
+
chain :action => :start, :grace => 0.2.seconds
|
23
|
+
|
24
|
+
(5555..5560).each do |port|
|
25
|
+
thin self, port
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/examples/unicorn.eye
CHANGED
data/eye.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |gem|
|
|
32
32
|
gem.add_development_dependency 'ruby-graphviz'
|
33
33
|
gem.add_development_dependency 'forking'
|
34
34
|
gem.add_development_dependency 'fakeweb'
|
35
|
-
gem.add_development_dependency 'eventmachine'
|
35
|
+
gem.add_development_dependency 'eventmachine', ">= 1.0.3"
|
36
36
|
gem.add_development_dependency 'sinatra'
|
37
37
|
gem.add_development_dependency 'thin'
|
38
38
|
gem.add_development_dependency 'xmpp4r'
|
data/lib/eye.rb
CHANGED
data/lib/eye/checker.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
class Eye::Checker
|
2
2
|
include Eye::Logger::Helpers
|
3
3
|
|
4
|
-
autoload :Validation, 'eye/checker/validation'
|
5
|
-
|
6
4
|
autoload :Memory, 'eye/checker/memory'
|
7
5
|
autoload :Cpu, 'eye/checker/cpu'
|
8
6
|
autoload :Http, 'eye/checker/http'
|
@@ -51,7 +49,6 @@ class Eye::Checker
|
|
51
49
|
end
|
52
50
|
|
53
51
|
def check
|
54
|
-
tm1 = Time.now
|
55
52
|
@value = get_value
|
56
53
|
@values << {:value => @value, :good => good?(value)}
|
57
54
|
|
@@ -62,7 +59,7 @@ class Eye::Checker
|
|
62
59
|
result = false if bad_count >= min_tries
|
63
60
|
end
|
64
61
|
|
65
|
-
info "#{last_human_values} => #{result ? 'OK' : 'Fail'}
|
62
|
+
info "#{last_human_values} => #{result ? 'OK' : 'Fail'}"
|
66
63
|
result
|
67
64
|
end
|
68
65
|
|
@@ -112,8 +109,9 @@ class Eye::Checker
|
|
112
109
|
@values[-1][:value] if @values.present?
|
113
110
|
end
|
114
111
|
|
115
|
-
extend Eye::
|
112
|
+
extend Eye::Dsl::Validation
|
116
113
|
param :every, [Fixnum, Float], false, 5
|
117
114
|
param :times, [Fixnum, Array]
|
115
|
+
param :fire, Symbol, nil, nil, [:stop, :restart, :unmonitor, :nothing]
|
118
116
|
|
119
117
|
end
|
data/lib/eye/checker/http.rb
CHANGED
@@ -38,8 +38,7 @@ class Eye::Checker::Http < Eye::Checker
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def get_value_sync
|
41
|
-
|
42
|
-
res = _session.start{ |http| http.get(@uri.path) }
|
41
|
+
res = session.start{ |http| http.get(@uri.request_uri) }
|
43
42
|
{:result => res}
|
44
43
|
|
45
44
|
rescue Timeout::Error => ex
|
data/lib/eye/checker/socket.rb
CHANGED
@@ -5,7 +5,7 @@ class Eye::Checker::Socket < Eye::Checker
|
|
5
5
|
#
|
6
6
|
# Available parameters:
|
7
7
|
# :addr the socket addr to open. The format is tcp://<host>:<port> or unix:<path>
|
8
|
-
# :timeout generic timeout for
|
8
|
+
# :timeout generic timeout for reading data from socket
|
9
9
|
# :open_timeout override generic timeout for the connection
|
10
10
|
# :read_timeout override generic timeout for data read/write
|
11
11
|
# :send_data after connection send this data
|
@@ -18,7 +18,7 @@ class Eye::Checker::Socket < Eye::Checker
|
|
18
18
|
param :read_timeout, [Fixnum, Float]
|
19
19
|
param :send_data
|
20
20
|
param :expect_data, [String, Regexp, Proc]
|
21
|
-
param :protocol, [Symbol]
|
21
|
+
param :protocol, [Symbol], nil, nil, [:default, :em_object]
|
22
22
|
|
23
23
|
def check_name
|
24
24
|
'socket'
|
@@ -21,6 +21,12 @@ module Eye::Controller::SendCommand
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def break_chain(*obj_strs)
|
25
|
+
matched_objects(*obj_strs) do |obj|
|
26
|
+
obj.send_command(:break_chain)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
24
30
|
private
|
25
31
|
|
26
32
|
def matched_objects(*obj_strs, &block)
|
@@ -60,7 +66,7 @@ private
|
|
60
66
|
# nil if not found
|
61
67
|
def find_objects(*obj_strs)
|
62
68
|
return [] if obj_strs.blank?
|
63
|
-
return @applications if obj_strs.size == 1 && obj_strs[0].strip == 'all'
|
69
|
+
return @applications.dup if obj_strs.size == 1 && (obj_strs[0].strip == 'all' || obj_strs[0].strip == '*')
|
64
70
|
|
65
71
|
res = obj_strs.map{|c| c.split(",").map{|mask| find_objects_by_mask(mask) }}.flatten
|
66
72
|
|
@@ -76,7 +82,7 @@ private
|
|
76
82
|
res = final
|
77
83
|
end
|
78
84
|
|
79
|
-
res.present? ? Eye::Utils::AliveArray.new(res) :
|
85
|
+
res.present? ? Eye::Utils::AliveArray.new(res) : []
|
80
86
|
end
|
81
87
|
|
82
88
|
def find_objects_by_mask(mask)
|
data/lib/eye/dsl.rb
CHANGED
data/lib/eye/dsl/opts.rb
CHANGED
@@ -97,8 +97,42 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
|
|
97
97
|
h.instance_eval(&block)
|
98
98
|
groups = h.config.delete :groups
|
99
99
|
processes = h.config.delete :processes
|
100
|
-
|
101
|
-
|
100
|
+
|
101
|
+
if groups.present?
|
102
|
+
config[:groups] ||= {}
|
103
|
+
config[:groups].merge!(groups)
|
104
|
+
end
|
105
|
+
|
106
|
+
if processes.present?
|
107
|
+
config[:processes] ||= {}
|
108
|
+
config[:processes].merge!(processes)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# execute part of config on particular server
|
113
|
+
# array of strings
|
114
|
+
# regexp
|
115
|
+
# string
|
116
|
+
def with_server(glob = nil, &block)
|
117
|
+
on_server = true
|
118
|
+
|
119
|
+
if glob.present?
|
120
|
+
host = Eye::System.host
|
121
|
+
|
122
|
+
if glob.is_a?(Array)
|
123
|
+
on_server = !!glob.any?{|elem| elem == host}
|
124
|
+
elsif glob.is_a?(Regexp)
|
125
|
+
on_server = !!host.match(glob)
|
126
|
+
elsif glob.is_a?(String) || glob.is_a?(Symbol)
|
127
|
+
on_server = (host == glob.to_s)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
scoped do
|
132
|
+
with_condition(on_server, &block)
|
133
|
+
end
|
134
|
+
|
135
|
+
on_server
|
102
136
|
end
|
103
137
|
|
104
138
|
end
|