eye 0.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b1592106a2ce3c26da8ad55f6b0036b10e5932fc
4
+ data.tar.gz: ff73a4ae40c4eeef57e9c50df0e50e8220eb187f
5
+ SHA512:
6
+ metadata.gz: b81127c859a0e48c6a08b7109582cddcdb12731b93eca191ae3fe65289703075e32c53f3552db24fcca3d693e61ada93ca7bfcae1bed4488724c54918ed6c880
7
+ data.tar.gz: 22e769a89a91343374045e502404f2fa26002f9a641807d4f772354774a3f88837cf486afb18da4880738548d9b8522f0c865e2b9c8ed2ae6cc9757d3da1ea78
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Eye
2
2
  ===
3
3
 
4
- Process monitoring tool. Alternative for God and Bluepill. With Bluepill like config syntax. Requires MRI Ruby >= 1.9.2. Uses Celluloid and Celluloid::IO.
4
+ Process monitoring tool. An alternative to God and Bluepill. With Bluepill like config syntax. Requires MRI Ruby >= 1.9.2. Uses Celluloid and Celluloid::IO.
5
5
 
6
6
 
7
7
  Recommended installation on the server (system wide):
@@ -153,3 +153,8 @@ Quit monitoring:
153
153
  Config explain (for debug):
154
154
 
155
155
  $ eye explain examples/test.eye
156
+
157
+
158
+ ### Config api:
159
+
160
+ Waiting for pull requests ..., until that you can read `examples` and `spec/dsl` folders.
data/bin/eye CHANGED
@@ -266,13 +266,10 @@ private
266
266
  true
267
267
  end
268
268
 
269
- def wait_server
270
- Timeout.timeout(15) do
271
- while !server_started?
272
- sleep 0.3
273
- end
269
+ def wait_server(timeout = 15)
270
+ Timeout.timeout(timeout) do
271
+ sleep 0.3 while !server_started?
274
272
  end
275
-
276
273
  true
277
274
  rescue Timeout::Error
278
275
  false
data/examples/puma.eye ADDED
@@ -0,0 +1,34 @@
1
+ RUBY = '/usr/local/ruby/1.9.3-p392/bin/ruby'
2
+ RAILS_ENV = 'production'
3
+ ROOT = '/var/www/super_app'
4
+ CURRENT = File.expand_path(File.join(ROOT, %w{current}))
5
+ LOGS = File.expand_path(File.join(ROOT, %w{shared log}))
6
+ PIDS = File.expand_path(File.join(ROOT, %w{shared pids}))
7
+
8
+ Eye.config do
9
+ logger "#{LOGS}/eye.log"
10
+ logger_level Logger::ERROR
11
+ end
12
+
13
+ Eye.application :super_app do
14
+ env 'RAILS_ENV' => RAILS_ENV
15
+ working_dir CURRENT
16
+ triggers :flapping, :times => 10, :within => 1.minute
17
+
18
+ process :puma do
19
+ daemonize true
20
+ pid_file "#{PIDS}/puma.pid"
21
+ stdall "#{LOGS}/#{RAILS_ENV}.log"
22
+
23
+ start_command "#{RUBY} bin/puma --port 80 --pidfile #{PIDS}/puma.pid --environment #{RAILS_ENV} config.ru"
24
+ stop_command "kill -TERM {{PID}}"
25
+ restart_command "kill -USR2 {{PID}}"
26
+
27
+ start_timeout 15.seconds
28
+ stop_grace 10.seconds
29
+ restart_grace 10.seconds
30
+
31
+ checks :cpu, :every => 30, :below => 80, :times => 3
32
+ checks :memory, :every => 30, :below => 70.megabytes, :times => [3,5]
33
+ end
34
+ end
data/eye.gemspec CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
5
5
  gem.email = "kostya27@gmail.com"
6
6
 
7
7
  gem.description = gem.summary = \
8
- %q{Process monitoring tool. Alternative for God and Bluepill. With Bluepill like config syntax. Requires MRI Ruby >= 1.9.2. Uses Celluloid and Celluloid::IO.}
8
+ %q{Process monitoring tool. An alternative to God and Bluepill. With Bluepill like config syntax. Requires MRI Ruby >= 1.9.2. Uses Celluloid and Celluloid::IO.}
9
9
  gem.homepage = "http://github.com/kostya/eye"
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
data/lib/eye.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Eye
2
- VERSION = "0.2"
2
+ VERSION = "0.2.1"
3
3
  ABOUT = "Eye v#{VERSION} (c) 2012-2013 @kostya"
4
4
 
5
5
  autoload :Process, 'eye/process'
@@ -22,5 +22,4 @@ module Eye
22
22
  autoload :Control, 'eye/control'
23
23
  end
24
24
 
25
- ROOT_BINDING = binding
26
- ENV_LANG = ENV['LANG'] # save original LANG, because ruby somehow rewrite it
25
+ ENV_LANG = ENV['LANG'] # save original LANG, bug of celluloid 0.12
@@ -24,6 +24,11 @@ class Eye::Application
24
24
  @groups << group
25
25
  end
26
26
 
27
+ # sort processes in name order
28
+ def resort_groups
29
+ @groups = @groups.sort_by{|gr| gr.name == '__default__' ? 'zzzzz' : gr.name }
30
+ end
31
+
27
32
  def status_data(debug = false)
28
33
  h = { name: @name, type: :application, subtree: @groups.map{|gr| gr.status_data(debug) }}
29
34
  h.merge!(debug: debug_data) if debug
data/lib/eye/checker.rb CHANGED
@@ -51,6 +51,7 @@ class Eye::Checker
51
51
  end
52
52
 
53
53
  def check
54
+ tm1 = Time.now
54
55
  @value = get_value
55
56
  @values << {:value => @value, :good => good?(value)}
56
57
 
@@ -61,7 +62,7 @@ class Eye::Checker
61
62
  result = false if bad_count >= min_tries
62
63
  end
63
64
 
64
- info "#{last_human_values} => #{result ? 'OK' : 'Fail'}"
65
+ info "#{last_human_values} => #{result ? 'OK' : 'Fail'} (#{Time.now - tm1}s)"
65
66
  result
66
67
  end
67
68
 
@@ -12,7 +12,7 @@ class Eye::Checker::Http < Eye::Checker
12
12
  param :open_timeout, [Fixnum, Float]
13
13
  param :read_timeout, [Fixnum, Float]
14
14
 
15
- attr_reader :session, :uri
15
+ attr_reader :uri
16
16
 
17
17
  def check_name
18
18
  'http'
@@ -29,49 +29,49 @@ class Eye::Checker::Http < Eye::Checker
29
29
  else
30
30
  Net::HTTPSuccess
31
31
  end
32
- @open_timeout = (open_timeout || timeout || 5).to_i
33
- @read_timeout = (read_timeout || timeout || 30).to_i
34
-
35
- @session = Net::HTTP.new(@uri.host, @uri.port)
36
- if @uri.scheme == 'https'
37
- require 'net/https'
38
- @session.use_ssl=true
39
- @session.verify_mode = OpenSSL::SSL::VERIFY_NONE
40
- end
41
- @session.open_timeout = @open_timeout
42
- @session.read_timeout = @read_timeout
32
+ @open_timeout = (open_timeout || 3).to_f
33
+ @read_timeout = (read_timeout || timeout || 15).to_f
43
34
  end
44
-
35
+
45
36
  def get_value
46
37
  Celluloid::Future.new{ get_value_sync }.value
47
38
  end
48
39
 
49
40
  def get_value_sync
50
- res = @session.start do |http|
51
- http.get(@uri.path)
52
- end
53
-
41
+ _session = session
42
+ res = _session.start{ |http| http.get(@uri.path) }
54
43
  {:result => res}
55
44
 
56
- rescue Timeout::Error
57
- debug 'Timeout error'
58
- {:exception => :timeout}
45
+ rescue Timeout::Error => ex
46
+ debug ex.inspect
47
+
48
+ if defined?(Net::OpenTimeout) # for ruby 2.0
49
+ mes = ex.class.is_a?(Net::OpenTimeout) ? "OpenTimeout<#{@open_timeout}>" : "ReadTimeout<#{@read_timeout}>"
50
+ {:exception => mes}
51
+ else
52
+ error "#{ex.message}"
53
+ {:exception => "Timeout<#{@open_timeout},#{@read_timeout}>"}
54
+ end
59
55
 
60
56
  rescue => ex
61
- error "Exception #{ex.message}"
62
- {:exception => ex.message}
57
+ {:exception => "Error<#{ex.message}>"}
63
58
  end
64
59
 
65
60
  def good?(value)
66
61
  return false unless value[:result]
67
- return false unless value[:result].kind_of?(@kind)
62
+
63
+ unless value[:result].kind_of?(@kind)
64
+ return false
65
+ end
68
66
 
69
67
  if @pattern
70
- if @pattern.is_a?(Regexp)
68
+ matched = if @pattern.is_a?(Regexp)
71
69
  @pattern === value[:result].body
72
70
  else
73
71
  value[:result].body.include?(@pattern.to_s)
74
72
  end
73
+ value[:notice] = "missing '#{@pattern.to_s}'" unless matched
74
+ matched
75
75
  else
76
76
  true
77
77
  end
@@ -81,13 +81,26 @@ class Eye::Checker::Http < Eye::Checker
81
81
  if !value.is_a?(Hash)
82
82
  '-'
83
83
  elsif value[:exception]
84
- if value[:exception] == :timeout
85
- 'T-out'
86
- else
87
- 'Err'
88
- end
84
+ value[:exception]
89
85
  else
90
- "#{value[:result].code}=#{value[:result].body.size/ 1024}Kb"
86
+ body_size = value[:result].body.size / 1024
87
+ msg = "#{value[:result].code}=#{body_size}Kb"
88
+ msg += "<#{value[:notice]}>" if value[:notice]
89
+ msg
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ def session
96
+ Net::HTTP.new(@uri.host, @uri.port).tap do |session|
97
+ if @uri.scheme == 'https'
98
+ require 'net/https'
99
+ session.use_ssl=true
100
+ session.verify_mode = OpenSSL::SSL::VERIFY_NONE
101
+ end
102
+ session.open_timeout = @open_timeout
103
+ session.read_timeout = @read_timeout
91
104
  end
92
105
  end
93
106
 
@@ -26,8 +26,8 @@ class Eye::Checker::Socket < Eye::Checker
26
26
 
27
27
  def initialize(*args)
28
28
  super
29
- @open_timeout = (open_timeout || 1).to_i
30
- @read_timeout = (read_timeout || timeout || 5).to_i
29
+ @open_timeout = (open_timeout || 1).to_f
30
+ @read_timeout = (read_timeout || timeout || 5).to_f
31
31
 
32
32
  if addr =~ %r[\Atcp://(.*?):(.*?)\z]
33
33
  @socket_family = :tcp
@@ -44,32 +44,29 @@ class Eye::Checker::Socket < Eye::Checker
44
44
  end
45
45
 
46
46
  def get_value_sync
47
- sock = Timeout::timeout(@open_timeout) do
48
- if @socket_family == :tcp
49
- TCPSocket.open(@socket_addr, @socket_port)
50
- elsif @socket_family == :unix
51
- UNIXSocket.open(@socket_path)
52
- else
53
- raise "Unknown socket addr #{addr}"
54
- end
47
+ sock = begin
48
+ Timeout::timeout(@open_timeout){ open_socket }
49
+ rescue Timeout::Error
50
+ return { :exception => "OpenTimeout<#{@open_timeout}>" }
55
51
  end
56
52
 
57
53
  if send_data
58
- Timeout::timeout(@read_timeout) do
59
- _write_data(sock, send_data)
60
- { :result => _read_data(sock) }
54
+ begin
55
+ Timeout::timeout(@read_timeout) do
56
+ _write_data(sock, send_data)
57
+ result = _read_data(sock)
58
+
59
+ { :result => result }
60
+ end
61
+ rescue Timeout::Error
62
+ return { :exception => "ReadTimeout<#{@read_timeout}>" }
61
63
  end
62
64
  else
63
65
  { :result => :listen }
64
66
  end
65
67
 
66
- rescue Timeout::Error
67
- debug 'Timeout error'
68
- { :exception => :timeout }
69
-
70
68
  rescue Exception => e
71
- warn "Exception #{e.message}"
72
- { :exception => e.message }
69
+ { :exception => "Error<#{e.message}>" }
73
70
 
74
71
  ensure
75
72
  sock.close if sock
@@ -83,18 +80,25 @@ class Eye::Checker::Socket < Eye::Checker
83
80
  match = begin
84
81
  !!expect_data[value[:result]]
85
82
  rescue Timeout::Error, Exception => ex
86
- error "proc match failed with #{ex.message}"
83
+ mes = "proc match failed with '#{ex.message}'"
84
+ error(mes)
85
+ value[:notice] = mes
87
86
  return false
88
87
  end
89
88
 
90
- warn "proc #{expect_data} not matched (#{value[:result].truncate(30)}) answer" unless match
89
+ unless match
90
+ warn "proc #{expect_data} not matched (#{value[:result].truncate(30)}) answer"
91
+ value[:notice] = "missing proc validation"
92
+ end
93
+
91
94
  return match
92
95
  end
93
96
 
94
97
  return true if expect_data.is_a?(Regexp) && expect_data.match(value[:result])
95
98
  return true if value[:result].to_s == expect_data.to_s
96
99
 
97
- warn "#{expect_data} not matched (#{value[:result].truncate(30)}) answer"
100
+ warn "#{expect_data} not matched (#{value[:result].truncate(30)}) answer"
101
+ value[:notice] = "missing '#{expect_data.to_s}'"
98
102
  return false
99
103
  end
100
104
 
@@ -105,22 +109,30 @@ class Eye::Checker::Socket < Eye::Checker
105
109
  if !value.is_a?(Hash)
106
110
  '-'
107
111
  elsif value[:exception]
108
- if value[:exception] == :timeout
109
- 'T-out'
110
- else
111
- "Err(#{value[:exception]})"
112
- end
112
+ value[:exception]
113
113
  else
114
114
  if value[:result] == :listen
115
115
  "listen"
116
116
  else
117
- "#{value[:result].to_s.size}b"
117
+ res = "#{value[:result].to_s.size}b"
118
+ res += "<#{value[:notice]}>" if value[:notice]
119
+ res
118
120
  end
119
121
  end
120
122
  end
121
123
 
122
124
  private
123
125
 
126
+ def open_socket
127
+ if @socket_family == :tcp
128
+ TCPSocket.open(@socket_addr, @socket_port)
129
+ elsif @socket_family == :unix
130
+ UNIXSocket.open(@socket_path)
131
+ else
132
+ raise "Unknown socket addr #{addr}"
133
+ end
134
+ end
135
+
124
136
  def _write_data(socket, data)
125
137
  case protocol
126
138
  when :em_object
@@ -50,6 +50,10 @@ class Eye::ChildProcess
50
50
  :up
51
51
  end
52
52
 
53
+ def up?
54
+ state == :up
55
+ end
56
+
53
57
  def send_command(command, *args)
54
58
  schedule command, *args, "#{command} by user"
55
59
  end
@@ -38,6 +38,8 @@ class Eye::Controller
38
38
  Celluloid::logger = Eye.logger
39
39
 
40
40
  Eye::SystemResources.setup
41
+
42
+ info "starting #{Eye::ABOUT}"
41
43
  end
42
44
 
43
45
  end
@@ -183,6 +183,8 @@ private
183
183
  @added_groups = nil
184
184
  @added_processes = nil
185
185
 
186
+ app.resort_groups
187
+
186
188
  app
187
189
  end
188
190
 
data/lib/eye/dsl.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require_relative 'dsl/helpers'
2
2
 
3
+ Eye::BINDING = binding
4
+
3
5
  class Eye::Dsl
4
6
 
5
7
  autoload :Main, 'eye/dsl/main'
@@ -34,7 +36,7 @@ class Eye::Dsl
34
36
  content = File.read(filename) if content.blank?
35
37
 
36
38
  silence_warnings do
37
- Kernel.eval(content, ROOT_BINDING, filename.to_s)
39
+ Kernel.eval(content, Eye::BINDING, filename.to_s)
38
40
  end
39
41
 
40
42
  validate(Eye.parsed_config)
data/lib/eye/dsl/opts.rb CHANGED
@@ -92,4 +92,13 @@ class Eye::Dsl::Opts < Eye::Dsl::PureOpts
92
92
  set_stderr value
93
93
  end
94
94
 
95
+ def scoped(&block)
96
+ h = self.class.new(self.name, self)
97
+ h.instance_eval(&block)
98
+ groups = h.config.delete :groups
99
+ processes = h.config.delete :processes
100
+ self.config[:groups].merge!(groups) if groups.present?
101
+ self.config[:processes].merge!(processes) if processes.present?
102
+ end
103
+
95
104
  end
data/lib/eye/process.rb CHANGED
@@ -58,7 +58,7 @@ class Eye::Process
58
58
  # add_watchers, remove_watchers:
59
59
  include Eye::Process::Watchers
60
60
 
61
- # check alive, crush methods:
61
+ # check alive, crash methods:
62
62
  include Eye::Process::Monitor
63
63
 
64
64
  # system methods:
@@ -25,7 +25,7 @@ module Eye::Process::Commands
25
25
  end
26
26
 
27
27
  self.pid = nil
28
- switch :crushed
28
+ switch :crashed
29
29
  end
30
30
 
31
31
  result
@@ -75,7 +75,7 @@ module Eye::Process::Commands
75
75
  execute_restart_command
76
76
  sleep self[:restart_timeout].to_f
77
77
  result = check_alive_with_refresh_pid_if_needed
78
- switch(result ? :restarted : :crushed)
78
+ switch(result ? :restarted : :crashed)
79
79
  else
80
80
  stop_process
81
81
  start_process
@@ -166,8 +166,7 @@ private
166
166
  res = Eye::System.daemonize(self[:start_command], config)
167
167
  start_time = Time.now - time_before
168
168
 
169
- info "daemonizing: `#{self[:start_command]}` with start_grace: #{self[:start_grace].to_f}s, env: #{self[:environment].inspect}, working_dir: #{self[:working_dir]}"
170
-
169
+ info "daemonizing: `#{self[:start_command]}` with start_grace: #{self[:start_grace].to_f}s, env: #{self[:environment].inspect}, working_dir: #{self[:working_dir]} (pid:#{res[:pid]})"
171
170
 
172
171
  if res[:error]
173
172
  error "raised with #{res[:error].inspect}"
@@ -189,7 +188,7 @@ private
189
188
  sleep self[:start_grace].to_f
190
189
 
191
190
  unless process_realy_running?
192
- error "process with pid (#{self.pid}) not found, may be crushed (#{check_logs_str})"
191
+ error "process with pid (#{self.pid}) not found, may be crashed (#{check_logs_str})"
193
192
  return {:error => :not_realy_running}
194
193
  end
195
194
 
@@ -232,11 +231,12 @@ private
232
231
  end
233
232
 
234
233
  unless process_realy_running?
235
- error "process in pid_file(#{self[:pid_file]})(#{self.pid}) not found, maybe process do not write there actual pid, or just crushed (#{check_logs_str})"
234
+ error "process in pid_file(#{self[:pid_file]})(#{self.pid}) not found, maybe process do not write there actual pid, or just crashed (#{check_logs_str})"
236
235
  return {:error => :not_realy_running}
237
236
  end
238
237
 
239
238
  res[:pid] = self.pid
239
+ info "process get pid:#{res[:pid]}"
240
240
  res
241
241
  end
242
242
 
@@ -1,7 +1,7 @@
1
1
  module Eye::Process::Config
2
2
 
3
3
  DEFAULTS = {
4
- :keep_alive => true, # restart when crushed
4
+ :keep_alive => true, # restart when crashed
5
5
  :check_alive_period => 5.seconds,
6
6
 
7
7
  :start_timeout => 15.seconds,
@@ -39,16 +39,16 @@ private
39
39
  # check that process runned
40
40
  unless process_realy_running?
41
41
  warn 'check_alive: process not found'
42
- notify :warn, 'crushed!'
43
- switch :crushed
42
+ notify :warn, 'crashed!'
43
+ switch :crashed
44
44
  else
45
45
  # check that pid_file still here
46
46
  ppid = failsafe_load_pid
47
47
 
48
48
  if ppid != self.pid
49
- msg = "check_alive: pid_file(#{self[:pid_file]}) changes by itself (#{self.pid}) => (#{ppid})"
49
+ msg = "check_alive: pid_file(#{self[:pid_file]}) changes by itself (pid:#{self.pid}) => (pid:#{ppid})"
50
50
  if control_pid?
51
- msg += ", not correct, pid_file is under eye control, so rewrited back #{self.pid}"
51
+ msg += ", not correct, pid_file is under eye control, so rewrited back pid:#{self.pid}"
52
52
  save_pid_to_file rescue msg += ', (Can`t rewrite pid_file O_o)'
53
53
  else
54
54
  if ppid == nil
@@ -80,18 +80,18 @@ private
80
80
  pid
81
81
  end
82
82
 
83
- def check_crush
83
+ def check_crash
84
84
  if down?
85
85
  if self[:keep_alive] && !@flapping
86
- warn 'check crushed: process is down'
87
- schedule :start, 'crushed'
86
+ warn 'check crashed: process is down'
87
+ schedule :start, 'crashed'
88
88
  else
89
- warn 'check crushed: process is down, and flapping happens (or not keep_alive option)'
89
+ warn 'check crashed: process is down, and flapping happens (or not keep_alive option)'
90
90
  schedule :unmonitor, 'flapping'
91
91
  end
92
92
  end
93
93
  end
94
94
 
95
- public :check_crush # bug of celluloid 0.12
95
+ public :check_crash # bug of celluloid 0.12
96
96
 
97
97
  end
@@ -1,7 +1,7 @@
1
1
  module Eye::Process::Notify
2
2
 
3
3
  # notify to user:
4
- # 1) process crushed by itself, and we restart it [:warn]
4
+ # 1) process crashed by itself, and we restart it [:warn]
5
5
  # 2) checker bounded to restart process [:crit]
6
6
  # 3) flapping + switch to unmonitored [:crit]
7
7
 
@@ -25,7 +25,7 @@ class Eye::Process
25
25
  transition :starting => :up
26
26
  end
27
27
 
28
- event :crushed do
28
+ event :crashed do
29
29
  transition [:starting, :restarting, :up] => :down
30
30
  end
31
31
 
@@ -53,7 +53,7 @@ class Eye::Process
53
53
  transition any => :unmonitored
54
54
  end
55
55
 
56
- after_transition :on => :crushed, :do => :on_crushed
56
+ after_transition :on => :crashed, :do => :on_crashed
57
57
  after_transition any => :unmonitored, :do => :on_unmonitored
58
58
  after_transition any-:up => :up, :do => :on_up
59
59
  after_transition :up => any-:up, :do => :from_up
@@ -61,8 +61,8 @@ class Eye::Process
61
61
  after_transition any => any, :do => :upd_for_triggers
62
62
  end
63
63
 
64
- def on_crushed
65
- schedule :check_crush, 'crushed'
64
+ def on_crashed
65
+ schedule :check_crash, 'crashed'
66
66
  end
67
67
 
68
68
  def on_unmonitored
@@ -59,6 +59,8 @@ private
59
59
 
60
60
  def watcher_tick(subject)
61
61
  unless subject.check
62
+ return unless up?
63
+
62
64
  notify :crit, "Bounded #{subject.check_name}: #{subject.last_human_values}"
63
65
  schedule :restart, "bounded #{subject.check_name}"
64
66
  end
data/lib/eye/utils.rb CHANGED
@@ -10,5 +10,5 @@ module Eye::Utils
10
10
  else value
11
11
  end
12
12
  end
13
-
13
+
14
14
  end
@@ -18,7 +18,7 @@ describe "Eye::Checker::Http" do
18
18
  it "initialize" do
19
19
  subject.instance_variable_get(:@kind).should == Net::HTTPSuccess
20
20
  subject.instance_variable_get(:@pattern).should == /OK/
21
- subject.instance_variable_get(:@open_timeout).should == 2
21
+ subject.instance_variable_get(:@open_timeout).should == 3
22
22
  subject.instance_variable_get(:@read_timeout).should == 2
23
23
  end
24
24
 
@@ -34,17 +34,22 @@ describe "Eye::Checker::Http" do
34
34
  end
35
35
 
36
36
  it "get_value exception" do
37
+ a = ""
38
+ stub(subject).session{ a }
37
39
  stub(subject.session).start{ raise Timeout::Error, "timeout" }
38
- subject.get_value.should == {:exception => :timeout}
40
+ mes = RUBY_VERSION < '2.0' ? "Timeout<3.0,2.0>" : "ReadTimeout<2.0>"
39
41
 
40
- subject.human_value(subject.get_value).should == "T-out"
42
+ subject.get_value.should == {:exception => mes}
43
+ subject.human_value(subject.get_value).should == mes
41
44
  end
42
45
 
43
46
  it "get_value raised" do
47
+ a = ""
48
+ stub(subject).session{ a }
44
49
  stub(subject.session).start{ raise "something" }
45
- subject.get_value.should == {:exception => "something"}
50
+ subject.get_value.should == {:exception => "Error<something>"}
46
51
 
47
- subject.human_value(subject.get_value).should == "Err"
52
+ subject.human_value(subject.get_value).should == "Error<something>"
48
53
  end
49
54
 
50
55
  end
@@ -30,7 +30,7 @@ describe "Socket Checker" do
30
30
 
31
31
  it "timeouted" do
32
32
  c = chsock(:addr => addr, :send_data => "timeout")
33
- c.get_value.should == {:exception => :timeout}
33
+ c.get_value.should == {:exception => "ReadTimeout<2.0>"}
34
34
  c.check.should == false
35
35
  end
36
36
 
@@ -47,7 +47,7 @@ describe "Socket Checker" do
47
47
  @process.stop
48
48
  c = chsock(:addr => addr.chop)
49
49
  if addr =~ /tcp/
50
- c.get_value.should == {:exception => "Connection refused - connect(2)"}
50
+ c.get_value.should == {:exception => "Error<Connection refused - connect(2)>"}
51
51
  else
52
52
  c.get_value[:exception].should include("No such file or directory")
53
53
  end
@@ -63,7 +63,7 @@ describe "Socket Checker" do
63
63
  it "check responding without send_data" do
64
64
  c = chsock(:addr => addr.chop, :send_data => nil, :expect_data => nil)
65
65
  if addr =~ /tcp/
66
- c.get_value.should == {:exception => "Connection refused - connect(2)"}
66
+ c.get_value.should == {:exception => "Error<Connection refused - connect(2)>"}
67
67
  else
68
68
  c.get_value[:exception].should include("No such file or directory")
69
69
  end
@@ -10,10 +10,12 @@ def app_check(app, name, gr_size)
10
10
  app.name.should == name
11
11
  app.class.should == Eye::Application
12
12
  app.groups.size.should == gr_size
13
+ app.groups.class.should == Eye::Utils::AliveArray
13
14
  end
14
15
 
15
16
  def gr_check(gr, name, p_size, hidden = false)
16
17
  gr.class.should == Eye::Group
18
+ gr.processes.class.should == Eye::Utils::AliveArray
17
19
  gr.processes.size.should == p_size
18
20
  gr.name.should == name
19
21
  gr.hidden.should == hidden
data/spec/dsl/dsl_spec.rb CHANGED
@@ -69,5 +69,5 @@ describe "Eye::Dsl" do
69
69
  cfg['bla'][:groups]['__default__'][:some].should == nil
70
70
  cfg['bla'][:groups]['__default__'][:processes][:some].should == nil
71
71
  end
72
-
72
+
73
73
  end
@@ -308,4 +308,69 @@ describe "Eye::Dsl" do
308
308
  :environment=>{"P"=>"1"}}}}}
309
309
  end
310
310
 
311
+
312
+ describe "scoped" do
313
+ it "scoped" do
314
+ conf = <<-E
315
+ Eye.application("bla") do
316
+ group :gr do
317
+ env "A" => '1', "B" => '2'
318
+
319
+ process :a do
320
+ pid_file "1.pid"
321
+ end
322
+
323
+ scoped do
324
+ env "A" => '2'
325
+
326
+ process :b do
327
+ pid_file "2.pid"
328
+ end
329
+ end
330
+
331
+ process :c do
332
+ pid_file "3.pid"
333
+ end
334
+ end
335
+ end
336
+ E
337
+
338
+ Eye::Dsl.parse_apps(conf).should == {
339
+ "bla" => {:name=>"bla", :groups=>{
340
+ "gr"=>{:name=>"gr", :application=>"bla", :environment=>{"A"=>"1", "B"=>"2"},
341
+ :processes=>{
342
+ "a"=>{:name=>"a", :application=>"bla", :environment=>{"A"=>"1", "B"=>"2"}, :group=>"gr", :pid_file=>"1.pid"},
343
+ "b"=>{:name=>"b", :application=>"bla", :environment=>{"A"=>"2", "B"=>"2"}, :group=>"gr", :pid_file=>"2.pid"},
344
+ "c"=>{:name=>"c", :application=>"bla", :environment=>{"A"=>"1", "B"=>"2"}, :group=>"gr", :pid_file=>"3.pid"}}}}}}
345
+ end
346
+
347
+ it "scoped" do
348
+ conf = <<-E
349
+ Eye.application("bla") do
350
+ start_timeout 10.seconds
351
+
352
+ group(:a){}
353
+
354
+ scoped do
355
+ start_timeout 15.seconds
356
+ group(:b){
357
+ scoped do
358
+
359
+ end
360
+ }
361
+ end
362
+
363
+ group(:c){}
364
+ end
365
+ E
366
+
367
+ Eye::Dsl.parse_apps(conf).should == {
368
+ "bla" => {:name=>"bla", :start_timeout=>10, :groups=>{
369
+ "a"=>{:name=>"a", :start_timeout=>10, :application=>"bla", :processes=>{}},
370
+ "b"=>{:name=>"b", :start_timeout=>15, :application=>"bla", :processes=>{}},
371
+ "c"=>{:name=>"c", :start_timeout=>10, :application=>"bla", :processes=>{}}}}}
372
+ end
373
+
374
+ end
375
+
311
376
  end
@@ -124,7 +124,7 @@ describe "Process Controller" do
124
124
  end
125
125
  end
126
126
 
127
- describe "process cant start, crush each time" do
127
+ describe "process cant start, crash each time" do
128
128
  before :each do
129
129
  @process = process(C.p2.merge(:start_command => C.p2[:start_command] + " -r" ))
130
130
  @process.send_command :start
@@ -3,7 +3,7 @@ require File.dirname(__FILE__) + '/../spec_helper'
3
3
  describe "Process Monitoring" do
4
4
 
5
5
  [C.p1, C.p2].each do |cfg|
6
- it "process crushed, should restart #{cfg[:name]}" do
6
+ it "process crashed, should restart #{cfg[:name]}" do
7
7
  start_ok_process(cfg)
8
8
  old_pid = @pid
9
9
 
@@ -6,7 +6,7 @@ describe "Process Restart" do
6
6
  start_ok_process(cfg)
7
7
  old_pid = @pid
8
8
 
9
- dont_allow(@process).check_crush
9
+ dont_allow(@process).check_crash
10
10
  @process.restart
11
11
 
12
12
  @process.pid.should_not == old_pid
@@ -26,7 +26,7 @@ describe "Process Restart" do
26
26
  start_ok_process(cfg.merge(:stop_command => "kill -9 {{PID}}"))
27
27
  old_pid = @pid
28
28
 
29
- dont_allow(@process).check_crush
29
+ dont_allow(@process).check_crash
30
30
  @process.restart
31
31
 
32
32
  @process.pid.should_not == old_pid
@@ -46,7 +46,7 @@ describe "Process Restart" do
46
46
  start_ok_process(cfg.merge(:restart_command => "kill -USR1 {{PID}}"))
47
47
  old_pid = @pid
48
48
 
49
- dont_allow(@process).check_crush
49
+ dont_allow(@process).check_crash
50
50
  @process.restart
51
51
 
52
52
  sleep 3
@@ -71,7 +71,7 @@ describe "Process Restart" do
71
71
  start_ok_process(cfg.merge(:stop_command => "kill -USR1 {{PID}}"))
72
72
  old_pid = @pid
73
73
 
74
- dont_allow(@process).check_crush
74
+ dont_allow(@process).check_crash
75
75
  @process.restart
76
76
 
77
77
  sleep 3
@@ -93,7 +93,7 @@ describe "Process Restart" do
93
93
  # so monitor should see that process died, and up it
94
94
  start_ok_process(cfg.merge(:restart_command => "kill -9 {{PID}}"))
95
95
 
96
- mock(@process).check_crush
96
+ mock(@process).check_crash
97
97
 
98
98
  @process.restart
99
99
  Eye::System.pid_alive?(@pid).should == false
@@ -103,7 +103,7 @@ describe "Process Restart" do
103
103
  it "Bad restart command, invalid" do
104
104
  start_ok_process(cfg.merge(:restart_command => "asdfasdf sdf asd fasdf asdf"))
105
105
 
106
- dont_allow(@process).check_crush
106
+ dont_allow(@process).check_crash
107
107
 
108
108
  @process.restart
109
109
  Eye::System.pid_alive?(@pid).should == true
@@ -133,7 +133,7 @@ describe "Process Restart" do
133
133
  @process.state = st.to_s
134
134
  old_pid = @pid
135
135
 
136
- dont_allow(@process).check_crush
136
+ dont_allow(@process).check_crash
137
137
  @process.restart
138
138
 
139
139
  @process.pid.should_not == old_pid
@@ -69,7 +69,7 @@ describe "Process Start" do
69
69
  @process.state_name.should == :up
70
70
  end
71
71
 
72
- it "process crushed, with config #{c[:name]}" do
72
+ it "process crashed, with config #{c[:name]}" do
73
73
  @process = process(c.merge(:start_command => c[:start_command] + " -r" ))
74
74
  @process.start.should == {:error=>:not_realy_running}
75
75
 
@@ -89,7 +89,7 @@ describe "Process Start" do
89
89
 
90
90
  it "start with invalid command" do
91
91
  @process = process(c.merge(:start_command => "asdf asdf1 r f324 f324f 32f44f"))
92
- mock(@process).check_crush
92
+ mock(@process).check_crash
93
93
  res = @process.start
94
94
  res.should == {:error=>"#<Errno::ENOENT: No such file or directory - asdf>"}
95
95
 
@@ -103,7 +103,7 @@ describe "Process Start" do
103
103
 
104
104
  it "start PROBLEM with stdout permissions" do
105
105
  @process = process(c.merge(:stdout => "/var/run/1.log"))
106
- mock(@process).check_crush
106
+ mock(@process).check_crash
107
107
  res = @process.start
108
108
  res.should == {:error=>"#<Errno::EACCES: Permission denied - open>"}
109
109
 
@@ -117,7 +117,7 @@ describe "Process Start" do
117
117
 
118
118
  it "start PROBLEM binary permissions" do
119
119
  @process = process(c.merge(:start_command => "./sample.rb"))
120
- mock(@process).check_crush
120
+ mock(@process).check_crash
121
121
  res = @process.start
122
122
  res.should == {:error=>"#<Errno::EACCES: Permission denied - ./sample.rb>"}
123
123
 
@@ -40,7 +40,7 @@ describe "Process Stop" do
40
40
  it "stop process by default command" do
41
41
  start_ok_process
42
42
 
43
- dont_allow(@process).check_crush
43
+ dont_allow(@process).check_crash
44
44
  @process.stop_process
45
45
 
46
46
  Eye::System.pid_alive?(@pid).should == false
@@ -54,7 +54,7 @@ describe "Process Stop" do
54
54
  start_ok_process(C.p2.merge(:start_command => C.p2[:start_command] + " -T"))
55
55
  Eye::System.pid_alive?(@pid).should == true
56
56
 
57
- dont_allow(@process).check_crush
57
+ dont_allow(@process).check_crash
58
58
  @process.stop_process
59
59
 
60
60
  Eye::System.pid_alive?(@pid).should == false
@@ -67,7 +67,7 @@ describe "Process Stop" do
67
67
  it "stop process by specific command" do
68
68
  start_ok_process(C.p1.merge(:stop_command => "kill -9 {{PID}}"))
69
69
 
70
- dont_allow(@process).check_crush
70
+ dont_allow(@process).check_crash
71
71
  @process.stop_process
72
72
 
73
73
  Eye::System.pid_alive?(@pid).should == false
@@ -64,7 +64,7 @@ describe "Flapping" do
64
64
  @process.start!
65
65
 
66
66
  proxy(@process).schedule(:start, anything)
67
- proxy(@process).schedule(:check_crush, anything)
67
+ proxy(@process).schedule(:check_crash, anything)
68
68
  dont_allow(@process).schedule(:unmonitor)
69
69
 
70
70
 
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eye
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
5
- prerelease:
4
+ version: 0.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Konstantin Makarchev
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-03-09 00:00:00.000000000 Z
11
+ date: 2013-03-17 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: celluloid
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: celluloid-io
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,23 +41,20 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: state_machine
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: activesupport
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
@@ -78,196 +69,172 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: thor
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :runtime
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: rake
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - '>='
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - '>='
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0'
110
97
  - !ruby/object:Gem::Dependency
111
98
  name: rspec
112
99
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
100
  requirements:
115
- - - ! '>='
101
+ - - '>='
116
102
  - !ruby/object:Gem::Version
117
103
  version: '0'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
107
  requirements:
123
- - - ! '>='
108
+ - - '>='
124
109
  - !ruby/object:Gem::Version
125
110
  version: '0'
126
111
  - !ruby/object:Gem::Dependency
127
112
  name: simplecov
128
113
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
114
  requirements:
131
- - - ! '>='
115
+ - - '>='
132
116
  - !ruby/object:Gem::Version
133
117
  version: '0'
134
118
  type: :development
135
119
  prerelease: false
136
120
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
121
  requirements:
139
- - - ! '>='
122
+ - - '>='
140
123
  - !ruby/object:Gem::Version
141
124
  version: '0'
142
125
  - !ruby/object:Gem::Dependency
143
126
  name: rr
144
127
  requirement: !ruby/object:Gem::Requirement
145
- none: false
146
128
  requirements:
147
- - - ! '>='
129
+ - - '>='
148
130
  - !ruby/object:Gem::Version
149
131
  version: '0'
150
132
  type: :development
151
133
  prerelease: false
152
134
  version_requirements: !ruby/object:Gem::Requirement
153
- none: false
154
135
  requirements:
155
- - - ! '>='
136
+ - - '>='
156
137
  - !ruby/object:Gem::Version
157
138
  version: '0'
158
139
  - !ruby/object:Gem::Dependency
159
140
  name: ruby-graphviz
160
141
  requirement: !ruby/object:Gem::Requirement
161
- none: false
162
142
  requirements:
163
- - - ! '>='
143
+ - - '>='
164
144
  - !ruby/object:Gem::Version
165
145
  version: '0'
166
146
  type: :development
167
147
  prerelease: false
168
148
  version_requirements: !ruby/object:Gem::Requirement
169
- none: false
170
149
  requirements:
171
- - - ! '>='
150
+ - - '>='
172
151
  - !ruby/object:Gem::Version
173
152
  version: '0'
174
153
  - !ruby/object:Gem::Dependency
175
154
  name: forking
176
155
  requirement: !ruby/object:Gem::Requirement
177
- none: false
178
156
  requirements:
179
- - - ! '>='
157
+ - - '>='
180
158
  - !ruby/object:Gem::Version
181
159
  version: '0'
182
160
  type: :development
183
161
  prerelease: false
184
162
  version_requirements: !ruby/object:Gem::Requirement
185
- none: false
186
163
  requirements:
187
- - - ! '>='
164
+ - - '>='
188
165
  - !ruby/object:Gem::Version
189
166
  version: '0'
190
167
  - !ruby/object:Gem::Dependency
191
168
  name: fakeweb
192
169
  requirement: !ruby/object:Gem::Requirement
193
- none: false
194
170
  requirements:
195
- - - ! '>='
171
+ - - '>='
196
172
  - !ruby/object:Gem::Version
197
173
  version: '0'
198
174
  type: :development
199
175
  prerelease: false
200
176
  version_requirements: !ruby/object:Gem::Requirement
201
- none: false
202
177
  requirements:
203
- - - ! '>='
178
+ - - '>='
204
179
  - !ruby/object:Gem::Version
205
180
  version: '0'
206
181
  - !ruby/object:Gem::Dependency
207
182
  name: eventmachine
208
183
  requirement: !ruby/object:Gem::Requirement
209
- none: false
210
184
  requirements:
211
- - - ! '>='
185
+ - - '>='
212
186
  - !ruby/object:Gem::Version
213
187
  version: '0'
214
188
  type: :development
215
189
  prerelease: false
216
190
  version_requirements: !ruby/object:Gem::Requirement
217
- none: false
218
191
  requirements:
219
- - - ! '>='
192
+ - - '>='
220
193
  - !ruby/object:Gem::Version
221
194
  version: '0'
222
195
  - !ruby/object:Gem::Dependency
223
196
  name: sinatra
224
197
  requirement: !ruby/object:Gem::Requirement
225
- none: false
226
198
  requirements:
227
- - - ! '>='
199
+ - - '>='
228
200
  - !ruby/object:Gem::Version
229
201
  version: '0'
230
202
  type: :development
231
203
  prerelease: false
232
204
  version_requirements: !ruby/object:Gem::Requirement
233
- none: false
234
205
  requirements:
235
- - - ! '>='
206
+ - - '>='
236
207
  - !ruby/object:Gem::Version
237
208
  version: '0'
238
209
  - !ruby/object:Gem::Dependency
239
210
  name: thin
240
211
  requirement: !ruby/object:Gem::Requirement
241
- none: false
242
212
  requirements:
243
- - - ! '>='
213
+ - - '>='
244
214
  - !ruby/object:Gem::Version
245
215
  version: '0'
246
216
  type: :development
247
217
  prerelease: false
248
218
  version_requirements: !ruby/object:Gem::Requirement
249
- none: false
250
219
  requirements:
251
- - - ! '>='
220
+ - - '>='
252
221
  - !ruby/object:Gem::Version
253
222
  version: '0'
254
223
  - !ruby/object:Gem::Dependency
255
224
  name: xmpp4r
256
225
  requirement: !ruby/object:Gem::Requirement
257
- none: false
258
226
  requirements:
259
- - - ! '>='
227
+ - - '>='
260
228
  - !ruby/object:Gem::Version
261
229
  version: '0'
262
230
  type: :development
263
231
  prerelease: false
264
232
  version_requirements: !ruby/object:Gem::Requirement
265
- none: false
266
233
  requirements:
267
- - - ! '>='
234
+ - - '>='
268
235
  - !ruby/object:Gem::Version
269
236
  version: '0'
270
- description: Process monitoring tool. Alternative for God and Bluepill. With Bluepill
237
+ description: Process monitoring tool. An alternative to God and Bluepill. With Bluepill
271
238
  like config syntax. Requires MRI Ruby >= 1.9.2. Uses Celluloid and Celluloid::IO.
272
239
  email: kostya27@gmail.com
273
240
  executables:
@@ -288,6 +255,7 @@ files:
288
255
  - examples/processes/forking.rb
289
256
  - examples/processes/sample.rb
290
257
  - examples/processes/thin.ru
258
+ - examples/puma.eye
291
259
  - examples/rbenv.eye
292
260
  - examples/sidekiq.eye
293
261
  - examples/test.eye
@@ -479,28 +447,27 @@ files:
479
447
  homepage: http://github.com/kostya/eye
480
448
  licenses:
481
449
  - MIT
450
+ metadata: {}
482
451
  post_install_message:
483
452
  rdoc_options: []
484
453
  require_paths:
485
454
  - lib
486
455
  required_ruby_version: !ruby/object:Gem::Requirement
487
- none: false
488
456
  requirements:
489
- - - ! '>='
457
+ - - '>='
490
458
  - !ruby/object:Gem::Version
491
459
  version: 1.9.2
492
460
  required_rubygems_version: !ruby/object:Gem::Requirement
493
- none: false
494
461
  requirements:
495
- - - ! '>='
462
+ - - '>='
496
463
  - !ruby/object:Gem::Version
497
464
  version: 1.3.6
498
465
  requirements: []
499
466
  rubyforge_project:
500
- rubygems_version: 1.8.25
467
+ rubygems_version: 2.0.2
501
468
  signing_key:
502
- specification_version: 3
503
- summary: Process monitoring tool. Alternative for God and Bluepill. With Bluepill
469
+ specification_version: 4
470
+ summary: Process monitoring tool. An alternative to God and Bluepill. With Bluepill
504
471
  like config syntax. Requires MRI Ruby >= 1.9.2. Uses Celluloid and Celluloid::IO.
505
472
  test_files:
506
473
  - spec/checker/cpu_spec.rb