eye 0.5.1 → 0.5.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGES.md +6 -0
  4. data/README.md +37 -35
  5. data/examples/puma.eye +1 -1
  6. data/examples/test.eye +32 -30
  7. data/examples/unicorn.eye +1 -1
  8. data/lib/eye.rb +1 -1
  9. data/lib/eye/checker.rb +24 -1
  10. data/lib/eye/checker/cpu.rb +4 -14
  11. data/lib/eye/checker/cputime.rb +2 -12
  12. data/lib/eye/checker/file_ctime.rb +2 -3
  13. data/lib/eye/checker/file_size.rb +8 -8
  14. data/lib/eye/checker/http.rb +2 -2
  15. data/lib/eye/checker/memory.rb +4 -14
  16. data/lib/eye/checker/runtime.rb +2 -12
  17. data/lib/eye/checker/socket.rb +1 -1
  18. data/lib/eye/cli.rb +6 -0
  19. data/lib/eye/cli/commands.rb +2 -3
  20. data/lib/eye/cli/render.rb +4 -4
  21. data/lib/eye/cli/server.rb +4 -4
  22. data/lib/eye/controller.rb +1 -1
  23. data/lib/eye/controller/load.rb +14 -13
  24. data/lib/eye/controller/send_command.rb +4 -4
  25. data/lib/eye/controller/status.rb +2 -1
  26. data/lib/eye/dsl.rb +1 -1
  27. data/lib/eye/dsl/child_process_opts.rb +2 -2
  28. data/lib/eye/dsl/opts.rb +5 -1
  29. data/lib/eye/dsl/validation.rb +2 -2
  30. data/lib/eye/group/chain.rb +2 -2
  31. data/lib/eye/notify.rb +3 -3
  32. data/lib/eye/process.rb +7 -7
  33. data/lib/eye/process/children.rb +60 -0
  34. data/lib/eye/process/commands.rb +40 -37
  35. data/lib/eye/process/config.rb +5 -5
  36. data/lib/eye/process/controller.rb +8 -8
  37. data/lib/eye/process/data.rb +4 -4
  38. data/lib/eye/process/monitor.rb +17 -17
  39. data/lib/eye/process/scheduler.rb +1 -1
  40. data/lib/eye/process/states.rb +3 -3
  41. data/lib/eye/process/system.rb +3 -3
  42. data/lib/eye/process/validate.rb +1 -1
  43. data/lib/eye/process/watchers.rb +6 -6
  44. data/lib/eye/server.rb +1 -1
  45. data/lib/eye/system.rb +4 -4
  46. data/lib/eye/system_resources.rb +3 -3
  47. data/lib/eye/trigger.rb +4 -6
  48. data/lib/eye/trigger/flapping.rb +2 -2
  49. data/lib/eye/trigger/stop_children.rb +14 -0
  50. metadata +4 -4
  51. data/lib/eye/process/child.rb +0 -60
  52. data/lib/eye/trigger/stop_childs.rb +0 -10
@@ -2,7 +2,7 @@ require 'net/http'
2
2
 
3
3
  class Eye::Checker::Http < Eye::Checker::Defer
4
4
 
5
- # checks :http, :every => 5.seconds, :times => 1,
5
+ # check :http, :every => 5.seconds, :times => 1,
6
6
  # :url => "http://127.0.0.1:3000/", :kind => :success, :pattern => /OK/, :timeout => 3.seconds
7
7
 
8
8
  param :url, String, true
@@ -93,4 +93,4 @@ private
93
93
  end
94
94
  end
95
95
 
96
- end
96
+ end
@@ -1,11 +1,9 @@
1
- class Eye::Checker::Memory < Eye::Checker
1
+ class Eye::Checker::Memory < Eye::Checker::Measure
2
2
 
3
- # checks :memory, :every => 3.seconds, :below => 80.megabytes, :times => [3,5]
4
-
5
- param :below, [Fixnum, Float], true
3
+ # check :memory, :every => 3.seconds, :below => 80.megabytes, :times => [3,5]
6
4
 
7
5
  def check_name
8
- @check_name ||= "memory(#{human_value(below)})"
6
+ @check_name ||= "memory(#{measure_str})"
9
7
  end
10
8
 
11
9
  def get_value
@@ -16,12 +14,4 @@ class Eye::Checker::Memory < Eye::Checker
16
14
  "#{value.to_i / 1024 / 1024}Mb"
17
15
  end
18
16
 
19
- def good?(value)
20
- if below
21
- value < below
22
- else
23
- true
24
- end
25
- end
26
-
27
- end
17
+ end
@@ -1,9 +1,7 @@
1
- class Eye::Checker::Runtime < Eye::Checker
1
+ class Eye::Checker::Runtime < Eye::Checker::Measure
2
2
 
3
3
  # check :runtime, :every => 1.minute, :below => 120.minutes
4
4
 
5
- param :below, [Fixnum, Float], true
6
-
7
5
  def get_value
8
6
  st = Eye::SystemResources.start_time(@pid)
9
7
  if st
@@ -17,12 +15,4 @@ class Eye::Checker::Runtime < Eye::Checker
17
15
  "#{value / 60}m"
18
16
  end
19
17
 
20
- def good?(value)
21
- if below
22
- value < below
23
- else
24
- true
25
- end
26
- end
27
-
28
- end
18
+ end
@@ -1,6 +1,6 @@
1
1
  class Eye::Checker::Socket < Eye::Checker::Defer
2
2
 
3
- # checks :socket, :every => 5.seconds, :times => 1,
3
+ # check :socket, :every => 5.seconds, :times => 1,
4
4
  # :addr => "unix:/var/run/daemon.sock", :timeout => 3.seconds,
5
5
  #
6
6
  # Available parameters:
@@ -13,6 +13,9 @@ class Eye::Cli < Thor
13
13
  desc "info [MASK]", "processes info"
14
14
  def info(mask = nil)
15
15
  res = cmd(:info_data, *Array(mask))
16
+ if mask && res[:subtree] && res[:subtree].empty?
17
+ error!("command :info, objects not found!")
18
+ end
16
19
  say render_info(res)
17
20
  say
18
21
  end
@@ -41,6 +44,9 @@ class Eye::Cli < Thor
41
44
  desc "history [MASK,...]", "processes history"
42
45
  def history(*masks)
43
46
  res = cmd(:history_data, *masks)
47
+ if !masks.empty? && res && res.empty?
48
+ error!("command :history, objects not found!")
49
+ end
44
50
  say render_history(res)
45
51
  say
46
52
  end
@@ -15,9 +15,9 @@ private
15
15
  res = _cmd(cmd, *args)
16
16
 
17
17
  if res == :not_started
18
- error! "socket(#{Eye::Local.socket_path}) not found, did you `eye load`?"
18
+ error! "socket(#{Eye::Local.socket_path}) not found, did you run `eye load`?"
19
19
  elsif res == :timeouted
20
- error! 'eye does not answer, timeouted...'
20
+ error! 'eye timed out without responding...'
21
21
  end
22
22
 
23
23
  res
@@ -26,7 +26,6 @@ private
26
26
  def say_load_result(res = {}, opts = {})
27
27
  error!(res) unless res.is_a?(Hash)
28
28
  say_filename = (res.size > 1)
29
- say 'eye started!', :green if opts[:started]
30
29
  error = false
31
30
  res.each do |filename, _res|
32
31
  say "#{filename}: ", nil, true if say_filename
@@ -1,7 +1,7 @@
1
1
  module Eye::Cli::Render
2
2
  private
3
3
  def render_info(data)
4
- error!("unexpected server answer #{data.inspect}") unless data.is_a?(Hash)
4
+ error!("unexpected server response #{data.inspect}") unless data.is_a?(Hash)
5
5
 
6
6
  make_str data
7
7
  end
@@ -62,7 +62,7 @@ private
62
62
  end
63
63
 
64
64
  def render_debug_info(data)
65
- error!("unexpected server answer #{data.inspect}") unless data.is_a?(Hash)
65
+ error!("unexpected server response #{data.inspect}") unless data.is_a?(Hash)
66
66
 
67
67
  s = ""
68
68
 
@@ -90,7 +90,7 @@ private
90
90
  end
91
91
 
92
92
  def render_history(data)
93
- error!("unexpected server answer #{data.inspect}") unless data.is_a?(Hash)
93
+ error!("unexpected server response #{data.inspect}") unless data.is_a?(Hash)
94
94
 
95
95
  res = []
96
96
  data.each do |name, data|
@@ -103,7 +103,7 @@ private
103
103
  def detail_process_info(name, history)
104
104
  return if history.empty?
105
105
 
106
- res = "\033[1m#{name}\033[0m:\n"
106
+ res = "\033[1m#{name}\033[0m\n"
107
107
  history = history.reverse
108
108
 
109
109
  history.chunk{|h| [h[:state], h[:reason].to_s] }.each do |_, hist|
@@ -51,15 +51,15 @@ private
51
51
  File.open(Eye::Local.pid_path, 'w'){|f| f.write(pid) }
52
52
 
53
53
  unless wait_server
54
- error! 'server not runned in 15 seconds, something crazy wrong'
54
+ error! 'server has not started in 15 seconds, something is very wrong'
55
55
  end
56
56
 
57
57
  configs.unshift(Eye::Local.eyeconfig) if File.exists?(Eye::Local.eyeconfig)
58
58
 
59
+ say 'eye started!', :green
60
+
59
61
  if !configs.empty?
60
- say_load_result cmd(:load, *configs), :started => true
61
- else
62
- say 'started!', :green
62
+ say_load_result cmd(:load, *configs)
63
63
  end
64
64
  end
65
65
 
@@ -40,7 +40,7 @@ class Eye::Controller
40
40
  Celluloid::logger = Eye::Logger.new('celluloid')
41
41
  Eye::SystemResources.cache
42
42
 
43
- info "starting #{Eye::ABOUT} (#{$$})"
43
+ info "starting #{Eye::ABOUT} <#{$$}>"
44
44
  end
45
45
 
46
46
  def settings
@@ -11,7 +11,7 @@ module Eye::Controller::Load
11
11
  def load(*args)
12
12
  h = args.extract_options!
13
13
  obj_strs = args.flatten
14
- info "load: #{obj_strs}"
14
+ info "loading: #{obj_strs}"
15
15
 
16
16
  res = Hash.new
17
17
 
@@ -42,7 +42,7 @@ private
42
42
  rescue Eye::Dsl::Error, Exception, NoMethodError => ex
43
43
  raise if ex.class.to_s.include?('RR') # skip RR exceptions
44
44
 
45
- error "load: config error <#{filename}>: #{ex.message}"
45
+ error "loading: config error <#{filename}>: #{ex.message}"
46
46
 
47
47
  # filter backtrace for user output
48
48
  bt = (ex.backtrace || [])
@@ -65,7 +65,7 @@ private
65
65
  filename
66
66
  end
67
67
 
68
- debug "load: globbing mask #{mask}"
68
+ debug "loading: globbing mask #{mask}"
69
69
 
70
70
  sub = []
71
71
  Dir[mask].each do |config_path|
@@ -81,16 +81,17 @@ private
81
81
 
82
82
  # return: result, config
83
83
  def parse_config(filename)
84
- debug "parse #{filename}"
84
+ debug "parsing: #{filename}"
85
85
 
86
86
  cfg = Eye::Dsl.parse(nil, filename)
87
87
  @current_config.merge(cfg).validate! # just validate summary config here
88
+ Eye.parsed_config = nil # remove link on config, for better gc
88
89
  cfg
89
90
  end
90
91
 
91
92
  # !!! exclusive operation
92
93
  def load_config(filename, config)
93
- info "load #{filename}"
94
+ info "loading: #{filename}"
94
95
  new_cfg = @current_config.merge(config)
95
96
  new_cfg.validate!
96
97
 
@@ -111,7 +112,7 @@ private
111
112
 
112
113
  # create objects as diff, from configs
113
114
  def create_objects(apps_config, changed_apps = [])
114
- debug 'create objects'
115
+ debug 'creating objects'
115
116
 
116
117
  apps_config.each do |app_name, app_cfg|
117
118
  update_or_create_application(app_name, app_cfg.clone) if changed_apps.include?(app_name)
@@ -137,9 +138,9 @@ private
137
138
 
138
139
  @applications.delete(app)
139
140
 
140
- debug "update app #{app_name}"
141
+ debug "updating app: #{app_name}"
141
142
  else
142
- debug "create app #{app_name}"
143
+ debug "creating app: #{app_name}"
143
144
  end
144
145
 
145
146
  app = Eye::Application.new(app_name, app_config)
@@ -182,13 +183,13 @@ private
182
183
 
183
184
  def update_or_create_group(group_name, group_config)
184
185
  group = if @old_groups[group_name]
185
- debug "update group #{group_name}"
186
+ debug "updating group: #{group_name}"
186
187
  group = @old_groups.delete(group_name)
187
188
  group.schedule :update_config, group_config, Eye::Reason::User.new(:'load config')
188
189
  group.clear
189
190
  group
190
191
  else
191
- debug "create group #{group_name}"
192
+ debug "creating group: #{group_name}"
192
193
  gr = Eye::Group.new(group_name, group_config)
193
194
  @added_groups << gr
194
195
  gr
@@ -209,16 +210,16 @@ private
209
210
  key = @old_processes[name] ? name : @old_processes.keys.detect { |n| n.end_with?(postfix) }
210
211
 
211
212
  if @old_processes[key]
212
- debug "update process #{name}"
213
+ debug "updating process: #{name}"
213
214
  process = @old_processes.delete(key)
214
215
  process.schedule :update_config, process_cfg, Eye::Reason::User.new(:'load config')
215
216
  process
216
217
  else
217
- debug "create process #{name}"
218
+ debug "creating process: #{name}"
218
219
  process = Eye::Process.new(process_cfg)
219
220
  @added_processes << process
220
221
  process
221
222
  end
222
223
  end
223
224
 
224
- end
225
+ end
@@ -124,7 +124,7 @@ private
124
124
  return apps if apps.size > 0
125
125
 
126
126
  if objs.map(&:app_name).uniq.size > 1
127
- raise Error, "cant match targets from different applications: #{res.map(&:full_name)}"
127
+ raise Error, "cannot match targets from different applications: #{res.map(&:full_name)}"
128
128
  end
129
129
  end
130
130
 
@@ -150,9 +150,9 @@ private
150
150
  res << p if p.name =~ r || p.full_name =~ r
151
151
 
152
152
  # child matching
153
- if p.childs.present?
154
- childs = p.childs.values
155
- res += childs.select do |ch|
153
+ if p.children.present?
154
+ children = p.children.values
155
+ res += children.select do |ch|
156
156
  name = ch.name rescue ''
157
157
  full_name = ch.full_name rescue ''
158
158
  name =~ r || full_name =~ r
@@ -59,8 +59,9 @@ private
59
59
  args = ['*'] if args.empty?
60
60
  res = []
61
61
  matched_objects(*args) do |obj|
62
- if (obj.is_a?(Eye::Process) || obj.is_a?(Eye::ChildProcess))
62
+ if obj.is_a?(Eye::Process)
63
63
  res << obj
64
+ elsif obj.is_a?(Eye::ChildProcess)
64
65
  else
65
66
  res += obj.processes.to_a
66
67
  end
@@ -43,7 +43,7 @@ class Eye::Dsl
43
43
  end
44
44
 
45
45
  def check_name(name)
46
- raise Error, "not allow ':' in name '#{name}'" if name.to_s.include?(':')
46
+ raise Error, "':' is not allowed in name '#{name}'" if name.to_s.include?(':')
47
47
  end
48
48
  end
49
49
  end
@@ -1,12 +1,12 @@
1
1
  class Eye::Dsl::ChildProcessOpts < Eye::Dsl::Opts
2
2
 
3
3
  def allow_options
4
- [:stop_command, :restart_command, :childs_update_period,
4
+ [:stop_command, :restart_command, :children_update_period,
5
5
  :stop_signals, :stop_grace, :stop_timeout, :restart_timeout]
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 not allowed in monitor_children'
10
10
  end
11
11
  alias trigger triggers
12
12
 
@@ -8,7 +8,7 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
8
8
  create_options_methods(BOOL_OPTIONS, [TrueClass, FalseClass])
9
9
 
10
10
  INTERVAL_OPTIONS = [ :check_alive_period, :start_timeout, :restart_timeout, :stop_timeout, :start_grace,
11
- :restart_grace, :stop_grace, :childs_update_period, :restore_in ]
11
+ :restart_grace, :stop_grace, :children_update_period, :restore_in ]
12
12
  create_options_methods(INTERVAL_OPTIONS, [Fixnum, Float])
13
13
 
14
14
  create_options_methods([:environment], Hash)
@@ -111,6 +111,10 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
111
111
  set_daemonize true
112
112
  end
113
113
 
114
+ def clear_bundler_env
115
+ env('GEM_PATH' => nil, 'GEM_HOME' => nil, 'RUBYOPT' => nil, 'BUNDLE_BIN_PATH' => nil, 'BUNDLE_GEMFILE' => nil)
116
+ end
117
+
114
118
  def scoped(&block)
115
119
  h = self.class.new(self.name, self)
116
120
  h.instance_eval(&block)
@@ -49,10 +49,10 @@ module Eye::Dsl::Validation
49
49
  if value && !value.is_a?(Proc)
50
50
  if value.is_a?(Array)
51
51
  if (value - self.variants[param]).present?
52
- raise Error, "#{value.inspect} should within #{self.variants[param].inspect}"
52
+ raise Error, "#{value.inspect} should be within #{self.variants[param].inspect}"
53
53
  end
54
54
  elsif !self.variants[param].include?(value)
55
- raise Error, "#{value.inspect} should within #{self.variants[param].inspect}"
55
+ raise Error, "#{value.inspect} should be within #{self.variants[param].inspect}"
56
56
  end
57
57
  end
58
58
  end
@@ -3,7 +3,7 @@ module Eye::Group::Chain
3
3
  private
4
4
 
5
5
  def chain_schedule(type, grace, command, *args)
6
- info "start #{type} with #{grace}s chain #{command} #{args}"
6
+ info "starting #{type} with #{grace}s chain #{command} #{args}"
7
7
 
8
8
  @chain_processes_count = @processes.size
9
9
  @chain_processes_current = 0
@@ -78,4 +78,4 @@ private
78
78
  end
79
79
  end
80
80
 
81
- end
81
+ end
@@ -9,7 +9,7 @@ class Eye::Notify
9
9
 
10
10
  def self.get_class(type)
11
11
  klass = eval("Eye::Notify::#{TYPES[type]}") rescue nil
12
- raise "Unknown notify #{type}" unless klass
12
+ raise "unknown notifier :#{type}" unless klass
13
13
  if deps = klass.depends_on
14
14
  Array(deps).each { |d| require d }
15
15
  end
@@ -26,7 +26,7 @@ class Eye::Notify
26
26
  needed_hash = (settings[:contacts] || {})[contact]
27
27
 
28
28
  if needed_hash.blank?
29
- error "not found contact #{contact}! something wrong with config"
29
+ error "contact #{contact} not found; check your configuration"
30
30
  return
31
31
  end
32
32
 
@@ -74,7 +74,7 @@ class Eye::Notify
74
74
  end
75
75
 
76
76
  def execute
77
- raise 'realize me'
77
+ raise NotImplementedError
78
78
  end
79
79
 
80
80
  param :contact, [String]
@@ -11,22 +11,22 @@ class Eye::Process
11
11
  autoload :System, 'eye/process/system'
12
12
  autoload :Controller, 'eye/process/controller'
13
13
  autoload :StatesHistory, 'eye/process/states_history'
14
- autoload :Child, 'eye/process/child'
14
+ autoload :Children, 'eye/process/children'
15
15
  autoload :Trigger, 'eye/process/trigger'
16
16
  autoload :Notify, 'eye/process/notify'
17
17
  autoload :Scheduler, 'eye/process/scheduler'
18
18
  autoload :Validate, 'eye/process/validate'
19
19
 
20
20
  attr_accessor :pid, :watchers, :config, :states_history,
21
- :childs, :triggers, :name, :state_reason, :flapping_times
21
+ :children, :triggers, :name, :state_reason, :flapping_times
22
22
 
23
23
  def initialize(config)
24
- raise 'pid file should be' unless config[:pid_file]
24
+ raise 'you must supply a pid_file location' unless config[:pid_file]
25
25
 
26
26
  @config = prepare_config(config)
27
27
 
28
28
  @watchers = {}
29
- @childs = {}
29
+ @children = {}
30
30
  @triggers = []
31
31
  @name = @config[:name]
32
32
  @flapping_times = 0
@@ -34,7 +34,7 @@ class Eye::Process
34
34
  @states_history = Eye::Process::StatesHistory.new(100)
35
35
  @states_history << :unmonitored
36
36
 
37
- debug "create with config: #{@config.inspect}"
37
+ debug "creating with config: #{@config.inspect}"
38
38
 
39
39
  add_triggers
40
40
 
@@ -63,8 +63,8 @@ class Eye::Process
63
63
  # system methods:
64
64
  include Eye::Process::System
65
65
 
66
- # manage childs methods
67
- include Eye::Process::Child
66
+ # manage child methods
67
+ include Eye::Process::Children
68
68
 
69
69
  # manage triggers methods
70
70
  include Eye::Process::Trigger