eye 0.5.2 → 0.6
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 +13 -5
- data/.travis.yml +1 -6
- data/CHANGES.md +12 -0
- data/README.md +5 -0
- data/Rakefile +4 -4
- data/bin/loader_eye +14 -3
- data/bin/runner +16 -0
- data/examples/dependency.eye +17 -0
- data/examples/plugin/README.md +15 -0
- data/examples/plugin/main.eye +15 -0
- data/examples/plugin/plugin.rb +63 -0
- data/examples/unicorn.eye +1 -1
- data/eye.gemspec +1 -2
- data/lib/eye.rb +1 -1
- data/lib/eye/checker.rb +16 -4
- data/lib/eye/checker/children_count.rb +44 -0
- data/lib/eye/checker/children_memory.rb +12 -0
- data/lib/eye/checker/socket.rb +9 -2
- data/lib/eye/child_process.rb +6 -2
- data/lib/eye/cli.rb +13 -2
- data/lib/eye/cli/commands.rb +2 -2
- data/lib/eye/cli/server.rb +11 -3
- data/lib/eye/config.rb +2 -2
- data/lib/eye/controller/commands.rb +29 -2
- data/lib/eye/controller/helpers.rb +31 -6
- data/lib/eye/controller/load.rb +5 -6
- data/lib/eye/controller/options.rb +1 -1
- data/lib/eye/controller/send_command.rb +0 -1
- data/lib/eye/dsl.rb +2 -1
- data/lib/eye/dsl/application_opts.rb +4 -7
- data/lib/eye/dsl/group_opts.rb +2 -1
- data/lib/eye/dsl/helpers.rb +9 -1
- data/lib/eye/dsl/main.rb +11 -5
- data/lib/eye/dsl/opts.rb +5 -22
- data/lib/eye/dsl/process_opts.rb +20 -2
- data/lib/eye/dsl/pure_opts.rb +1 -1
- data/lib/eye/dsl/validation.rb +17 -2
- data/lib/eye/local.rb +79 -50
- data/lib/eye/notify.rb +5 -3
- data/lib/eye/notify/mail.rb +6 -2
- data/lib/eye/process.rb +3 -1
- data/lib/eye/process/children.rb +1 -1
- data/lib/eye/process/commands.rb +17 -6
- data/lib/eye/process/config.rb +6 -1
- data/lib/eye/process/data.rb +20 -0
- data/lib/eye/process/monitor.rb +10 -4
- data/lib/eye/process/states.rb +5 -2
- data/lib/eye/process/states_history.rb +1 -1
- data/lib/eye/process/system.rb +6 -2
- data/lib/eye/process/trigger.rb +0 -1
- data/lib/eye/process/validate.rb +8 -6
- data/lib/eye/process/watchers.rb +1 -7
- data/lib/eye/system.rb +14 -11
- data/lib/eye/system_resources.rb +8 -0
- data/lib/eye/trigger.rb +12 -4
- data/lib/eye/trigger/check_dependency.rb +30 -0
- data/lib/eye/trigger/stop_children.rb +4 -1
- data/lib/eye/trigger/wait_dependency.rb +49 -0
- data/lib/eye/utils.rb +13 -0
- metadata +41 -45
checksums.yaml
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YTRhNjdkYTZkYmFlMmJmNGJmMGUzNWM4N2ViZjAyOWZiODhiOThkNA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MzFiZDcwZjM4NTg4Y2QwNDI4NjgxZmU4MGQxZjEzMzQxYmJiZDY5Mw==
|
5
7
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
Zjk2MzM3ODlmMTA4ZTE4OTUzNTJkMTY3YzEzNTY5ZGM1ZmI4YWYzYjFiMjJk
|
10
|
+
N2RmMzJmNWE1ZDcyNzkyYmE1ZDhlNjM1ZTcxNzFmMmRlZmQ5YTVlNDE3NzNm
|
11
|
+
MGNlNmQwZDc1MzNjN2JlYzFjNWI5MDgyYWNmZDYyMjc0ZDRiNTE=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MzRkYjE1M2FhN2Q4YmQyMDk0Y2Q3ZjYxN2Y2YmQwYTMwODM5YmJjMzI3Nzlh
|
14
|
+
NTFmMjA2MTc1OTk2ODA4Y2FkZjRjYTMwZGNlNmEyYWMzYTJlMTJiYmI4Y2Iw
|
15
|
+
YmQyODZjMzVlMzliZWNmNzVjNDAxZGU5YTM4YmVkNmRiMmJiY2M=
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
0.6
|
2
|
+
------
|
3
|
+
* add processes dependencies (#43)
|
4
|
+
* add eye-http gem (https://github.com/kostya/eye-http)
|
5
|
+
* add eye plugin example (https://github.com/kostya/eye/tree/master/examples/plugin)
|
6
|
+
* add quit option --stop_all (#39)
|
7
|
+
* add local eye runner (like foreman, used Eyefile)
|
8
|
+
* add use_leaf_child monitoring strategy (to daemonize sh -c '...') (788488a)
|
9
|
+
* add children_count, children_memory checks
|
10
|
+
* add dsl default application options (__default__)
|
11
|
+
* trusting external pid_file changes (#52)
|
12
|
+
|
1
13
|
0.5.2
|
2
14
|
-----
|
3
15
|
* rename dsl :childs_update_period to :children_update_period
|
data/README.md
CHANGED
@@ -185,6 +185,7 @@ Log tracing (tail and grep):
|
|
185
185
|
Quit monitoring:
|
186
186
|
|
187
187
|
$ eye q(uit)
|
188
|
+
$ eye q -s # stop all processes and quit
|
188
189
|
|
189
190
|
Interactive info:
|
190
191
|
|
@@ -204,4 +205,8 @@ Process states and events:
|
|
204
205
|
[](https://raw.github.com/kostya/stuff/master/eye/process.png)
|
205
206
|
|
206
207
|
|
208
|
+
EyeHttp Gem:
|
209
|
+
|
210
|
+
https://github.com/kostya/eye-http
|
211
|
+
|
207
212
|
Thanks `Bluepill` for the nice config ideas.
|
data/Rakefile
CHANGED
@@ -7,10 +7,10 @@ require 'coveralls/rake/task'
|
|
7
7
|
|
8
8
|
Coveralls::RakeTask.new
|
9
9
|
|
10
|
-
task :default => :
|
10
|
+
task :default => :pspec
|
11
11
|
|
12
|
-
task :
|
13
|
-
Rake::Task['parallel:spec'].invoke(ENV['N'] ||
|
12
|
+
task :pspec do
|
13
|
+
Rake::Task['parallel:spec'].invoke(ENV['N'] || 10)
|
14
14
|
end
|
15
15
|
|
16
16
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
@@ -26,7 +26,7 @@ task :env do
|
|
26
26
|
require 'bundler/setup'
|
27
27
|
require 'eye'
|
28
28
|
Eye::Controller
|
29
|
-
Eye::Process
|
29
|
+
Eye::Process
|
30
30
|
end
|
31
31
|
|
32
32
|
desc "graph"
|
data/bin/loader_eye
CHANGED
@@ -24,6 +24,15 @@ OptionParser.new do |opts|
|
|
24
24
|
options[:logger] = logger
|
25
25
|
end
|
26
26
|
|
27
|
+
opts.on( '-dr', '--dir DIR', 'Dir for local runner' ) do |dir|
|
28
|
+
Eye::Local.dir = dir
|
29
|
+
Eye::Local.local_runner = true
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on( '-st', '--stop_all', 'Stop all on exit' ) do |stop_all|
|
33
|
+
options[:stop_all] = true
|
34
|
+
end
|
35
|
+
|
27
36
|
opts.on( '-d', '--debug', 'debug info to logger' ) do
|
28
37
|
options[:debug] = true
|
29
38
|
end
|
@@ -52,8 +61,10 @@ Eye::Control.set_proc_line
|
|
52
61
|
|
53
62
|
server.async.run
|
54
63
|
|
55
|
-
trap("
|
56
|
-
trap("
|
57
|
-
trap("
|
64
|
+
trap("USR1") { Eye::Logger.reopen }
|
65
|
+
trap("USR2") { GC.start }
|
66
|
+
trap("INT") { exit }
|
67
|
+
|
68
|
+
at_exit { Eye::Control.command(:stop_all) } if options[:stop_all]
|
58
69
|
|
59
70
|
sleep
|
data/bin/runner
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib]))
|
3
|
+
require 'eye'
|
4
|
+
|
5
|
+
# Local version of eye
|
6
|
+
# which looking for Eyefile
|
7
|
+
# like foreman
|
8
|
+
|
9
|
+
unless Eye::Local.eyefile
|
10
|
+
puts "Not found Eyefile"
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
Eye::Local.dir = File.dirname(Eye::Local.eyefile)
|
15
|
+
Eye::Local.local_runner = true
|
16
|
+
Eye::Cli.start
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# process dependencies :b -> :a
|
2
|
+
|
3
|
+
Eye.app :dependency do
|
4
|
+
process(:a) do
|
5
|
+
start_command "sleep 100"
|
6
|
+
daemonize true
|
7
|
+
pid_file "/tmp/test_process_a.pid"
|
8
|
+
end
|
9
|
+
|
10
|
+
process(:b) do
|
11
|
+
start_command "sleep 100"
|
12
|
+
daemonize true
|
13
|
+
pid_file "/tmp/test_process_b.pid"
|
14
|
+
depend_on :a
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Eye Plugin Example
|
2
|
+
------------------
|
3
|
+
|
4
|
+
This plugin adds reactor which try to reads command from file "/tmp/cmd.txt" every 1.second (then execute it and delete file). Also plugin add trigger to save every process state transition into "/tmp/saver.log".
|
5
|
+
|
6
|
+
To test it:
|
7
|
+
|
8
|
+
bundle exec eye l examples/plugin/main.eye
|
9
|
+
tail -f /tmp/eye.log
|
10
|
+
tail -f /tmp/saver.log
|
11
|
+
echo 'restart' > /tmp/cmd.txt
|
12
|
+
|
13
|
+
Also, here http example of gem:
|
14
|
+
|
15
|
+
https://github.com/kostya/eye-http
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Eye.load('./plugin.rb')
|
2
|
+
|
3
|
+
Eye.config do
|
4
|
+
logger "/tmp/eye.log"
|
5
|
+
enable_reactor(1.second, "/tmp/cmd.txt")
|
6
|
+
enable_saver("/tmp/saver.log")
|
7
|
+
end
|
8
|
+
|
9
|
+
Eye.app :app do
|
10
|
+
process :process do
|
11
|
+
pid_file "/tmp/p.pid"
|
12
|
+
start_command "sleep 10"
|
13
|
+
daemonize true
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Reactor
|
2
|
+
include Celluloid
|
3
|
+
|
4
|
+
def initialize(interval, filename)
|
5
|
+
@interval = interval
|
6
|
+
@filename = filename
|
7
|
+
every(@interval) do
|
8
|
+
info "check file #{@filename}"
|
9
|
+
if cmd = read_file
|
10
|
+
execute_command cmd
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def read_file
|
16
|
+
if File.exists?(@filename)
|
17
|
+
cmd = File.read(@filename).chop
|
18
|
+
File.delete(@filename) rescue nil
|
19
|
+
cmd
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def execute_command(cmd)
|
24
|
+
Eye::Control.command(cmd, 'all') if %w{restart start stop}.include?(cmd)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Saver < Eye::Trigger::Custom
|
29
|
+
param :log_name, String, true
|
30
|
+
|
31
|
+
def check(trans)
|
32
|
+
tlogger.info "#{process.full_name} transition from #{trans.from_name} to #{trans.to_name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def tlogger
|
36
|
+
@tlogger ||= Logger.new(log_name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def reactor
|
41
|
+
Celluloid::Actor[:reactor]
|
42
|
+
end
|
43
|
+
|
44
|
+
# Extend config options, add enable_reactor
|
45
|
+
class Eye::Dsl::ConfigOpts
|
46
|
+
def enable_reactor(*args)
|
47
|
+
@config[:reactor] = args
|
48
|
+
end
|
49
|
+
|
50
|
+
def enable_saver(save_log)
|
51
|
+
Eye.application '__default__' do
|
52
|
+
trigger :saver, :log_name => save_log
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# extend controller to execute method, and config loads
|
58
|
+
class Eye::Controller
|
59
|
+
def set_opt_reactor(args)
|
60
|
+
reactor.terminate if reactor
|
61
|
+
Celluloid::Actor[:reactor] = Reactor.supervise(*args)
|
62
|
+
end
|
63
|
+
end
|
data/examples/unicorn.eye
CHANGED
@@ -26,7 +26,7 @@ Eye.application "rails_unicorn" do
|
|
26
26
|
check :cpu, :every => 30, :below => 80, :times => 3
|
27
27
|
check :memory, :every => 30, :below => 150.megabytes, :times => [3,5]
|
28
28
|
|
29
|
-
start_timeout
|
29
|
+
start_timeout 100.seconds
|
30
30
|
restart_grace 30.seconds
|
31
31
|
|
32
32
|
monitor_children do
|
data/eye.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Eye::VERSION
|
17
17
|
gem.license = "MIT"
|
18
18
|
|
19
|
-
gem.required_ruby_version = '>= 1.9.2'
|
19
|
+
gem.required_ruby_version = '>= 1.9.2'
|
20
20
|
gem.required_rubygems_version = '>= 1.3.6'
|
21
21
|
|
22
22
|
gem.add_dependency 'celluloid', '~> 0.15.0'
|
@@ -37,5 +37,4 @@ Gem::Specification.new do |gem|
|
|
37
37
|
gem.add_development_dependency 'xmpp4r'
|
38
38
|
gem.add_development_dependency 'coveralls'
|
39
39
|
gem.add_development_dependency 'simplecov', '>= 0.8.1'
|
40
|
-
gem.add_development_dependency 'parallel_tests'
|
41
40
|
end
|
data/lib/eye.rb
CHANGED
data/lib/eye/checker.rb
CHANGED
@@ -11,16 +11,19 @@ class Eye::Checker
|
|
11
11
|
autoload :Nop, 'eye/checker/nop'
|
12
12
|
autoload :Runtime, 'eye/checker/runtime'
|
13
13
|
autoload :Cputime, 'eye/checker/cputime'
|
14
|
+
autoload :ChildrenCount, 'eye/checker/children_count'
|
15
|
+
autoload :ChildrenMemory,'eye/checker/children_memory'
|
14
16
|
|
15
17
|
TYPES = {:memory => 'Memory', :cpu => 'Cpu', :http => 'Http',
|
16
18
|
:ctime => 'FileCTime', :fsize => 'FileSize', :file_touched => 'FileTouched',
|
17
|
-
:socket => 'Socket', :nop => 'Nop', :runtime => 'Runtime', :cputime => 'Cputime'
|
19
|
+
:socket => 'Socket', :nop => 'Nop', :runtime => 'Runtime', :cputime => 'Cputime',
|
20
|
+
:children_count => "ChildrenCount", :children_memory => "ChildrenMemory" }
|
18
21
|
|
19
22
|
attr_accessor :value, :values, :options, :pid, :type, :check_count, :process
|
20
23
|
|
21
24
|
param :every, [Fixnum, Float], false, 5
|
22
25
|
param :times, [Fixnum, Array], nil, 1
|
23
|
-
param :fires, [Symbol, Array], nil, nil, [:stop, :restart, :unmonitor, :
|
26
|
+
param :fires, [Symbol, Array], nil, nil, [:stop, :restart, :unmonitor, :start, :delete, :nothing, :notify]
|
24
27
|
param :initial_grace, [Fixnum, Float]
|
25
28
|
param :skip_initial_fails, [TrueClass, FalseClass]
|
26
29
|
|
@@ -37,7 +40,7 @@ class Eye::Checker
|
|
37
40
|
def self.get_class(type)
|
38
41
|
klass = eval("Eye::Checker::#{TYPES[type]}") rescue nil
|
39
42
|
raise "Unknown checker #{type}" unless klass
|
40
|
-
if deps = klass.
|
43
|
+
if deps = klass.requires
|
41
44
|
Array(deps).each { |d| require d }
|
42
45
|
end
|
43
46
|
klass
|
@@ -180,6 +183,15 @@ class Eye::Checker
|
|
180
183
|
process.instance_exec(&p) if process.alive?
|
181
184
|
end
|
182
185
|
|
186
|
+
def fire
|
187
|
+
actions = fires ? Array(fires) : [:restart]
|
188
|
+
process.notify :warn, "Bounded #{check_name}: #{last_human_values} send to #{actions}"
|
189
|
+
|
190
|
+
actions.each do |action|
|
191
|
+
process.schedule action, Eye::Reason.new("bounded #{check_name}")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
183
195
|
def defer(&block)
|
184
196
|
Celluloid::Future.new(&block).value
|
185
197
|
end
|
@@ -197,7 +209,7 @@ class Eye::Checker
|
|
197
209
|
Eye::Checker.const_set(name, base)
|
198
210
|
end
|
199
211
|
|
200
|
-
def self.
|
212
|
+
def self.requires
|
201
213
|
end
|
202
214
|
|
203
215
|
class CustomCell < Eye::Checker
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Eye::Checker::ChildrenCount < Eye::Checker::Measure
|
2
|
+
|
3
|
+
# check :children_count, :every => 30.seconds, :below => 10, :strategy => :kill_old
|
4
|
+
# monitor_children should be enabled
|
5
|
+
|
6
|
+
param :strategy, Symbol, nil, :restart, [:restart, :kill_old, :kill_new]
|
7
|
+
|
8
|
+
def get_value
|
9
|
+
process.children.size
|
10
|
+
end
|
11
|
+
|
12
|
+
def fire
|
13
|
+
if strategy == :restart
|
14
|
+
super
|
15
|
+
else
|
16
|
+
pids = ordered_by_date_children_pids
|
17
|
+
|
18
|
+
pids = if strategy == :kill_old
|
19
|
+
pids[0...-below]
|
20
|
+
else
|
21
|
+
pids[below..-1]
|
22
|
+
end
|
23
|
+
|
24
|
+
kill_pids(pids)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def kill_pids(pids)
|
31
|
+
info "killing pids: #{pids.inspect} for strategy: #{strategy}"
|
32
|
+
pids.each do |pid|
|
33
|
+
if child = process.children[pid]
|
34
|
+
child.schedule :stop, Eye::Reason.new("bounded #{check_name}")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def ordered_by_date_children_pids
|
40
|
+
children = process.children.values
|
41
|
+
children.sort_by { |ch| Eye::SystemResources.start_time(ch.pid).to_i }.map &:pid
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Eye::Checker::ChildrenMemory < Eye::Checker::Measure
|
2
|
+
|
3
|
+
# check :children_memory, :every => 30.seconds, :below => 400.megabytes
|
4
|
+
# monitor_children should be enabled
|
5
|
+
|
6
|
+
def get_value
|
7
|
+
process.children.values.inject(0) do |sum, ch|
|
8
|
+
sum + Eye::SystemResources.memory(ch.pid).to_i
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
data/lib/eye/checker/socket.rb
CHANGED
@@ -18,7 +18,7 @@ class Eye::Checker::Socket < Eye::Checker::Defer
|
|
18
18
|
param :read_timeout, [Fixnum, Float]
|
19
19
|
param :send_data
|
20
20
|
param :expect_data, [String, Regexp, Proc]
|
21
|
-
param :protocol, [Symbol], nil, nil, [:default, :em_object]
|
21
|
+
param :protocol, [Symbol], nil, nil, [:default, :em_object, :raw]
|
22
22
|
|
23
23
|
def initialize(*args)
|
24
24
|
super
|
@@ -51,7 +51,11 @@ class Eye::Checker::Socket < Eye::Checker::Defer
|
|
51
51
|
{ :result => result }
|
52
52
|
end
|
53
53
|
rescue Timeout::Error
|
54
|
-
|
54
|
+
if protocol == :raw
|
55
|
+
return { :result => @buffer }
|
56
|
+
else
|
57
|
+
return { :exception => "ReadTimeout<#{@read_timeout}>" }
|
58
|
+
end
|
55
59
|
end
|
56
60
|
else
|
57
61
|
{ :result => :listen }
|
@@ -144,6 +148,9 @@ private
|
|
144
148
|
if content.present?
|
145
149
|
Marshal.load(content) rescue 'corrupted_marshal'
|
146
150
|
end
|
151
|
+
when :raw
|
152
|
+
@buffer = ''
|
153
|
+
loop { @buffer << socket.recv(1) }
|
147
154
|
else
|
148
155
|
socket.readline.chop
|
149
156
|
end
|
data/lib/eye/child_process.rb
CHANGED
@@ -26,10 +26,11 @@ class Eye::ChildProcess
|
|
26
26
|
|
27
27
|
attr_reader :pid, :name, :full_name, :config, :watchers
|
28
28
|
|
29
|
-
def initialize(pid, config = {}, logger_prefix = nil)
|
29
|
+
def initialize(pid, config = {}, logger_prefix = nil, parent_pid = nil)
|
30
30
|
raise 'Empty pid' unless pid
|
31
31
|
|
32
32
|
@pid = pid
|
33
|
+
@parent_pid = parent_pid
|
33
34
|
@config = prepare_config(config)
|
34
35
|
@name = "child-#{pid}"
|
35
36
|
@full_name = [logger_prefix, @name] * ':'
|
@@ -94,4 +95,7 @@ class Eye::ChildProcess
|
|
94
95
|
self_status_data(debug)
|
95
96
|
end
|
96
97
|
|
97
|
-
|
98
|
+
def prepare_command(command) # override
|
99
|
+
super.gsub('{PARENT_PID}', @parent_pid.to_s)
|
100
|
+
end
|
101
|
+
end
|