eye 0.2.1 → 0.2.2
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.
- 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
|