eye 0.8.celluloid15 → 0.8.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -5
  3. data/CHANGES.md +3 -7
  4. data/README.md +2 -5
  5. data/Rakefile +6 -6
  6. data/bin/leye +4 -9
  7. data/bin/loader_eye +15 -14
  8. data/examples/delayed_job.eye +3 -3
  9. data/examples/dependency.eye +11 -10
  10. data/examples/notify.eye +4 -3
  11. data/examples/plugin/main.eye +5 -5
  12. data/examples/plugin/plugin.rb +2 -10
  13. data/examples/process_thin.rb +8 -8
  14. data/examples/processes/em.rb +12 -18
  15. data/examples/processes/forking.rb +5 -5
  16. data/examples/processes/sample.rb +44 -46
  17. data/examples/puma.eye +8 -9
  18. data/examples/rbenv.eye +5 -5
  19. data/examples/sidekiq.eye +3 -3
  20. data/examples/stress_test.eye +4 -4
  21. data/examples/syslog.eye +1 -1
  22. data/examples/test.eye +2 -1
  23. data/examples/thin-farm.eye +8 -7
  24. data/examples/triggers.eye +15 -13
  25. data/examples/unicorn.eye +13 -12
  26. data/eye.gemspec +14 -16
  27. data/lib/eye.rb +3 -2
  28. data/lib/eye/application.rb +6 -5
  29. data/lib/eye/checker.rb +25 -44
  30. data/lib/eye/checker/children_count.rb +1 -1
  31. data/lib/eye/checker/file_ctime.rb +1 -1
  32. data/lib/eye/checker/http.rb +15 -13
  33. data/lib/eye/checker/nop.rb +0 -1
  34. data/lib/eye/checker/socket.rb +63 -60
  35. data/lib/eye/checker/ssl_socket.rb +5 -5
  36. data/lib/eye/child_process.rb +4 -6
  37. data/lib/eye/cli.rb +46 -74
  38. data/lib/eye/cli/commands.rb +5 -4
  39. data/lib/eye/cli/render.rb +41 -61
  40. data/lib/eye/cli/server.rb +16 -19
  41. data/lib/eye/client.rb +0 -1
  42. data/lib/eye/config.rb +33 -36
  43. data/lib/eye/controller.rb +3 -2
  44. data/lib/eye/controller/commands.rb +1 -1
  45. data/lib/eye/controller/helpers.rb +2 -2
  46. data/lib/eye/controller/load.rb +17 -19
  47. data/lib/eye/controller/options.rb +5 -1
  48. data/lib/eye/controller/send_command.rb +23 -21
  49. data/lib/eye/controller/status.rb +15 -17
  50. data/lib/eye/dsl.rb +1 -6
  51. data/lib/eye/dsl/application_opts.rb +3 -4
  52. data/lib/eye/dsl/chain.rb +2 -2
  53. data/lib/eye/dsl/child_process_opts.rb +3 -3
  54. data/lib/eye/dsl/config_opts.rb +7 -7
  55. data/lib/eye/dsl/group_opts.rb +3 -3
  56. data/lib/eye/dsl/helpers.rb +1 -1
  57. data/lib/eye/dsl/main.rb +3 -4
  58. data/lib/eye/dsl/opts.rb +28 -31
  59. data/lib/eye/dsl/process_opts.rb +7 -13
  60. data/lib/eye/dsl/pure_opts.rb +9 -13
  61. data/lib/eye/dsl/validation.rb +35 -48
  62. data/lib/eye/group.rb +8 -23
  63. data/lib/eye/group/chain.rb +6 -6
  64. data/lib/eye/loader.rb +3 -3
  65. data/lib/eye/local.rb +4 -9
  66. data/lib/eye/logger.rb +4 -11
  67. data/lib/eye/notify.rb +6 -10
  68. data/lib/eye/notify/jabber.rb +1 -1
  69. data/lib/eye/notify/mail.rb +2 -2
  70. data/lib/eye/notify/slack.rb +3 -4
  71. data/lib/eye/process.rb +0 -2
  72. data/lib/eye/process/children.rb +4 -4
  73. data/lib/eye/process/commands.rb +39 -38
  74. data/lib/eye/process/config.rb +16 -22
  75. data/lib/eye/process/controller.rb +19 -5
  76. data/lib/eye/process/data.rb +9 -11
  77. data/lib/eye/process/monitor.rb +76 -86
  78. data/lib/eye/process/notify.rb +10 -10
  79. data/lib/eye/process/scheduler.rb +31 -36
  80. data/lib/eye/process/states.rb +5 -7
  81. data/lib/eye/process/states_history.rb +3 -9
  82. data/lib/eye/process/system.rb +20 -35
  83. data/lib/eye/process/trigger.rb +5 -1
  84. data/lib/eye/process/watchers.rb +9 -12
  85. data/lib/eye/reason.rb +1 -4
  86. data/lib/eye/server.rb +1 -2
  87. data/lib/eye/system.rb +15 -22
  88. data/lib/eye/system_resources.rb +9 -18
  89. data/lib/eye/trigger.rb +16 -18
  90. data/lib/eye/trigger/check_dependency.rb +4 -7
  91. data/lib/eye/trigger/flapping.rb +7 -24
  92. data/lib/eye/trigger/starting_guard.rb +6 -7
  93. data/lib/eye/trigger/stop_children.rb +2 -2
  94. data/lib/eye/trigger/transition.rb +1 -1
  95. data/lib/eye/trigger/wait_dependency.rb +2 -3
  96. data/lib/eye/utils.rb +3 -4
  97. data/lib/eye/utils/alive_array.rb +4 -9
  98. data/lib/eye/utils/celluloid_chain.rb +10 -12
  99. data/lib/eye/utils/leak_19.rb +10 -0
  100. data/lib/eye/utils/mini_active_support.rb +16 -16
  101. data/lib/eye/utils/pmap.rb +0 -2
  102. data/lib/eye/utils/tail.rb +2 -2
  103. metadata +8 -39
  104. data/.rubocop.yml +0 -141
  105. data/examples/custom_check.eye +0 -24
  106. data/examples/custom_trigger.eye +0 -30
  107. data/examples/leye_example/Eyefile +0 -10
@@ -1,16 +1,17 @@
1
1
  require 'openssl'
2
2
 
3
3
  class Eye::Checker::SslSocket < Eye::Checker::Socket
4
+ param :ctx, Hash, nil, {ssl_version: :SSLv23, verify_mode: OpenSSL::SSL::VERIFY_NONE}
4
5
 
5
- # ctx params from http://ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
6
+ # other params inherits from socket check
6
7
  #
7
8
  # examples:
8
9
  #
9
10
  # check :ssl_socket, :addr => "tcp://127.0.0.1:443", :every => 5.seconds, :times => 1, :timeout => 1.second,
10
11
  # :ctx => {ssl_version: :SSLv23, verify_mode: OpenSSL::SSL::VERIFY_NONE}
11
12
  #
12
-
13
- param :ctx, Hash, nil, ssl_version: :SSLv23, verify_mode: OpenSSL::SSL::VERIFY_NONE
13
+ #
14
+ # ctx_params from http://ruby-doc.org/stdlib-1.9.3/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
14
15
 
15
16
  private
16
17
 
@@ -22,7 +23,6 @@ private
22
23
  end
23
24
 
24
25
  def ctx_params
25
- @ctx_params ||= OpenSSL::SSL::SSLContext.new.tap { |c| c.set_params(ctx) }
26
+ @ctx_params ||= OpenSSL::SSL::SSLContext.new().tap { |c| c.set_params(ctx) }
26
27
  end
27
-
28
28
  end
@@ -1,7 +1,6 @@
1
1
  require 'celluloid'
2
2
 
3
3
  class Eye::ChildProcess
4
-
5
4
  include Celluloid
6
5
 
7
6
  # needs: kill_process
@@ -34,7 +33,7 @@ class Eye::ChildProcess
34
33
  @parent = parent
35
34
  @config = prepare_config(config)
36
35
  @name = "child-#{pid}"
37
- @full_name = [logger_prefix, @name].join(':')
36
+ @full_name = [logger_prefix, @name] * ':'
38
37
 
39
38
  @watchers = {}
40
39
 
@@ -89,15 +88,14 @@ class Eye::ChildProcess
89
88
  end
90
89
 
91
90
  def signal(sig)
92
- send_signal(sig) if pid
91
+ send_signal(sig) if self.pid
93
92
  end
94
93
 
95
- def status_data(opts = {})
96
- self_status_data(opts)
94
+ def status_data(debug = false)
95
+ self_status_data(debug)
97
96
  end
98
97
 
99
98
  def prepare_command(command) # override
100
99
  super.gsub('{PARENT_PID}', @parent.pid.to_s)
101
100
  end
102
-
103
101
  end
@@ -4,7 +4,6 @@ gem 'thor'
4
4
  require 'thor'
5
5
 
6
6
  class Eye::Cli < Thor
7
-
8
7
  autoload :Server, 'eye/cli/server'
9
8
  autoload :Commands, 'eye/cli/commands'
10
9
  autoload :Render, 'eye/cli/render'
@@ -13,27 +12,24 @@ class Eye::Cli < Thor
13
12
  include Eye::Cli::Commands
14
13
  include Eye::Cli::Render
15
14
 
16
- desc 'info [MASK]', 'processes info'
17
- method_option :json, type: :boolean, aliases: '-j'
18
- method_option :procline, type: :boolean, aliases: '-p'
15
+ desc "info [MASK]", "processes info"
16
+ method_option :json, :type => :boolean, :aliases => "-j"
19
17
  def info(mask = nil)
20
- h = {}
21
- h[:procline] = true if options[:procline]
22
-
23
- res = cmd(:info_data, *Array(mask), h)
18
+ res = cmd(:info_data, *Array(mask))
24
19
  if mask && res[:subtree] && res[:subtree].empty?
25
- error!('command :info, objects not found!')
20
+ error!("command :info, objects not found!")
26
21
  end
27
22
 
28
23
  if options[:json]
29
- say_json(res)
24
+ require 'json'
25
+ say JSON.dump(res)
30
26
  else
31
27
  say render_info(res)
32
28
  say
33
29
  end
34
30
  end
35
31
 
36
- desc 'status NAME', 'return exit status for process name 0-up, 3-unmonitored'
32
+ desc "status NAME", "return exit status for process name 0-up, 3-unmonitored"
37
33
  def status(name)
38
34
  res = cmd(:info_data, *Array(name))
39
35
  es, msg = render_status(res)
@@ -41,58 +37,43 @@ class Eye::Cli < Thor
41
37
  exit(es)
42
38
  end
43
39
 
44
- desc 'xinfo', 'eye-deamon info (-c show current config)'
45
- method_option :config, type: :boolean, aliases: '-c'
46
- method_option :json, type: :boolean, aliases: '-j'
40
+ desc "xinfo", "eye-deamon info (-c show current config)"
41
+ method_option :config, :type => :boolean, :aliases => "-c"
47
42
  def xinfo
48
- res = cmd(:debug_data, config: options[:config])
49
- if options[:json]
50
- say_json(res)
51
- else
52
- say render_debug_info(res)
53
- say
54
- end
43
+ res = cmd(:debug_data, :config => options[:config])
44
+ say render_debug_info(res)
45
+ say
55
46
  end
56
47
 
57
- desc 'oinfo', 'onelined info'
58
- method_option :json, type: :boolean, aliases: '-j'
48
+ desc "oinfo", "onelined info"
59
49
  def oinfo(mask = nil)
60
50
  res = cmd(:short_data, *Array(mask))
61
- if options[:json]
62
- say_json(res)
63
- else
64
- say render_info(res)
65
- say
66
- end
51
+ say render_info(res)
52
+ say
67
53
  end
68
54
 
69
- desc 'history [MASK,...]', 'processes history'
70
- method_option :json, type: :boolean, aliases: '-j'
55
+ desc "history [MASK,...]", "processes history"
71
56
  def history(*masks)
72
57
  res = cmd(:history_data, *masks)
73
58
  if !masks.empty? && res && res.empty?
74
- error!('command :history, objects not found!')
75
- end
76
- if options[:json]
77
- say_json(res)
78
- else
79
- say render_history(res)
80
- say
59
+ error!("command :history, objects not found!")
81
60
  end
61
+ say render_history(res)
62
+ say
82
63
  end
83
64
 
84
- desc 'load [CONF, ...]', 'load config (run eye-daemon if not) (-f foreground load)'
85
- method_option :foreground, type: :boolean, aliases: '-f'
65
+ desc "load [CONF, ...]", "load config (run eye-daemon if not) (-f foreground load)"
66
+ method_option :foreground, :type => :boolean, :aliases => "-f"
86
67
  def load(*configs)
87
- configs.map! { |c| File.expand_path(c) }
68
+ configs.map!{ |c| File.expand_path(c) } if !configs.empty?
88
69
 
89
70
  if options[:foreground]
90
71
  # in foreground we stop another server, and run just 1 current config version
91
- error!('foreground expected only one config') if configs.size > 1
72
+ error!("foreground expected only one config") if configs.size > 1
92
73
  server_start_foreground(configs.first)
93
74
 
94
75
  elsif server_started?
95
- configs << Eye::Local.eyefile if Eye::Local.local_runner && configs.empty? && Eye::Local.eyefile
76
+ configs << Eye::Local.eyefile if Eye::Local.local_runner
96
77
  say_load_result cmd(:load, *configs)
97
78
 
98
79
  else
@@ -101,9 +82,9 @@ class Eye::Cli < Thor
101
82
  end
102
83
  end
103
84
 
104
- desc 'quit', 'eye-daemon quit'
105
- method_option :stop_all, type: :boolean, aliases: '-s'
106
- method_option :timeout, type: :string, aliases: '-t', default: '600'
85
+ desc "quit", "eye-daemon quit"
86
+ method_option :stop_all, :type => :boolean, :aliases => "-s"
87
+ method_option :timeout, :type => :string, :aliases => "-t", :default => "600"
107
88
  def quit
108
89
  if options[:stop_all]
109
90
  Eye::Local.client_timeout = options[:timeout].to_i
@@ -119,7 +100,7 @@ class Eye::Cli < Thor
119
100
  # remove pid_file
120
101
  File.delete(Eye::Local.pid_path) if File.exist?(Eye::Local.pid_path)
121
102
 
122
- say "Eye quit ಠ╭╮ಠ (#{Eye::Local.home})", :yellow
103
+ say "Quit ಠ╭╮ಠ", :yellow
123
104
  end
124
105
 
125
106
  [:start, :stop, :restart, :unmonitor, :monitor, :delete, :match].each do |command|
@@ -129,61 +110,60 @@ class Eye::Cli < Thor
129
110
  end
130
111
  end
131
112
 
132
- desc 'force_restart MASK[,...]', 'restart by stop;start (not by restart_command)'
113
+ desc "force_restart MASK[,...]", "restart by stop;start (not by restart_command)"
133
114
  def force_restart(*masks)
134
115
  send_command(:stop, *masks)
135
116
  send_command(:start, *masks)
136
117
  end
137
118
 
138
- desc 'signal SIG MASK[,...]', 'send signal to app,group or process'
119
+ desc "signal SIG MASK[,...]", "send signal to app,group or process"
139
120
  def signal(sig, *masks)
140
121
  send_command(:signal, sig, *masks)
141
122
  end
142
123
 
143
- desc 'break MASK[,...]', 'break chain executing'
124
+ desc "break MASK[,...]", "break chain executing"
144
125
  def break(*masks)
145
126
  send_command(:break_chain, *masks)
146
127
  end
147
128
 
148
- desc 'trace [MASK]', 'tracing log(tail + grep) for app,group or process'
149
- def trace(mask = '')
129
+ desc "trace [MASK]", "tracing log(tail + grep) for app,group or process"
130
+ def trace(mask = "")
150
131
  log_trace(mask)
151
132
  end
152
133
 
153
- map ['-v', '--version'] => :version
154
- desc 'version', 'version'
134
+ map ["-v", "--version"] => :version
135
+ desc "version", "version"
155
136
  def version
156
137
  say Eye::ABOUT
157
138
  end
158
139
 
159
- desc 'check CONF', 'check config file syntax'
160
- method_option :host, type: :string, aliases: '-h'
161
- method_option :verbose, type: :boolean, aliases: '-v'
140
+ desc "check CONF", "check config file syntax"
141
+ method_option :host, :type => :string, :aliases => "-h"
142
+ method_option :verbose, :type => :boolean, :aliases => "-v"
162
143
  def check(conf)
163
144
  conf = File.expand_path(conf) if conf && !conf.empty?
164
145
 
165
146
  Eye::Local.host = options[:host] if options[:host]
166
147
  Eye::Dsl.verbose = options[:verbose]
167
148
 
168
- say_load_result Eye::Controller.new.check(conf), syntax: true
149
+ say_load_result Eye::Controller.new.check(conf), :syntax => true
169
150
  end
170
151
 
171
- desc 'explain CONF', 'explain config tree'
172
- method_option :host, type: :string, aliases: '-h'
173
- method_option :verbose, type: :boolean, aliases: '-v'
152
+ desc "explain CONF", "explain config tree"
153
+ method_option :host, :type => :string, :aliases => "-h"
154
+ method_option :verbose, :type => :boolean, :aliases => "-v"
174
155
  def explain(conf)
175
156
  conf = File.expand_path(conf) if conf && !conf.empty?
176
157
 
177
158
  Eye::Local.host = options[:host] if options[:host]
178
159
  Eye::Dsl.verbose = options[:verbose]
179
160
 
180
- say_load_result Eye::Controller.new.explain(conf), print_config: true, syntax: true
161
+ say_load_result Eye::Controller.new.explain(conf), :print_config => true, :syntax => true
181
162
  end
182
163
 
183
- desc 'watch [MASK]', 'interactive processes info'
184
- method_option :procline, type: :boolean, aliases: '-p'
164
+ desc "watch [MASK]", "interactive processes info"
185
165
  def watch(*args)
186
- error!('You should install watch utility') if `which watch`.empty?
166
+ error!("You should install watch utility") if `which watch`.empty?
187
167
 
188
168
  cmd = if `watch --version 2>&1`.chop > '0.2.0'
189
169
  "watch -n 1 --color #{$0} i #{args * ' '}"
@@ -191,14 +171,12 @@ class Eye::Cli < Thor
191
171
  "watch -n 1 #{$0} i #{args * ' '}"
192
172
  end
193
173
 
194
- cmd += ' -p' if options[:procline]
195
-
196
174
  pid = Process.spawn(cmd)
197
175
  Process.waitpid(pid)
198
176
  rescue Interrupt
199
177
  end
200
178
 
201
- desc 'user_command CMD [MASK]', 'execute user_command (dsl command)'
179
+ desc "user_command CMD [MASK]", "execute user_command (dsl command)"
202
180
  def user_command(cmd, *args)
203
181
  send_command(:user_command, cmd, *args)
204
182
  end
@@ -224,13 +202,7 @@ private
224
202
  end
225
203
  end
226
204
 
227
- def say_json(obj)
228
- require 'json'
229
- say JSON.dump(obj)
230
- end
231
-
232
205
  def self.exit_on_failure?
233
206
  true
234
207
  end
235
-
236
208
  end
@@ -1,5 +1,4 @@
1
1
  module Eye::Cli::Commands
2
-
3
2
  private
4
3
 
5
4
  def client
@@ -40,10 +39,12 @@ private
40
39
  def show_load_message(res, opts = {})
41
40
  if res[:error]
42
41
  say res[:message], :red
43
- res[:backtrace].to_a.each { |line| say line, :red }
42
+ res[:backtrace].to_a.each{|line| say line, :red }
44
43
  else
45
- unless res[:empty]
46
- say(opts[:syntax] ? 'Config ok!' : 'Config loaded!', :green)
44
+ if opts[:syntax]
45
+ say 'Config ok!', :green if !res[:empty]
46
+ else
47
+ say 'Config loaded!', :green if !res[:empty]
47
48
  end
48
49
 
49
50
  if opts[:print_config]
@@ -1,11 +1,9 @@
1
1
  module Eye::Cli::Render
2
-
3
2
  private
4
-
5
3
  def render_status(data)
6
4
  return [1, "unexpected server response #{data.inspect}"] unless data.is_a?(Hash)
7
5
  data = data[:subtree]
8
- return [1, "match #{data.size} objects (#{data.map { |d| d[:name] }}), but expected only 1 process"] if data.size != 1
6
+ return [1, "match #{data.size} objects (#{data.map{|d| d[:name]}}), but expected only 1 process"] if data.size != 1
9
7
  process = data[0]
10
8
  return [1, "unknown status for :#{process[:type]}=#{process[:name]}"] unless process[:type] == :process
11
9
 
@@ -26,14 +24,37 @@ private
26
24
  return nil if !data || data.empty?
27
25
 
28
26
  if data.is_a?(Array)
29
- data.map { |el| make_str(el, level) }.compact * "\n"
27
+ data.map{|el| make_str(el, level) }.compact * "\n"
30
28
  else
31
29
  str = nil
32
30
 
33
31
  if data[:name]
34
32
  return make_str(data[:subtree], level) if data[:name] == '__default__'
35
33
 
36
- str = render_element(data, level)
34
+ off = level * 2
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
+
37
58
  end
38
59
 
39
60
  if data[:subtree].nil?
@@ -46,10 +67,18 @@ private
46
67
  end
47
68
  end
48
69
 
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
+
49
78
  def render_debug_info(data)
50
79
  error!("unexpected server response #{data.inspect}") unless data.is_a?(Hash)
51
80
 
52
- s = ''
81
+ s = ""
53
82
 
54
83
  if config_yaml = data.delete(:config_yaml)
55
84
  s << config_yaml
@@ -59,10 +88,10 @@ private
59
88
  s << "#{"#{k}:".ljust(10)} "
60
89
 
61
90
  case k
62
- when :resources
63
- s << resources_str(v)
64
- else
65
- s << "#{v}"
91
+ when :resources
92
+ s << resources_str(v)
93
+ else
94
+ s << "#{v}"
66
95
  end
67
96
 
68
97
  s << "\n"
@@ -85,10 +114,10 @@ private
85
114
  res = "\033[1m#{name}\033[0m\n"
86
115
  history = history.reverse
87
116
 
88
- history.chunk { |h| [h[:state], h[:reason].to_s] }.each do |_, hist|
117
+ history.chunk{|h| [h[:state], h[:reason].to_s] }.each do |_, hist|
89
118
  if hist.size >= 3
90
119
  res << detail_process_info_string(hist[0])
91
- res << detail_process_info_string(state: "... #{hist.size - 2} times", reason: '...')
120
+ res << detail_process_info_string(:state => "... #{hist.size - 2} times", :reason => '...')
92
121
  res << detail_process_info_string(hist[-1])
93
122
  else
94
123
  hist.each do |h|
@@ -106,53 +135,4 @@ private
106
135
  "#{at} - #{state} (#{h[:reason]})\n"
107
136
  end
108
137
 
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
-
158
138
  end