reel-eye 0.4.1 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +4 -0
  4. data/CHANGES.md +17 -1
  5. data/README.md +3 -3
  6. data/Rakefile +8 -0
  7. data/bin/eye +0 -316
  8. data/bin/loader_eye +3 -3
  9. data/examples/test.eye +2 -2
  10. data/eye.gemspec +6 -10
  11. data/lib/eye.rb +4 -2
  12. data/lib/eye/application.rb +3 -3
  13. data/lib/eye/checker.rb +35 -7
  14. data/lib/eye/checker/cputime.rb +23 -0
  15. data/lib/eye/checker/file_touched.rb +15 -0
  16. data/lib/eye/checker/http.rb +7 -9
  17. data/lib/eye/checker/memory.rb +1 -1
  18. data/lib/eye/checker/runtime.rb +28 -0
  19. data/lib/eye/checker/socket.rb +4 -4
  20. data/lib/eye/cli.rb +166 -0
  21. data/lib/eye/cli/commands.rb +79 -0
  22. data/lib/eye/cli/render.rb +137 -0
  23. data/lib/eye/cli/server.rb +85 -0
  24. data/lib/eye/client.rb +3 -3
  25. data/lib/eye/config.rb +17 -14
  26. data/lib/eye/controller.rb +6 -10
  27. data/lib/eye/controller/commands.rb +6 -10
  28. data/lib/eye/controller/helpers.rb +1 -1
  29. data/lib/eye/controller/send_command.rb +5 -2
  30. data/lib/eye/controller/status.rb +38 -106
  31. data/lib/eye/dsl.rb +1 -1
  32. data/lib/eye/dsl/application_opts.rb +6 -2
  33. data/lib/eye/dsl/child_process_opts.rb +3 -2
  34. data/lib/eye/dsl/config_opts.rb +2 -2
  35. data/lib/eye/dsl/group_opts.rb +2 -1
  36. data/lib/eye/dsl/main.rb +4 -2
  37. data/lib/eye/dsl/opts.rb +11 -4
  38. data/lib/eye/dsl/validation.rb +49 -43
  39. data/lib/eye/group.rb +1 -1
  40. data/lib/eye/http.rb +4 -9
  41. data/lib/eye/http/router.rb +1 -1
  42. data/lib/eye/loader.rb +5 -9
  43. data/lib/eye/{settings.rb → local.rb} +1 -1
  44. data/lib/eye/logger.rb +5 -0
  45. data/lib/eye/notify.rb +12 -6
  46. data/lib/eye/notify/jabber.rb +2 -2
  47. data/lib/eye/process/child.rb +3 -1
  48. data/lib/eye/process/commands.rb +2 -2
  49. data/lib/eye/process/controller.rb +1 -1
  50. data/lib/eye/process/trigger.rb +1 -1
  51. data/lib/eye/sigar.rb +5 -0
  52. data/lib/eye/system.rb +8 -7
  53. data/lib/eye/system_resources.rb +46 -41
  54. data/lib/eye/trigger.rb +15 -8
  55. data/lib/eye/trigger/flapping.rb +1 -1
  56. data/lib/eye/trigger/stop_childs.rb +1 -1
  57. data/lib/eye/trigger/transition.rb +15 -0
  58. data/lib/eye/utils.rb +12 -0
  59. data/lib/eye/utils/leak_19.rb +7 -0
  60. data/lib/eye/utils/mini_active_support.rb +106 -0
  61. metadata +40 -17
  62. data/lib/eye/controller/show_history.rb +0 -63
  63. data/lib/eye/trigger/state.rb +0 -11
@@ -8,7 +8,7 @@ module Eye::Controller::Helpers
8
8
  end
9
9
 
10
10
  def save_cache
11
- File.open(Eye::Settings.cache_path, 'w') { |f| f.write(cache_str) }
11
+ File.open(Eye::Local.cache_path, 'w') { |f| f.write(cache_str) }
12
12
  rescue => ex
13
13
  log_ex(ex)
14
14
  end
@@ -35,8 +35,11 @@ private
35
35
 
36
36
  rescue Error => ex
37
37
  log_ex(ex)
38
-
39
38
  {:error => ex.message}
39
+
40
+ rescue Celluloid::DeadActorError => ex
41
+ log_ex(ex)
42
+ {:error => "'#{ex.message}', try again!"}
40
43
  end
41
44
 
42
45
  def remove_object_from_tree(obj)
@@ -75,7 +78,7 @@ private
75
78
  end
76
79
 
77
80
  res = Eye::Utils::AliveArray.new
78
- obj_strs.map{|c| c.to_s.split(",")}.flatten.each do |mask|
81
+ obj_strs.map{|c| c.to_s.split(',')}.flatten.each do |mask|
79
82
  objs = find_objects_by_mask(mask.to_s.strip)
80
83
  objs.select! { |obj| obj.app_name == h[:application] } if h[:application]
81
84
  res += objs
@@ -1,51 +1,43 @@
1
1
  module Eye::Controller::Status
2
2
 
3
- def info_string(*args)
4
- make_str(info_data(*args)).to_s
5
- end
6
-
7
- def info_string_short(*args)
8
- make_str({:subtree => @applications.map{|a| a.status_data_short } }).to_s
9
- end
10
-
11
- def info_string_debug(*args)
3
+ def debug_data(*args)
12
4
  h = args.extract_options!
13
5
  actors = Celluloid::Actor.all.map{|actor| actor.__klass__ }.group_by{|a| a}.map{|k,v| [k, v.size]}.sort_by{|a|a[1]}.reverse
14
6
 
15
- str = <<-S
16
- About: #{Eye::ABOUT}
17
- Info: #{resources_str(Eye::SystemResources.resources($$))}
18
- Ruby: #{RUBY_DESCRIPTION}
19
- Gems: #{%w|Celluloid Celluloid::IO ActiveSupport StateMachine NIO|.map{|c| gem_version(c) }}
20
- Logger: #{Eye::Logger.dev}
21
- Http: #{@http ? "#{@http.host}:#{@http.port}" : '-'}
22
- Socket: #{Eye::Settings::socket_path}
23
- Pid: #{Eye::Settings::pid_path}
24
- Actors: #{actors.inspect}
25
-
26
- S
7
+ res = {
8
+ :about => Eye::ABOUT,
9
+ :resources => Eye::SystemResources.resources($$),
10
+ :ruby => RUBY_DESCRIPTION,
11
+ :http => @http ? "#{@http.host}:#{@http.port}" : '-',
12
+ :gems => %w|Celluloid Celluloid::IO StateMachine NIO Sigar|.map{|c| gem_version(c) },
13
+ :logger => Eye::Logger.dev,
14
+ :pid_path => Eye::Local::pid_path,
15
+ :actors => actors
16
+ }
27
17
 
28
- str += make_str(info_data_debug) + "\n" if h[:processes].present?
18
+ res[:config_yaml] = YAML.dump(current_config.to_h) if h[:config].present?
29
19
 
30
- if h[:config].present?
31
- str += "\nCurrent config: \n"
32
- str += YAML.dump(current_config.to_h)
33
- end
34
-
35
- GC.start
36
- str
20
+ res
37
21
  end
38
22
 
39
23
  def info_data(*args)
40
24
  {:subtree => info_objects(*args).map{|a| a.status_data } }
41
25
  end
42
26
 
43
- private
27
+ def short_data(*args)
28
+ {:subtree => @applications.map{|a| a.status_data_short } }
29
+ end
44
30
 
45
- def info_data_debug(*args)
46
- {:subtree => info_objects(*args).map{|a| a.status_data(true) } }
31
+ def history_data(*args)
32
+ res = {}
33
+ history_objects(*args).each do |process|
34
+ res[process.full_name] = process.schedule_history.reject{|c| c[:state] == :check_crash }
35
+ end
36
+ res
47
37
  end
48
38
 
39
+ private
40
+
49
41
  def info_objects(*args)
50
42
  res = []
51
43
  return @applications if args.empty?
@@ -53,79 +45,6 @@ private
53
45
  res
54
46
  end
55
47
 
56
- def make_str(data, level = -1)
57
- return nil if data.blank?
58
-
59
- if data.is_a?(Array)
60
- data.map{|el| make_str(el, level) }.compact * "\n"
61
- else
62
- str = nil
63
-
64
- if data[:name]
65
- return make_str(data[:subtree], level) if data[:name] == '__default__'
66
-
67
- off = level * 2
68
- off_str = ' ' * off
69
- name = (data[:type] == :application && data[:state].blank?) ? "\033[1m#{data[:name]}\033[0m" : data[:name].to_s
70
- off_len = (data[:type] == :application && !data[:state].blank?) ? 20 : 35
71
- str = off_str + (name + ' ').ljust(off_len - off, data[:state] ? '.' : ' ')
72
-
73
- if data[:debug]
74
- str += ' | ' + debug_str(data[:debug])
75
-
76
- # for group show chain data
77
- if data[:debug][:chain]
78
- str += " (chain: #{data[:debug][:chain].map(&:to_i)})"
79
- end
80
- elsif data[:state]
81
- str += ' ' + data[:state].to_s
82
- str += ' (' + resources_str(data[:resources]) + ')' if data[:resources].present? && data[:state].to_sym == :up
83
- str += " (#{data[:state_reason]} at #{data[:state_changed_at].to_s(:short)})" if data[:state_reason] && data[:state] == 'unmonitored'
84
- elsif data[:current_command]
85
- chain_progress = if data[:chain_progress]
86
- " #{data[:chain_progress][0]} of #{data[:chain_progress][1]}" rescue ''
87
- end
88
- str += " \e[1;33m[#{data[:current_command]}#{chain_progress}]\033[0m"
89
- str += " (#{data[:chain_commands] * ', '})" if data[:chain_commands]
90
- end
91
-
92
- end
93
-
94
- if data[:subtree].nil?
95
- str
96
- elsif data[:subtree].blank? && data[:type] != :application
97
- nil
98
- else
99
- [str, make_str(data[:subtree], level + 1)].compact * "\n"
100
- end
101
- end
102
- end
103
-
104
- def resources_str(r)
105
- return '' if r.blank?
106
-
107
- res = "#{r[:start_time]}, #{r[:cpu]}%"
108
- res += ", #{r[:memory] / 1024}Mb" if r[:memory]
109
- res += ", <#{r[:pid]}>"
110
-
111
- res
112
- end
113
-
114
- def debug_str(debug)
115
- return '' unless debug
116
-
117
- q = 'q(' + (debug[:queue] || []) * ',' + ')'
118
- w = 'w(' + (debug[:watchers] || []) * ',' + ')'
119
-
120
- [w, q] * '; '
121
- end
122
-
123
- def status_applications(app = nil)
124
- apps = app.present? ? @applications.select{|a| a.name == app} : nil
125
- apps = @applications unless apps
126
- apps
127
- end
128
-
129
48
  def gem_version(klass)
130
49
  v = nil
131
50
  begin
@@ -136,4 +55,17 @@ private
136
55
  "#{klass}=#{v}"
137
56
  end
138
57
 
139
- end
58
+ def history_objects(*args)
59
+ args = ['*'] if args.empty?
60
+ res = []
61
+ matched_objects(*args) do |obj|
62
+ if (obj.is_a?(Eye::Process) || obj.is_a?(Eye::ChildProcess))
63
+ res << obj
64
+ else
65
+ res += obj.processes.to_a
66
+ end
67
+ end
68
+ Eye::Utils::AliveArray.new(res)
69
+ end
70
+
71
+ end
@@ -20,7 +20,7 @@ class Eye::Dsl
20
20
  class << self
21
21
  attr_accessor :verbose
22
22
 
23
- def debug(msg = "")
23
+ def debug(msg = '')
24
24
  puts msg if verbose
25
25
  end
26
26
 
@@ -3,7 +3,7 @@ class Eye::Dsl::ApplicationOpts < Eye::Dsl::Opts
3
3
  include Eye::Dsl::Chain
4
4
 
5
5
  def disallow_options
6
- [:pid_file, :start_command]
6
+ [:pid_file, :start_command, :daemonize]
7
7
  end
8
8
 
9
9
  def not_seed_options
@@ -15,6 +15,7 @@ class Eye::Dsl::ApplicationOpts < Eye::Dsl::Opts
15
15
 
16
16
  opts = Eye::Dsl::GroupOpts.new(name, self)
17
17
  opts.instance_eval(&block)
18
+
18
19
  if cfg = opts.config
19
20
  @config[:groups] ||= {}
20
21
 
@@ -26,10 +27,13 @@ class Eye::Dsl::ApplicationOpts < Eye::Dsl::Opts
26
27
  end
27
28
 
28
29
  Eye::Dsl.debug "<= group #{name}"
30
+ opts
29
31
  end
30
32
 
31
33
  def process(name, &block)
32
- group("__default__"){ process(name.to_s, &block) }
34
+ res = nil
35
+ group('__default__'){ res = process(name.to_s, &block) }
36
+ res
33
37
  end
34
38
 
35
39
  alias xgroup nop
@@ -6,7 +6,8 @@ class Eye::Dsl::ChildProcessOpts < Eye::Dsl::Opts
6
6
  end
7
7
 
8
8
  def triggers(*args)
9
- raise Eye::Dsl::Error, "triggers does not allowed in monitor_children"
9
+ raise Eye::Dsl::Error, 'triggers does not allowed in monitor_children'
10
10
  end
11
+ alias trigger triggers
11
12
 
12
- end
13
+ end
@@ -23,7 +23,7 @@ class Eye::Dsl::ConfigOpts < Eye::Dsl::PureOpts
23
23
 
24
24
  def contact(contact_name, contact_type, contact, contact_opts = {})
25
25
  raise Eye::Dsl::Error, "unknown contact_type #{contact_type}" unless Eye::Notify::TYPES[contact_type]
26
- raise Eye::Dsl::Error, "contact should be a String" unless contact.is_a?(String)
26
+ raise Eye::Dsl::Error, 'contact should be a String' unless contact.is_a?(String)
27
27
 
28
28
  notify_hash = @config[contact_type] || (@parent && @parent.config[contact_type]) || Eye::parsed_config.settings[contact_type] || {}
29
29
  validate_hash = notify_hash.merge(contact_opts).merge(:type => contact_type)
@@ -46,4 +46,4 @@ class Eye::Dsl::ConfigOpts < Eye::Dsl::PureOpts
46
46
  end
47
47
  end
48
48
 
49
- end
49
+ end
@@ -3,7 +3,7 @@ class Eye::Dsl::GroupOpts < Eye::Dsl::Opts
3
3
  include Eye::Dsl::Chain
4
4
 
5
5
  def disallow_options
6
- [:pid_file, :start_command]
6
+ [:pid_file, :start_command, :daemonize]
7
7
  end
8
8
 
9
9
  def not_seed_options
@@ -19,6 +19,7 @@ class Eye::Dsl::GroupOpts < Eye::Dsl::Opts
19
19
  @config[:processes][name.to_s] = opts.config if opts.config
20
20
 
21
21
  Eye::Dsl.debug "<= process #{name}"
22
+ opts
22
23
  end
23
24
 
24
25
  alias xprocess nop
@@ -29,13 +29,15 @@ module Eye::Dsl::Main
29
29
  end
30
30
 
31
31
  def config(&block)
32
- Eye::Dsl.debug "=> config"
32
+ Eye::Dsl.debug '=> config'
33
33
 
34
34
  opts = Eye::Dsl::ConfigOpts.new
35
35
  opts.instance_eval(&block)
36
36
  @parsed_config.settings.merge!(opts.config)
37
37
 
38
- Eye::Dsl.debug "<= config"
38
+ Eye::Dsl.debug '<= config'
39
39
  end
40
40
 
41
+ alias settings config
42
+
41
43
  end
@@ -98,26 +98,33 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
98
98
  end
99
99
 
100
100
  def set_uid(value)
101
- raise Eye::Dsl::Error, ":uid not supported by ruby (needed 2.0)" unless Eye::Settings.supported_setsid?
101
+ raise Eye::Dsl::Error, ':uid not supported (use ruby >= 2.0)' unless Eye::Local.supported_setsid?
102
102
  super
103
103
  end
104
104
 
105
105
  def set_gid(value)
106
- raise Eye::Dsl::Error, ":gid not supported by ruby (needed 2.0)" unless Eye::Settings.supported_setsid?
106
+ raise Eye::Dsl::Error, ':gid not supported (use ruby >= 2.0)' unless Eye::Local.supported_setsid?
107
107
  super
108
108
  end
109
109
 
110
110
  def scoped(&block)
111
111
  h = self.class.new(self.name, self)
112
112
  h.instance_eval(&block)
113
+
113
114
  groups = h.config.delete :groups
114
- processes = h.config.delete :processes
115
115
 
116
116
  if groups.present?
117
117
  config[:groups] ||= {}
118
- config[:groups].merge!(groups)
118
+ groups.each do |name, cfg|
119
+ processes = cfg.delete(:processes) || {}
120
+ config[:groups][name] ||= {}
121
+ config[:groups][name].merge!(cfg)
122
+ config[:groups][name][:processes] ||= {}
123
+ config[:groups][name][:processes].merge!(processes)
124
+ end
119
125
  end
120
126
 
127
+ processes = h.config.delete :processes
121
128
  if processes.present?
122
129
  config[:processes] ||= {}
123
130
  config[:processes].merge!(processes)
@@ -1,66 +1,72 @@
1
1
  module Eye::Dsl::Validation
2
+ def self.included(base)
3
+ base.extend(ClassMethods)
4
+ end
5
+
2
6
  class Error < Exception; end
3
7
 
4
- def inherited(subclass)
5
- subclass.validates = self.validates.clone
6
- subclass.should_bes = self.should_bes.clone
7
- subclass.defaults = self.defaults.clone
8
- subclass.variants = self.variants.clone
9
- end
8
+ module ClassMethods
9
+ def inherited(subclass)
10
+ subclass.validates = self.validates.clone
11
+ subclass.should_bes = self.should_bes.clone
12
+ subclass.defaults = self.defaults.clone
13
+ subclass.variants = self.variants.clone
14
+ end
10
15
 
11
- attr_accessor :validates, :should_bes, :defaults, :variants
16
+ attr_accessor :validates, :should_bes, :defaults, :variants
12
17
 
13
- def validates; @validates ||= {}; end
14
- def should_bes; @should_bes ||= []; end
15
- def defaults; @defaults ||= {}; end
16
- def variants; @variants ||= {}; end
18
+ def validates; @validates ||= {}; end
19
+ def should_bes; @should_bes ||= []; end
20
+ def defaults; @defaults ||= {}; end
21
+ def variants; @variants ||= {}; end
17
22
 
18
- def param(param, types = [], should_be = false, default = nil, _variants = nil)
19
- param = param.to_sym
23
+ def param(param, types = [], should_be = false, default = nil, _variants = nil)
24
+ param = param.to_sym
20
25
 
21
- validates[param] = types
22
- should_bes << param if should_be
23
- defaults[param] = default
24
- variants[param] = _variants
26
+ validates[param] = types
27
+ should_bes << param if should_be
28
+ defaults[param] = default
29
+ variants[param] = _variants
25
30
 
26
- return if param == :do
31
+ return if param == :do
27
32
 
28
- define_method "#{param}" do
29
- @options[param] || default
33
+ define_method "#{param}" do
34
+ @options[param] || default
35
+ end
30
36
  end
31
- end
32
37
 
33
- def validate(options = {})
34
- options.each do |param, value|
35
- param = param.to_sym
36
- types = validates[param]
37
- unless types
38
- if param != :type
39
- raise Error, "#{self.name} unknown param :#{param} value #{value.inspect}"
38
+ def validate(options = {})
39
+ options.each do |param, value|
40
+ param = param.to_sym
41
+ types = validates[param]
42
+ unless types
43
+ if param != :type
44
+ raise Error, "#{self.name} unknown param :#{param} value #{value.inspect}"
45
+ end
40
46
  end
41
- end
42
47
 
43
- if self.variants[param]
44
- if value && !value.is_a?(Proc)
45
- if value.is_a?(Array)
46
- if (value - self.variants[param]).present?
48
+ if self.variants[param]
49
+ if value && !value.is_a?(Proc)
50
+ if value.is_a?(Array)
51
+ if (value - self.variants[param]).present?
52
+ raise Error, "#{value.inspect} should within #{self.variants[param].inspect}"
53
+ end
54
+ elsif !self.variants[param].include?(value)
47
55
  raise Error, "#{value.inspect} should within #{self.variants[param].inspect}"
48
56
  end
49
- elsif !self.variants[param].include?(value)
50
- raise Error, "#{value.inspect} should within #{self.variants[param].inspect}"
51
57
  end
52
58
  end
53
- end
54
59
 
55
- next if types.blank?
60
+ next if types.blank?
56
61
 
57
- types = Array(types)
58
- good = types.any?{|type| value.is_a?(type) }
59
- raise Error, "#{self.name} bad param :#{param} value #{value.inspect}, type #{types.inspect}" unless good
60
- end
62
+ types = Array(types)
63
+ good = types.any?{|type| value.is_a?(type) }
64
+ raise Error, "#{self.name} bad param :#{param} value #{value.inspect}, type #{types.inspect}" unless good
65
+ end
61
66
 
62
- should_bes.each do |param|
63
- raise Error, "#{self.name} for param :#{param} value should be" unless options[param.to_sym] || defaults[param.to_sym]
67
+ should_bes.each do |param|
68
+ raise Error, "#{self.name} for param :#{param} value should be" unless options[param.to_sym] || defaults[param.to_sym]
69
+ end
64
70
  end
65
71
  end
66
72