eye 0.7 → 0.8.celluloid15
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/.rubocop.yml +141 -0
- data/.travis.yml +5 -3
- data/CHANGES.md +9 -1
- data/README.md +5 -2
- data/Rakefile +6 -6
- data/bin/leye +9 -4
- data/bin/loader_eye +14 -15
- data/examples/custom_check.eye +24 -0
- data/examples/custom_trigger.eye +30 -0
- data/examples/delayed_job.eye +3 -3
- data/examples/dependency.eye +10 -11
- data/examples/leye_example/Eyefile +10 -0
- data/examples/notify.eye +3 -4
- data/examples/plugin/main.eye +5 -5
- data/examples/plugin/plugin.rb +10 -2
- data/examples/process_thin.rb +8 -8
- data/examples/processes/em.rb +18 -12
- data/examples/processes/forking.rb +5 -5
- data/examples/processes/sample.rb +46 -44
- data/examples/puma.eye +9 -8
- data/examples/rbenv.eye +5 -5
- data/examples/sidekiq.eye +3 -3
- data/examples/stress_test.eye +4 -4
- data/examples/syslog.eye +1 -1
- data/examples/test.eye +1 -2
- data/examples/thin-farm.eye +7 -8
- data/examples/triggers.eye +13 -15
- data/examples/unicorn.eye +12 -13
- data/eye.gemspec +16 -14
- data/lib/eye.rb +2 -3
- data/lib/eye/application.rb +5 -6
- data/lib/eye/checker.rb +44 -25
- data/lib/eye/checker/children_count.rb +1 -1
- data/lib/eye/checker/file_ctime.rb +1 -1
- data/lib/eye/checker/http.rb +13 -15
- data/lib/eye/checker/nop.rb +1 -0
- data/lib/eye/checker/socket.rb +60 -63
- data/lib/eye/checker/ssl_socket.rb +5 -5
- data/lib/eye/child_process.rb +6 -4
- data/lib/eye/cli.rb +74 -46
- data/lib/eye/cli/commands.rb +4 -5
- data/lib/eye/cli/render.rb +61 -41
- data/lib/eye/cli/server.rb +19 -16
- data/lib/eye/client.rb +1 -0
- data/lib/eye/config.rb +36 -33
- data/lib/eye/controller.rb +2 -3
- data/lib/eye/controller/commands.rb +1 -1
- data/lib/eye/controller/helpers.rb +2 -2
- data/lib/eye/controller/load.rb +19 -17
- data/lib/eye/controller/options.rb +1 -5
- data/lib/eye/controller/send_command.rb +21 -23
- data/lib/eye/controller/status.rb +17 -14
- data/lib/eye/dsl.rb +6 -1
- data/lib/eye/dsl/application_opts.rb +4 -3
- data/lib/eye/dsl/chain.rb +2 -2
- data/lib/eye/dsl/child_process_opts.rb +3 -3
- data/lib/eye/dsl/config_opts.rb +7 -7
- data/lib/eye/dsl/group_opts.rb +3 -3
- data/lib/eye/dsl/helpers.rb +1 -1
- data/lib/eye/dsl/main.rb +4 -3
- data/lib/eye/dsl/opts.rb +31 -28
- data/lib/eye/dsl/process_opts.rb +13 -7
- data/lib/eye/dsl/pure_opts.rb +13 -9
- data/lib/eye/dsl/validation.rb +48 -35
- data/lib/eye/group.rb +23 -8
- data/lib/eye/group/chain.rb +6 -6
- data/lib/eye/loader.rb +3 -3
- data/lib/eye/local.rb +9 -4
- data/lib/eye/logger.rb +11 -4
- data/lib/eye/notify.rb +10 -6
- data/lib/eye/notify/jabber.rb +1 -1
- data/lib/eye/notify/mail.rb +2 -2
- data/lib/eye/notify/slack.rb +4 -3
- data/lib/eye/process.rb +2 -0
- data/lib/eye/process/children.rb +4 -4
- data/lib/eye/process/commands.rb +38 -39
- data/lib/eye/process/config.rb +22 -16
- data/lib/eye/process/controller.rb +5 -19
- data/lib/eye/process/data.rb +11 -9
- data/lib/eye/process/monitor.rb +86 -76
- data/lib/eye/process/notify.rb +10 -10
- data/lib/eye/process/scheduler.rb +36 -31
- data/lib/eye/process/states.rb +7 -5
- data/lib/eye/process/states_history.rb +9 -3
- data/lib/eye/process/system.rb +35 -20
- data/lib/eye/process/trigger.rb +1 -5
- data/lib/eye/process/watchers.rb +12 -9
- data/lib/eye/reason.rb +4 -1
- data/lib/eye/server.rb +3 -2
- data/lib/eye/system.rb +22 -15
- data/lib/eye/system_resources.rb +17 -8
- data/lib/eye/trigger.rb +18 -16
- data/lib/eye/trigger/check_dependency.rb +7 -4
- data/lib/eye/trigger/flapping.rb +24 -7
- data/lib/eye/trigger/starting_guard.rb +7 -6
- data/lib/eye/trigger/stop_children.rb +2 -2
- data/lib/eye/trigger/transition.rb +1 -1
- data/lib/eye/trigger/wait_dependency.rb +3 -2
- data/lib/eye/utils.rb +4 -3
- data/lib/eye/utils/alive_array.rb +9 -4
- data/lib/eye/utils/celluloid_chain.rb +12 -10
- data/lib/eye/utils/mini_active_support.rb +16 -16
- data/lib/eye/utils/pmap.rb +2 -0
- data/lib/eye/utils/tail.rb +2 -2
- metadata +39 -8
- data/lib/eye/utils/leak_19.rb +0 -10
data/lib/eye/cli/commands.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Eye::Cli::Commands
|
2
|
+
|
2
3
|
private
|
3
4
|
|
4
5
|
def client
|
@@ -39,12 +40,10 @@ private
|
|
39
40
|
def show_load_message(res, opts = {})
|
40
41
|
if res[:error]
|
41
42
|
say res[:message], :red
|
42
|
-
res[:backtrace].to_a.each{|line| say line, :red }
|
43
|
+
res[:backtrace].to_a.each { |line| say line, :red }
|
43
44
|
else
|
44
|
-
|
45
|
-
say 'Config ok!'
|
46
|
-
else
|
47
|
-
say 'Config loaded!', :green if !res[:empty]
|
45
|
+
unless res[:empty]
|
46
|
+
say(opts[:syntax] ? 'Config ok!' : 'Config loaded!', :green)
|
48
47
|
end
|
49
48
|
|
50
49
|
if opts[:print_config]
|
data/lib/eye/cli/render.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
module Eye::Cli::Render
|
2
|
+
|
2
3
|
private
|
4
|
+
|
3
5
|
def render_status(data)
|
4
6
|
return [1, "unexpected server response #{data.inspect}"] unless data.is_a?(Hash)
|
5
7
|
data = data[:subtree]
|
6
|
-
return [1, "match #{data.size} objects (#{data.map{|d| d[:name]}}), but expected only 1 process"] if data.size != 1
|
8
|
+
return [1, "match #{data.size} objects (#{data.map { |d| d[:name] }}), but expected only 1 process"] if data.size != 1
|
7
9
|
process = data[0]
|
8
10
|
return [1, "unknown status for :#{process[:type]}=#{process[:name]}"] unless process[:type] == :process
|
9
11
|
|
@@ -24,37 +26,14 @@ private
|
|
24
26
|
return nil if !data || data.empty?
|
25
27
|
|
26
28
|
if data.is_a?(Array)
|
27
|
-
data.map{|el| make_str(el, level) }.compact * "\n"
|
29
|
+
data.map { |el| make_str(el, level) }.compact * "\n"
|
28
30
|
else
|
29
31
|
str = nil
|
30
32
|
|
31
33
|
if data[:name]
|
32
34
|
return make_str(data[:subtree], level) if data[:name] == '__default__'
|
33
35
|
|
34
|
-
|
35
|
-
off_str = ' ' * off
|
36
|
-
|
37
|
-
short_state = ((data[:type] == :application || data[:type] == :group) && data[:states])
|
38
|
-
is_text = data[:state] || data[:states]
|
39
|
-
|
40
|
-
name = (data[:type] == :application && !is_text) ? "\033[1m#{data[:name]}\033[0m" : data[:name].to_s
|
41
|
-
off_len = 35
|
42
|
-
str = off_str + (name + ' ').ljust(off_len - off, is_text ? '.' : ' ')
|
43
|
-
|
44
|
-
if short_state
|
45
|
-
str += ' ' + data[:states].map { |k, v| "#{k}:#{v}" }.join(', ')
|
46
|
-
elsif data[:state]
|
47
|
-
str += ' ' + data[:state].to_s
|
48
|
-
str += ' (' + resources_str(data[:resources]) + ')' if data[:resources] && data[:state].to_sym == :up
|
49
|
-
str += " (#{data[:state_reason]} at #{Eye::Utils.human_time2(data[:state_changed_at])})" if data[:state_reason] && data[:state] == 'unmonitored'
|
50
|
-
elsif data[:current_command]
|
51
|
-
chain_progress = if data[:chain_progress]
|
52
|
-
" #{data[:chain_progress][0]} of #{data[:chain_progress][1]}" rescue ''
|
53
|
-
end
|
54
|
-
str += " \e[1;33m[#{data[:current_command]}#{chain_progress}]\033[0m"
|
55
|
-
str += " (#{data[:chain_commands] * ', '})" if data[:chain_commands]
|
56
|
-
end
|
57
|
-
|
36
|
+
str = render_element(data, level)
|
58
37
|
end
|
59
38
|
|
60
39
|
if data[:subtree].nil?
|
@@ -67,18 +46,10 @@ private
|
|
67
46
|
end
|
68
47
|
end
|
69
48
|
|
70
|
-
def resources_str(r)
|
71
|
-
return '' if !r || r.empty?
|
72
|
-
memory, cpu, start_time, pid = r[:memory], r[:cpu], r[:start_time], r[:pid]
|
73
|
-
return '' unless memory && cpu && start_time
|
74
|
-
|
75
|
-
"#{Eye::Utils.human_time(start_time)}, #{cpu.to_i}%, #{memory / 1024 / 1024}Mb, <#{pid}>"
|
76
|
-
end
|
77
|
-
|
78
49
|
def render_debug_info(data)
|
79
50
|
error!("unexpected server response #{data.inspect}") unless data.is_a?(Hash)
|
80
51
|
|
81
|
-
s =
|
52
|
+
s = ''
|
82
53
|
|
83
54
|
if config_yaml = data.delete(:config_yaml)
|
84
55
|
s << config_yaml
|
@@ -88,10 +59,10 @@ private
|
|
88
59
|
s << "#{"#{k}:".ljust(10)} "
|
89
60
|
|
90
61
|
case k
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
62
|
+
when :resources
|
63
|
+
s << resources_str(v)
|
64
|
+
else
|
65
|
+
s << "#{v}"
|
95
66
|
end
|
96
67
|
|
97
68
|
s << "\n"
|
@@ -114,10 +85,10 @@ private
|
|
114
85
|
res = "\033[1m#{name}\033[0m\n"
|
115
86
|
history = history.reverse
|
116
87
|
|
117
|
-
history.chunk{|h| [h[:state], h[:reason].to_s] }.each do |_, hist|
|
88
|
+
history.chunk { |h| [h[:state], h[:reason].to_s] }.each do |_, hist|
|
118
89
|
if hist.size >= 3
|
119
90
|
res << detail_process_info_string(hist[0])
|
120
|
-
res << detail_process_info_string(:
|
91
|
+
res << detail_process_info_string(state: "... #{hist.size - 2} times", reason: '...')
|
121
92
|
res << detail_process_info_string(hist[-1])
|
122
93
|
else
|
123
94
|
hist.each do |h|
|
@@ -135,4 +106,53 @@ private
|
|
135
106
|
"#{at} - #{state} (#{h[:reason]})\n"
|
136
107
|
end
|
137
108
|
|
109
|
+
private
|
110
|
+
|
111
|
+
def render_element(data, level)
|
112
|
+
off = level * 2
|
113
|
+
off_str = ' ' * off
|
114
|
+
|
115
|
+
short_state = (data[:type] == :application || data[:type] == :group) && data[:states]
|
116
|
+
is_text = data[:state] || data[:states]
|
117
|
+
|
118
|
+
name = (data[:type] == :application && !is_text) ? "\033[1m#{data[:name]}\033[0m" : data[:name].to_s
|
119
|
+
off_len = 35
|
120
|
+
str = off_str + (name + ' ').ljust(off_len - off, is_text ? '.' : ' ')
|
121
|
+
|
122
|
+
if short_state
|
123
|
+
str += ' ' + data[:states].map { |k, v| "#{k}:#{v}" }.join(', ')
|
124
|
+
elsif data[:state]
|
125
|
+
str += ' ' + data[:state].to_s
|
126
|
+
if data[:resources] && data[:state].to_sym == :up
|
127
|
+
str += ' (' + resources_str(data[:resources])
|
128
|
+
str += ", <#{data[:procline]}>" if data[:procline]
|
129
|
+
str += ')'
|
130
|
+
end
|
131
|
+
if data[:state_reason] && data[:state] == 'unmonitored'
|
132
|
+
str += " (#{data[:state_reason]} at #{Eye::Utils.human_time2(data[:state_changed_at])})"
|
133
|
+
end
|
134
|
+
elsif data[:current_command]
|
135
|
+
chain_progress = if data[:chain_progress]
|
136
|
+
" #{data[:chain_progress][0]} of #{data[:chain_progress][1]}" rescue ''
|
137
|
+
end
|
138
|
+
str += " \e[1;33m[#{data[:current_command]}#{chain_progress}]\033[0m"
|
139
|
+
str += " (#{data[:chain_commands] * ', '})" if data[:chain_commands]
|
140
|
+
end
|
141
|
+
|
142
|
+
str
|
143
|
+
end
|
144
|
+
|
145
|
+
def resources_str(r)
|
146
|
+
return '' if !r || r.empty?
|
147
|
+
|
148
|
+
memory = r[:memory]
|
149
|
+
cpu = r[:cpu]
|
150
|
+
start_time = r[:start_time]
|
151
|
+
pid = r[:pid]
|
152
|
+
|
153
|
+
return '' unless memory && cpu && start_time
|
154
|
+
|
155
|
+
"#{Eye::Utils.human_time(start_time)}, #{cpu.to_i}%, #{memory / 1024 / 1024}Mb, <#{pid}>"
|
156
|
+
end
|
157
|
+
|
138
158
|
end
|
data/lib/eye/cli/server.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Eye::Cli::Server
|
4
|
+
|
4
5
|
private
|
5
6
|
|
6
7
|
def server_started?
|
@@ -26,17 +27,15 @@ private
|
|
26
27
|
ensure_loader_path
|
27
28
|
Eye::Local.ensure_eye_dir
|
28
29
|
|
29
|
-
if server_started?
|
30
|
-
_cmd(:quit) && sleep(1) # stop previous server
|
31
|
-
end
|
32
|
-
|
33
30
|
args = []
|
34
31
|
args += ['--config', conf] if conf
|
35
32
|
args += ['--logger', 'stdout']
|
33
|
+
args += ['--stop_all']
|
36
34
|
if Eye::Local.local_runner
|
37
|
-
args += ['--stop_all']
|
38
35
|
args += ['--dir', Eye::Local.dir]
|
39
|
-
|
36
|
+
if !conf && Eye::Local.eyefile
|
37
|
+
args += ['--config', Eye::Local.eyefile]
|
38
|
+
end
|
40
39
|
end
|
41
40
|
|
42
41
|
Process.exec(ruby_path, loader_path, *args)
|
@@ -51,12 +50,18 @@ private
|
|
51
50
|
args = []
|
52
51
|
args += ['--dir', Eye::Local.dir] if Eye::Local.local_runner
|
53
52
|
|
54
|
-
|
55
|
-
|
53
|
+
chdir = if Eye::Local.local_runner
|
54
|
+
Eye::Local.home
|
55
|
+
else
|
56
|
+
'/'
|
57
|
+
end
|
58
|
+
|
59
|
+
opts = { out: '/dev/null', err: '/dev/null', in: '/dev/null',
|
60
|
+
chdir: chdir, pgroup: true }
|
56
61
|
|
57
62
|
pid = Process.spawn(ruby_path, loader_path, *args, opts)
|
58
63
|
Process.detach(pid)
|
59
|
-
File.open(Eye::Local.pid_path, 'w'){|f| f.write(pid) }
|
64
|
+
File.open(Eye::Local.pid_path, 'w') { |f| f.write(pid) }
|
60
65
|
|
61
66
|
unless wait_server
|
62
67
|
error! 'server has not started in 15 seconds, something is very wrong'
|
@@ -64,11 +69,11 @@ private
|
|
64
69
|
|
65
70
|
configs.unshift(Eye::Local.global_eyeconfig) if File.exist?(Eye::Local.global_eyeconfig)
|
66
71
|
configs.unshift(Eye::Local.eyeconfig) if File.exist?(Eye::Local.eyeconfig)
|
67
|
-
configs << Eye::Local.eyefile if Eye::Local.local_runner
|
72
|
+
configs << Eye::Local.eyefile if Eye::Local.local_runner && Eye::Local.eyefile
|
68
73
|
|
69
|
-
say
|
74
|
+
say "Eye started! ㋡ (#{Eye::Local.home})", :green
|
70
75
|
|
71
|
-
if
|
76
|
+
if configs.any?
|
72
77
|
say_load_result cmd(:load, *configs)
|
73
78
|
end
|
74
79
|
end
|
@@ -76,16 +81,14 @@ private
|
|
76
81
|
def ensure_stop_previous_server
|
77
82
|
Eye::Local.ensure_eye_dir
|
78
83
|
pid = File.read(Eye::Local.pid_path).to_i rescue nil
|
79
|
-
if pid
|
80
|
-
Process.kill(9, pid) rescue nil
|
81
|
-
end
|
84
|
+
Process.kill(9, pid) rescue nil if pid
|
82
85
|
File.delete(Eye::Local.pid_path) rescue nil
|
83
86
|
true
|
84
87
|
end
|
85
88
|
|
86
89
|
def wait_server(timeout = 15)
|
87
90
|
Timeout.timeout(timeout) do
|
88
|
-
sleep 0.3
|
91
|
+
sleep 0.3 until server_started?
|
89
92
|
end
|
90
93
|
true
|
91
94
|
rescue Timeout::Error
|
data/lib/eye/client.rb
CHANGED
data/lib/eye/config.rb
CHANGED
@@ -32,71 +32,74 @@ class Eye::Config
|
|
32
32
|
|
33
33
|
# raise an error if config wrong
|
34
34
|
def validate!(validate_apps = [])
|
35
|
-
all_processes = processes
|
36
|
-
|
37
35
|
# Check blank pid_files
|
38
|
-
no_pid_file =
|
39
|
-
if
|
40
|
-
|
36
|
+
no_pid_file = []
|
37
|
+
each_process { |c| no_pid_file << c if c[:pid_file].blank? }
|
38
|
+
if no_pid_file.any?
|
39
|
+
raise Eye::Dsl::Error, "blank pid_file for: #{no_pid_file.map { |c| c[:name] } * ', '}"
|
41
40
|
end
|
42
41
|
|
43
42
|
# Check duplicates of the full pid_file
|
44
43
|
|
45
|
-
dupl_pids =
|
44
|
+
dupl_pids = Hash.new(0)
|
45
|
+
each_process do |o|
|
46
46
|
ex_pid_file = Eye::System.normalized_file(o[:pid_file], o[:working_dir])
|
47
|
-
|
47
|
+
dupl_pids[ex_pid_file] += 1
|
48
48
|
end
|
49
|
-
dupl_pids = dupl_pids.select{|
|
49
|
+
dupl_pids = dupl_pids.select { |_, v| v > 1 }
|
50
50
|
|
51
|
-
if dupl_pids.
|
51
|
+
if dupl_pids.any?
|
52
52
|
raise Eye::Dsl::Error, "duplicate pid_files: #{dupl_pids.inspect}"
|
53
53
|
end
|
54
54
|
|
55
55
|
# Check duplicates of the full_name
|
56
|
-
dupl_names =
|
56
|
+
dupl_names = Hash.new(0)
|
57
|
+
each_process do |o|
|
57
58
|
full_name = "#{o[:application]}:#{o[:group]}:#{o[:name]}"
|
58
|
-
|
59
|
+
dupl_names[full_name] += 1
|
59
60
|
end
|
60
|
-
dupl_names = dupl_names.select{|
|
61
|
+
dupl_names = dupl_names.select { |_, v| v > 1 }
|
61
62
|
|
62
|
-
if dupl_names.
|
63
|
+
if dupl_names.any?
|
63
64
|
raise Eye::Dsl::Error, "duplicate names: #{dupl_names.inspect}"
|
64
65
|
end
|
65
66
|
|
66
67
|
# validate processes with their own validate
|
67
|
-
|
68
|
+
each_process do |process_cfg|
|
68
69
|
Eye::Process.validate process_cfg, validate_apps.include?(process_cfg[:application])
|
69
70
|
end
|
70
71
|
|
71
72
|
# just to be sure ENV was not removed
|
72
|
-
ENV[''] rescue raise Eye::Dsl::Error
|
73
|
+
ENV[''] rescue raise Eye::Dsl::Error, "ENV is not a hash '#{ENV.inspect}'"
|
73
74
|
end
|
74
75
|
|
75
76
|
def transform!
|
76
|
-
all_processes = processes
|
77
|
-
|
78
77
|
# transform syslog option
|
79
|
-
|
78
|
+
each_process do |process|
|
80
79
|
out = process[:stdout] && process[:stdout].start_with?(':syslog')
|
81
80
|
err = process[:stderr] && process[:stderr].start_with?(':syslog')
|
82
|
-
|
83
|
-
redir = err ? '2>&1' : ''
|
84
|
-
process[:stdout] = nil if out
|
85
|
-
process[:stderr] = nil if err
|
81
|
+
next unless err || out
|
86
82
|
|
87
|
-
|
83
|
+
redir = err ? '2>&1' : ''
|
84
|
+
process[:stdout] = nil if out
|
85
|
+
process[:stderr] = nil if err
|
88
86
|
|
89
|
-
|
90
|
-
logger = "logger -t \"#{names.join(':')}\""
|
87
|
+
escaped_start_command = process[:start_command].to_s.gsub(%{"}, %{\\"})
|
91
88
|
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
names = [process[:application], process[:group] == '__default__' ? nil : process[:group], process[:name]].compact
|
90
|
+
logger = "logger -t \"#{names.join(':')}\""
|
91
|
+
|
92
|
+
process[:start_command] = %{sh -c "#{escaped_start_command} #{redir} | #{logger}"}
|
93
|
+
process[:use_leaf_child] = true if process[:daemonize]
|
95
94
|
end
|
96
95
|
end
|
97
96
|
|
98
|
-
def
|
99
|
-
applications.
|
97
|
+
def each_process(&block)
|
98
|
+
applications.each_value do |app_cfg|
|
99
|
+
(app_cfg[:groups] || {}).each_value do |gr_cfg|
|
100
|
+
(gr_cfg[:processes] || {}).each_value(&block)
|
101
|
+
end
|
102
|
+
end
|
100
103
|
end
|
101
104
|
|
102
105
|
def application_names
|
@@ -108,14 +111,14 @@ class Eye::Config
|
|
108
111
|
end
|
109
112
|
|
110
113
|
def delete_group(name)
|
111
|
-
applications.each do |
|
114
|
+
applications.each do |_app_name, app_cfg|
|
112
115
|
(app_cfg[:groups] || {}).delete(name)
|
113
116
|
end
|
114
117
|
end
|
115
118
|
|
116
119
|
def delete_process(name)
|
117
|
-
applications.each do |
|
118
|
-
(app_cfg[:groups] || {}).each do |
|
120
|
+
applications.each do |_app_name, app_cfg|
|
121
|
+
(app_cfg[:groups] || {}).each do |_gr_name, gr_cfg|
|
119
122
|
(gr_cfg[:processes] || {}).delete(name)
|
120
123
|
end
|
121
124
|
end
|
data/lib/eye/controller.rb
CHANGED
@@ -2,8 +2,6 @@ require 'celluloid'
|
|
2
2
|
require 'yaml'
|
3
3
|
|
4
4
|
require_relative 'utils/pmap'
|
5
|
-
|
6
|
-
require_relative 'utils/leak_19'
|
7
5
|
require_relative 'utils/mini_active_support'
|
8
6
|
|
9
7
|
# Extend all objects with logger
|
@@ -14,6 +12,7 @@ Eye::Sigar
|
|
14
12
|
Eye::SystemResources
|
15
13
|
|
16
14
|
class Eye::Controller
|
15
|
+
|
17
16
|
include Celluloid
|
18
17
|
|
19
18
|
autoload :Load, 'eye/controller/load'
|
@@ -36,7 +35,7 @@ class Eye::Controller
|
|
36
35
|
@applications = []
|
37
36
|
@current_config = Eye::Config.new
|
38
37
|
|
39
|
-
Celluloid
|
38
|
+
Celluloid.logger = Eye::Logger.new('celluloid')
|
40
39
|
|
41
40
|
info "starting #{Eye::ABOUT} <#{$$}>"
|
42
41
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Eye::Controller::Commands
|
2
2
|
|
3
3
|
NOT_IMPORTANT_COMMANDS = [:info_data, :short_data, :debug_data, :history_data, :ping,
|
4
|
-
|
4
|
+
:logger_dev, :match, :explain, :check]
|
5
5
|
|
6
6
|
# Main method, answer for the client command
|
7
7
|
def command(cmd, *args)
|
@@ -5,7 +5,7 @@ module Eye::Controller::Helpers
|
|
5
5
|
str = 'l' + str if Eye::Local.local_runner
|
6
6
|
str += " [#{@applications.map(&:name) * ', '}]" if @applications.present?
|
7
7
|
str += " (v #{ENV['EYE_V']})" if ENV['EYE_V']
|
8
|
-
str += " (in #{Eye::Local.
|
8
|
+
str += " (in #{Eye::Local.home})"
|
9
9
|
$0 = str
|
10
10
|
end
|
11
11
|
|
@@ -16,7 +16,7 @@ module Eye::Controller::Helpers
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def cache_str
|
19
|
-
all_processes.map{ |p| "#{p.full_name}=#{p.state}" } * "\n"
|
19
|
+
all_processes.map { |p| "#{p.full_name}=#{p.state}" } * "\n"
|
20
20
|
end
|
21
21
|
|
22
22
|
def process_by_name(name)
|
data/lib/eye/controller/load.rb
CHANGED
@@ -13,7 +13,7 @@ module Eye::Controller::Load
|
|
13
13
|
obj_strs = args.flatten
|
14
14
|
info "=> loading: #{obj_strs}"
|
15
15
|
|
16
|
-
res =
|
16
|
+
res = {}
|
17
17
|
|
18
18
|
globbing(*obj_strs).each do |filename|
|
19
19
|
res[filename] = catch_load_error(filename) do
|
@@ -35,8 +35,8 @@ private
|
|
35
35
|
# regexp for clean backtrace to show for user
|
36
36
|
BT_REGX = %r[/lib/eye/|lib/celluloid|internal:prelude|logger.rb:|active_support/core_ext|shellwords.rb|kernel/bootstrap].freeze
|
37
37
|
|
38
|
-
def catch_load_error(filename = nil, &
|
39
|
-
{ :
|
38
|
+
def catch_load_error(filename = nil, &_block)
|
39
|
+
{ error: false, config: yield }
|
40
40
|
|
41
41
|
rescue Eye::Dsl::Error, Exception, NoMethodError => ex
|
42
42
|
raise if ex.class.to_s.include?('RR') # skip RR exceptions
|
@@ -45,10 +45,10 @@ private
|
|
45
45
|
|
46
46
|
# filter backtrace for user output
|
47
47
|
bt = (ex.backtrace || [])
|
48
|
-
bt = bt.reject{|line| line.to_s =~ BT_REGX } unless ENV['EYE_FULL_BACKTRACE']
|
48
|
+
bt = bt.reject { |line| line.to_s =~ BT_REGX } unless ENV['EYE_FULL_BACKTRACE']
|
49
49
|
error bt.join("\n")
|
50
50
|
|
51
|
-
res = { :
|
51
|
+
res = { error: true, message: ex.message }
|
52
52
|
res[:backtrace] = bt if bt.present?
|
53
53
|
res
|
54
54
|
end
|
@@ -58,6 +58,8 @@ private
|
|
58
58
|
return res if obj_strs.empty?
|
59
59
|
|
60
60
|
obj_strs.each do |filename|
|
61
|
+
next unless filename
|
62
|
+
|
61
63
|
mask = File.directory?(filename) ? File.join(filename, '{*.eye}') : filename
|
62
64
|
debug { "loading: globbing mask #{mask}" }
|
63
65
|
|
@@ -76,11 +78,7 @@ private
|
|
76
78
|
# return: result, config
|
77
79
|
def parse_config(filename)
|
78
80
|
debug { "parsing: #{filename}" }
|
79
|
-
|
80
|
-
cfg = Eye::Dsl.parse(nil, filename)
|
81
|
-
@current_config.merge(cfg).validate! # just validate summary config here
|
82
|
-
Eye.parsed_config = nil # remove link on config, for better gc
|
83
|
-
cfg
|
81
|
+
Eye::Dsl.parse(nil, filename)
|
84
82
|
end
|
85
83
|
|
86
84
|
# !!! exclusive operation
|
@@ -126,7 +124,7 @@ private
|
|
126
124
|
app.groups.each do |group|
|
127
125
|
@old_groups[group.name] = group
|
128
126
|
group.processes.each do |proc|
|
129
|
-
@old_processes[group.name +
|
127
|
+
@old_processes[group.name + ':' + proc.name] = proc
|
130
128
|
end
|
131
129
|
end
|
132
130
|
|
@@ -139,7 +137,8 @@ private
|
|
139
137
|
|
140
138
|
app = Eye::Application.new(app_name, app_config)
|
141
139
|
@applications << app
|
142
|
-
@added_groups
|
140
|
+
@added_groups = []
|
141
|
+
@added_processes = []
|
143
142
|
|
144
143
|
new_groups = app_config.delete(:groups) || {}
|
145
144
|
new_groups.each do |group_name, group_cfg|
|
@@ -149,8 +148,11 @@ private
|
|
149
148
|
end
|
150
149
|
|
151
150
|
# now, need to clear @old_groups, and @old_processes
|
152
|
-
@old_groups.each
|
153
|
-
|
151
|
+
@old_groups.each do |_, group|
|
152
|
+
group.clear
|
153
|
+
group.send_command(:delete)
|
154
|
+
end
|
155
|
+
@old_processes.each { |_, process| process.send_command(:delete) if process.alive? }
|
154
156
|
|
155
157
|
# schedule monitoring for new groups, processes
|
156
158
|
added_fully_groups = []
|
@@ -161,8 +163,8 @@ private
|
|
161
163
|
end
|
162
164
|
end
|
163
165
|
|
164
|
-
added_fully_groups.each{|group| group.send_command :monitor }
|
165
|
-
@added_processes.each{|process| process.send_command :monitor }
|
166
|
+
added_fully_groups.each { |group| group.send_command :monitor }
|
167
|
+
@added_processes.each { |process| process.send_command :monitor }
|
166
168
|
|
167
169
|
# remove links to prevent memory leaks
|
168
170
|
@old_groups = nil
|
@@ -199,7 +201,7 @@ private
|
|
199
201
|
end
|
200
202
|
|
201
203
|
def update_or_create_process(process_name, process_cfg)
|
202
|
-
postfix =
|
204
|
+
postfix = ':' + process_name
|
203
205
|
name = process_cfg[:group] + postfix
|
204
206
|
key = @old_processes[name] ? name : @old_processes.keys.detect { |n| n.end_with?(postfix) }
|
205
207
|
|