eye 0.8.1 → 0.9.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +21 -2
  4. data/.travis.yml +2 -1
  5. data/Gemfile +3 -0
  6. data/LICENSE +1 -1
  7. data/README.md +1 -1
  8. data/bin/loader_eye +1 -1
  9. data/examples/delayed_job.eye +2 -2
  10. data/examples/processes/sample.rb +1 -1
  11. data/examples/puma.eye +1 -1
  12. data/examples/rbenv.eye +1 -1
  13. data/examples/sidekiq.eye +1 -1
  14. data/examples/test.eye +1 -1
  15. data/examples/thin-farm.eye +1 -1
  16. data/examples/unicorn.eye +1 -1
  17. data/eye.gemspec +2 -2
  18. data/lib/eye.rb +2 -3
  19. data/lib/eye/application.rb +3 -6
  20. data/lib/eye/checker.rb +4 -3
  21. data/lib/eye/checker/children_count.rb +3 -3
  22. data/lib/eye/checker/socket.rb +7 -12
  23. data/lib/eye/child_process.rb +5 -7
  24. data/lib/eye/cli.rb +6 -4
  25. data/lib/eye/cli/commands.rb +1 -1
  26. data/lib/eye/cli/render.rb +6 -5
  27. data/lib/eye/client.rb +9 -4
  28. data/lib/eye/controller.rb +2 -2
  29. data/lib/eye/controller/{send_command.rb → apply.rb} +25 -32
  30. data/lib/eye/controller/commands.rb +13 -10
  31. data/lib/eye/controller/load.rb +49 -38
  32. data/lib/eye/controller/status.rb +2 -2
  33. data/lib/eye/dsl.rb +1 -1
  34. data/lib/eye/dsl/application_opts.rb +2 -2
  35. data/lib/eye/dsl/child_process_opts.rb +1 -1
  36. data/lib/eye/dsl/config_opts.rb +1 -1
  37. data/lib/eye/dsl/group_opts.rb +3 -3
  38. data/lib/eye/dsl/main.rb +3 -3
  39. data/lib/eye/dsl/opts.rb +17 -21
  40. data/lib/eye/dsl/process_opts.rb +3 -3
  41. data/lib/eye/dsl/validation.rb +2 -2
  42. data/lib/eye/group.rb +8 -114
  43. data/lib/eye/group/call.rb +73 -0
  44. data/lib/eye/group/chain.rb +19 -17
  45. data/lib/eye/group/data.rb +40 -0
  46. data/lib/eye/loader.rb +1 -1
  47. data/lib/eye/logger.rb +4 -4
  48. data/lib/eye/process.rb +2 -0
  49. data/lib/eye/process/commands.rb +11 -19
  50. data/lib/eye/process/config.rb +2 -1
  51. data/lib/eye/process/controller.rb +5 -12
  52. data/lib/eye/process/data.rb +11 -3
  53. data/lib/eye/process/monitor.rb +5 -5
  54. data/lib/eye/process/notify.rb +1 -1
  55. data/lib/eye/process/scheduler.rb +118 -63
  56. data/lib/eye/process/states.rb +10 -9
  57. data/lib/eye/process/states_history.rb +1 -1
  58. data/lib/eye/process/system.rb +1 -1
  59. data/lib/eye/process/trigger.rb +5 -4
  60. data/lib/eye/process/validate.rb +1 -1
  61. data/lib/eye/server.rb +22 -9
  62. data/lib/eye/trigger.rb +4 -7
  63. data/lib/eye/trigger/check_dependency.rb +1 -1
  64. data/lib/eye/trigger/flapping.rb +8 -10
  65. data/lib/eye/trigger/starting_guard.rb +7 -4
  66. data/lib/eye/trigger/stop_children.rb +1 -1
  67. data/lib/eye/trigger/wait_dependency.rb +2 -2
  68. data/lib/eye/utils.rb +19 -9
  69. metadata +10 -10
  70. data/lib/eye/reason.rb +0 -26
  71. data/lib/eye/utils/celluloid_chain.rb +0 -73
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dcb8b4869dbc05dd43d8689f3dac2e2568da2836
4
- data.tar.gz: 812fb5390734850ae80aa61515f1b989eaa7dfdb
3
+ metadata.gz: e50d71e8909ed2df73bede83562f4254f374fa99
4
+ data.tar.gz: 2328cd9e596a36e42763514bf9c09190f7e7dc36
5
5
  SHA512:
6
- metadata.gz: fb16b8809575fe414f6cce0375071badf60e77b5ede06a4f7e941d4f9dd630c9f010bc3a669106e5789a959f66244df9ca505b8b6b9d1a49f8e5a7dc7302603d
7
- data.tar.gz: 994e3f4a5444b59ac5d9e33ee7a5d786ef9d1e457b4d161ddc1fa54765b6d7b69a1843fe24a70273019def28fb4b8c0425d7ed516f804fe225d1c6e8029e47a0
6
+ metadata.gz: 675c027af39891e72aa31101cdcc18eeeeb3f8e5b04e7ef56e67e88a49f6e703efaf8301a9f8c8aa9d0d20c3c6467b5c172e6e9e9b4b5b39c850b2789d52e314
7
+ data.tar.gz: 2b5f93e6d191f4f65d560f54d46ffef5ba95b555f4d3911509ed9828645e9d877813864f938b5dab7aa3c85ef9ae8374583bf19987c9120447f81d55dc11721a
data/.gitignore CHANGED
@@ -37,3 +37,4 @@ script
37
37
  /vendor/
38
38
  *.gz
39
39
  .eye
40
+ .DS_Store
@@ -5,6 +5,25 @@ AllCops:
5
5
  - 'spec/**/*'
6
6
  - 'lib/eye/utils/mini_active_support.rb'
7
7
 
8
+ Performance/RedundantBlockCall:
9
+ Exclude:
10
+ - 'lib/eye/process/watchers.rb'
11
+
12
+ Style/NumericPredicate:
13
+ EnforcedStyle: comparison
14
+
15
+ Style/TernaryParentheses:
16
+ Exclude:
17
+ - 'lib/eye/cli/render.rb'
18
+
19
+ Style/MutableConstant:
20
+ Exclude:
21
+ - 'lib/eye.rb'
22
+ - 'examples/**/*'
23
+ - 'lib/eye/trigger.rb'
24
+ - 'lib/eye/checker.rb'
25
+ - 'lib/eye/notify.rb'
26
+
8
27
  Style/ClassAndModuleChildren:
9
28
  EnforcedStyle: compact
10
29
 
@@ -69,7 +88,7 @@ Metrics/BlockNesting:
69
88
  - 'lib/eye/trigger/starting_guard.rb'
70
89
 
71
90
  Metrics/MethodLength:
72
- Max: 45
91
+ Max: 50
73
92
 
74
93
  Metrics/CyclomaticComplexity:
75
94
  Max: 19
@@ -83,7 +102,7 @@ Metrics/ModuleLength:
83
102
  - 'lib/eye/process/commands.rb'
84
103
 
85
104
  Metrics/AbcSize:
86
- Max: 60
105
+ Max: 65
87
106
 
88
107
  Style/GuardClause:
89
108
  MinBodyLength: 10
@@ -4,6 +4,7 @@ rvm:
4
4
  - "2.0.0"
5
5
  - "2.1.7"
6
6
  - "2.2.3"
7
+ - "2.3.0"
7
8
  script:
8
- - bundle exec rake N=16
9
+ - bundle exec rake N=15
9
10
  - bundle exec rubocop
data/Gemfile CHANGED
@@ -1,2 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
+
4
+ gem 'rack', '1.6.4'
5
+ gem 'json', '1.8.3'
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2015 'Konstantin Makarchev'
1
+ Copyright (c) 2012-2016 'Konstantin Makarchev'
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -136,7 +136,7 @@ foreground load:
136
136
 
137
137
  If the eye daemon has already started and you call the `load` command, the config will be updated (into eye daemon). New objects(applications, groups, processes) will be added and monitored. Processes removed from the config will be removed (and stopped if the process has `stop_on_delete true`). Other objects will update their configs.
138
138
 
139
- Two global configs loaded by default, if it exists (with the first eye load):
139
+ Two global configs loaded by default, if they exist (with the first eye load):
140
140
 
141
141
  /etc/eye.conf
142
142
  ~/.eyeconfig
@@ -52,7 +52,7 @@ config = File.expand_path(config) if config && !config.empty?
52
52
  Eye::Control # preload
53
53
 
54
54
  if config
55
- res = server.command('load', config)
55
+ res = Eye::Control.command('load', config)
56
56
  exit(1) if res.values.any? { |r| r[:error] }
57
57
  end
58
58
 
@@ -1,6 +1,6 @@
1
- cwd = File.expand_path(File.join(File.dirname(__FILE__), %w[ ../ ../ ]))
1
+ cwd = File.expand_path(File.join(File.dirname(__FILE__), %w[../ ../]))
2
2
 
3
- config_path = File.join(cwd, %w[ config dj.yml ])
3
+ config_path = File.join(cwd, %w[config dj.yml])
4
4
 
5
5
  workers_count = if File.exist?(config_path)
6
6
  YAML.load_file(config_path).try(:[], :workers) || 5
@@ -6,7 +6,7 @@ require 'optparse'
6
6
  # OptionParser.
7
7
  options = {}
8
8
 
9
- optparse = OptionParser.new do|opts|
9
+ optparse = OptionParser.new do |opts|
10
10
  # This displays the help screen, all programs are
11
11
  # assumed to have this option.
12
12
  opts.on('-h', '--help', 'Display this screen') do
@@ -1,6 +1,6 @@
1
1
  BUNDLE = 'bundle'
2
2
  RAILS_ENV = 'production'
3
- ROOT = File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
3
+ ROOT = File.expand_path(File.join(File.dirname(__FILE__), %w[processes]))
4
4
 
5
5
  Eye.config do
6
6
  logger "#{ROOT}/eye.log"
@@ -1,6 +1,6 @@
1
1
  Eye.application 'rbenv_example' do
2
2
  env 'RBENV_ROOT' => '/usr/local/rbenv', 'PATH' => "/usr/local/rbenv/shims:/usr/local/rbenv/bin:#{ENV['PATH']}"
3
- working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
3
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[processes]))
4
4
 
5
5
  process 'some_process' do
6
6
  pid_file 'some.pid'
@@ -16,7 +16,7 @@ def sidekiq_process(proxy, name)
16
16
  end
17
17
 
18
18
  Eye.application :sidekiq_test do
19
- working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
19
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[processes]))
20
20
  env 'RAILS_ENV' => 'production'
21
21
 
22
22
  sidekiq_process self, :sidekiq
@@ -14,7 +14,7 @@ Eye.application 'test' do
14
14
  # uid "user_name" # run app as a user_name (optional) - available only on ruby >= 2.0
15
15
  # gid "group_name" # run app as a group_name (optional) - available only on ruby >= 2.0
16
16
 
17
- working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
17
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[processes]))
18
18
  stdall 'trash.log' # stdout,err logs for processes by default
19
19
  env 'APP_ENV' => 'production' # global env for each processes
20
20
  trigger :flapping, times: 10, within: 1.minute, retry_in: 10.minutes
@@ -8,7 +8,7 @@ Eye.config do
8
8
  end
9
9
 
10
10
  Eye.app 'thin-farm' do
11
- working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
11
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[processes]))
12
12
  env 'RAILS_ENV' => 'production'
13
13
 
14
14
  # more about stop_on_delete: https://github.com/kostya/eye/wiki/About-stop_on_delete-=-true
@@ -9,7 +9,7 @@ Eye.application 'rails_unicorn' do
9
9
  # unicorn requires to be `ruby` in path (for soft restart)
10
10
  env 'PATH' => "#{File.dirname(RUBY)}:#{ENV['PATH']}"
11
11
 
12
- working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
12
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[processes]))
13
13
 
14
14
  process('unicorn') do
15
15
  pid_file 'tmp/pids/unicorn.pid'
@@ -21,13 +21,13 @@ Gem::Specification.new do |gem|
21
21
 
22
22
  gem.add_dependency 'celluloid', '~> 0.17.3'
23
23
  gem.add_dependency 'celluloid-io', '~> 0.17.0'
24
- gem.add_dependency 'state_machine'
24
+ gem.add_dependency 'state_machines'
25
25
  gem.add_dependency 'thor'
26
26
  gem.add_dependency 'sigar', '~> 0.7.3'
27
27
 
28
28
  gem.add_development_dependency 'rake'
29
29
  gem.add_development_dependency 'rspec', '< 2.14'
30
- gem.add_development_dependency 'rr'
30
+ gem.add_development_dependency 'rr', '1.1.2'
31
31
  gem.add_development_dependency 'ruby-graphviz'
32
32
  gem.add_development_dependency 'forking'
33
33
  gem.add_development_dependency 'fakeweb'
data/lib/eye.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Eye
2
- VERSION = '0.8.1'
3
- ABOUT = "Eye v#{VERSION} (c) 2012-2015 @kostya"
2
+ VERSION = '0.9.pre'
3
+ ABOUT = "Eye v#{VERSION} (c) 2012-2016 @kostya"
4
4
  PROCLINE = "eye monitoring v#{VERSION}"
5
5
 
6
6
  autoload :Process, 'eye/process'
@@ -19,7 +19,6 @@ module Eye
19
19
  autoload :Utils, 'eye/utils'
20
20
  autoload :Notify, 'eye/notify'
21
21
  autoload :Config, 'eye/config'
22
- autoload :Reason, 'eye/reason'
23
22
  autoload :Sigar, 'eye/sigar'
24
23
  autoload :Controller, 'eye/controller'
25
24
  autoload :Control, 'eye/control'
@@ -38,12 +38,9 @@ class Eye::Application
38
38
  def debug_data
39
39
  end
40
40
 
41
- def send_command(command, *args)
42
- info "send_command #{command}"
43
-
44
- @groups.each do |group|
45
- group.send_command(command, *args)
46
- end
41
+ def send_call(call)
42
+ info "call: #{call}"
43
+ @groups.each { |group| group.send_call(call) }
47
44
  end
48
45
 
49
46
  def alive?
@@ -130,6 +130,7 @@ class Eye::Checker
130
130
  result
131
131
 
132
132
  rescue Object => ex
133
+ raise(ex) if ex.class == Celluloid::TaskTerminated
133
134
  log_ex(ex)
134
135
  end
135
136
 
@@ -192,11 +193,11 @@ class Eye::Checker
192
193
  process.notify :warn, "Bounded #{check_name}: #{last_human_values} send to #{actions}"
193
194
 
194
195
  actions.each do |action|
195
- reason = Eye::Reason.new("bounded #{check_name}")
196
+ reason = "bounded #{check_name}"
196
197
  if action.is_a?(Proc)
197
- process.schedule :execute_proc, reason, &action
198
+ process.schedule command: :instance_exec, reason: reason, block: action
198
199
  else
199
- process.schedule action, reason
200
+ process.schedule command: action, reason: reason
200
201
  end
201
202
  end
202
203
  end
@@ -14,7 +14,7 @@ class Eye::Checker::ChildrenCount < Eye::Checker::Measure
14
14
  super
15
15
  else
16
16
  pids = ordered_by_date_children_pids
17
- pids = (strategy == :kill_old) ? pids[0...-below] : pids[below..-1]
17
+ pids = strategy == :kill_old ? pids[0...-below] : pids[below..-1]
18
18
  kill_pids(pids)
19
19
  end
20
20
  end
@@ -25,14 +25,14 @@ private
25
25
  info "killing pids: #{pids.inspect} for strategy: #{strategy}"
26
26
  pids.each do |pid|
27
27
  if child = process.children[pid]
28
- child.schedule :stop, Eye::Reason.new("bounded #{check_name}")
28
+ child.schedule command: :stop, reason: "bounded #{check_name}"
29
29
  end
30
30
  end
31
31
  end
32
32
 
33
33
  def ordered_by_date_children_pids
34
34
  children = process.children.values
35
- children.sort_by { |ch| Eye::SystemResources.start_time(ch.pid).to_i }.map(&:pid)
35
+ children.sort_by { |ch| [Eye::SystemResources.start_time(ch.pid).to_i, ch.pid] }.map(&:pid)
36
36
  end
37
37
 
38
38
  end
@@ -52,11 +52,8 @@ class Eye::Checker::Socket < Eye::Checker::Defer
52
52
  { result: result }
53
53
  end
54
54
  rescue Timeout::Error
55
- if protocol == :raw
56
- return { result: @buffer }
57
- else
58
- return { exception: "ReadTimeout<#{@read_timeout}>" }
59
- end
55
+ return { result: @buffer } if protocol == :raw
56
+ { exception: "ReadTimeout<#{@read_timeout}>" }
60
57
  end
61
58
 
62
59
  rescue Exception => e
@@ -103,14 +100,12 @@ class Eye::Checker::Socket < Eye::Checker::Defer
103
100
  '-'
104
101
  elsif value[:exception]
105
102
  value[:exception]
103
+ elsif value[:result] == :listen
104
+ 'listen'
106
105
  else
107
- if value[:result] == :listen
108
- 'listen'
109
- else
110
- res = "#{value[:result].to_s.size}b"
111
- res += "<#{value[:notice]}>" if value[:notice]
112
- res
113
- end
106
+ res = "#{value[:result].to_s.size}b"
107
+ res += "<#{value[:notice]}>" if value[:notice]
108
+ res
114
109
  end
115
110
  end
116
111
 
@@ -25,19 +25,21 @@ class Eye::ChildProcess
25
25
  # scheduler
26
26
  include Eye::Process::Scheduler
27
27
 
28
- attr_reader :pid, :name, :full_name, :config, :watchers, :parent
28
+ attr_reader :pid, :name, :full_name, :config, :watchers
29
29
 
30
30
  def initialize(pid, config = {}, logger_prefix = nil, parent = nil)
31
31
  raise 'Empty pid' unless pid
32
32
 
33
33
  @pid = pid
34
- @parent = parent
35
34
  @config = prepare_config(config)
36
35
  @name = "child-#{pid}"
37
36
  @full_name = [logger_prefix, @name].join(':')
38
37
 
39
38
  @watchers = {}
40
39
 
40
+ @scheduler_history = parent.scheduler_history
41
+ @parent_pid = parent.pid
42
+
41
43
  debug { "start monitoring CHILD config: #{@config.inspect}" }
42
44
 
43
45
  start_checkers
@@ -55,10 +57,6 @@ class Eye::ChildProcess
55
57
  state == :up
56
58
  end
57
59
 
58
- def send_command(command, *args)
59
- schedule command, *args, Eye::Reason::User.new(command)
60
- end
61
-
62
60
  def start
63
61
  end
64
62
 
@@ -97,7 +95,7 @@ class Eye::ChildProcess
97
95
  end
98
96
 
99
97
  def prepare_command(command) # override
100
- super.gsub('{PARENT_PID}', @parent.pid.to_s)
98
+ super.gsub('{PARENT_PID}', @parent_pid.to_s)
101
99
  end
102
100
 
103
101
  end
@@ -16,9 +16,11 @@ class Eye::Cli < Thor
16
16
  desc 'info [MASK]', 'processes info'
17
17
  method_option :json, type: :boolean, aliases: '-j'
18
18
  method_option :procline, type: :boolean, aliases: '-p'
19
+ method_option :debug, type: :boolean, aliases: '-d'
19
20
  def info(mask = nil)
20
21
  h = {}
21
22
  h[:procline] = true if options[:procline]
23
+ h[:debug] = true if options[:debug]
22
24
 
23
25
  res = cmd(:info_data, *Array(mask), h)
24
26
  if mask && res[:subtree] && res[:subtree].empty?
@@ -203,6 +205,10 @@ class Eye::Cli < Thor
203
205
  send_command(:user_command, cmd, *args)
204
206
  end
205
207
 
208
+ def self.exit_on_failure?
209
+ true
210
+ end
211
+
206
212
  private
207
213
 
208
214
  def error!(msg)
@@ -229,8 +235,4 @@ private
229
235
  say JSON.dump(obj)
230
236
  end
231
237
 
232
- def self.exit_on_failure?
233
- true
234
- end
235
-
236
238
  end
@@ -7,7 +7,7 @@ private
7
7
  end
8
8
 
9
9
  def _cmd(cmd, *args)
10
- client.command(cmd, *args)
10
+ client.execute(command: cmd, args: args)
11
11
  rescue Errno::ECONNREFUSED, Errno::ENOENT
12
12
  :not_started
13
13
  end
@@ -58,11 +58,11 @@ private
58
58
  data.each do |k, v|
59
59
  s << "#{"#{k}:".ljust(10)} "
60
60
 
61
- case k
61
+ s << case k
62
62
  when :resources
63
- s << resources_str(v)
63
+ resources_str(v)
64
64
  else
65
- s << "#{v}"
65
+ v.to_s
66
66
  end
67
67
 
68
68
  s << "\n"
@@ -106,8 +106,6 @@ private
106
106
  "#{at} - #{state} (#{h[:reason]})\n"
107
107
  end
108
108
 
109
- private
110
-
111
109
  def render_element(data, level)
112
110
  off = level * 2
113
111
  off_str = ' ' * off
@@ -131,6 +129,9 @@ private
131
129
  if data[:state_reason] && data[:state] == 'unmonitored'
132
130
  str += " (#{data[:state_reason]} at #{Eye::Utils.human_time2(data[:state_changed_at])})"
133
131
  end
132
+ if debug = data[:debug]
133
+ str += " (#{debug.inspect})"
134
+ end
134
135
  elsif data[:current_command]
135
136
  chain_progress = if data[:chain_progress]
136
137
  " #{data[:chain_progress][0]} of #{data[:chain_progress][1]}" rescue ''
@@ -9,12 +9,17 @@ class Eye::Client
9
9
  @socket_path = socket_path
10
10
  end
11
11
 
12
- def command(cmd, *args)
13
- attempt_command(Marshal.dump([cmd, *args]))
12
+ def execute(h = {})
13
+ payload = Marshal.dump(h)
14
+ payload = payload.length.to_s + "\n" + payload
15
+ timeout = h[:timeout] || Eye::Local.client_timeout
16
+ attempt_command(payload, timeout)
14
17
  end
15
18
 
16
- def attempt_command(pack)
17
- Timeout.timeout(Eye::Local.client_timeout) { send_request(pack) }
19
+ private
20
+
21
+ def attempt_command(payload, timeout)
22
+ Timeout.timeout(timeout) { send_request(payload) }
18
23
  rescue Timeout::Error, EOFError
19
24
  :timeouted
20
25
  end