ace-eye 0.6.1

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 (114) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +38 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/CHANGES.md +77 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE +22 -0
  8. data/README.md +212 -0
  9. data/Rakefile +35 -0
  10. data/bin/eye +5 -0
  11. data/bin/loader_eye +72 -0
  12. data/bin/runner +16 -0
  13. data/examples/dependency.eye +17 -0
  14. data/examples/notify.eye +19 -0
  15. data/examples/plugin/README.md +15 -0
  16. data/examples/plugin/main.eye +15 -0
  17. data/examples/plugin/plugin.rb +63 -0
  18. data/examples/process_thin.rb +29 -0
  19. data/examples/processes/em.rb +57 -0
  20. data/examples/processes/forking.rb +20 -0
  21. data/examples/processes/sample.rb +144 -0
  22. data/examples/processes/thin.ru +12 -0
  23. data/examples/puma.eye +29 -0
  24. data/examples/rbenv.eye +11 -0
  25. data/examples/sidekiq.eye +23 -0
  26. data/examples/test.eye +87 -0
  27. data/examples/thin-farm.eye +30 -0
  28. data/examples/unicorn.eye +39 -0
  29. data/eye.gemspec +40 -0
  30. data/lib/eye.rb +28 -0
  31. data/lib/eye/application.rb +73 -0
  32. data/lib/eye/checker.rb +258 -0
  33. data/lib/eye/checker/children_count.rb +44 -0
  34. data/lib/eye/checker/children_memory.rb +12 -0
  35. data/lib/eye/checker/cpu.rb +17 -0
  36. data/lib/eye/checker/cputime.rb +13 -0
  37. data/lib/eye/checker/file_ctime.rb +24 -0
  38. data/lib/eye/checker/file_size.rb +34 -0
  39. data/lib/eye/checker/file_touched.rb +15 -0
  40. data/lib/eye/checker/http.rb +96 -0
  41. data/lib/eye/checker/memory.rb +17 -0
  42. data/lib/eye/checker/nop.rb +6 -0
  43. data/lib/eye/checker/runtime.rb +18 -0
  44. data/lib/eye/checker/socket.rb +159 -0
  45. data/lib/eye/child_process.rb +101 -0
  46. data/lib/eye/cli.rb +185 -0
  47. data/lib/eye/cli/commands.rb +78 -0
  48. data/lib/eye/cli/render.rb +130 -0
  49. data/lib/eye/cli/server.rb +93 -0
  50. data/lib/eye/client.rb +32 -0
  51. data/lib/eye/config.rb +91 -0
  52. data/lib/eye/control.rb +2 -0
  53. data/lib/eye/controller.rb +54 -0
  54. data/lib/eye/controller/commands.rb +88 -0
  55. data/lib/eye/controller/helpers.rb +101 -0
  56. data/lib/eye/controller/load.rb +224 -0
  57. data/lib/eye/controller/options.rb +18 -0
  58. data/lib/eye/controller/send_command.rb +177 -0
  59. data/lib/eye/controller/status.rb +72 -0
  60. data/lib/eye/dsl.rb +53 -0
  61. data/lib/eye/dsl/application_opts.rb +39 -0
  62. data/lib/eye/dsl/chain.rb +12 -0
  63. data/lib/eye/dsl/child_process_opts.rb +13 -0
  64. data/lib/eye/dsl/config_opts.rb +55 -0
  65. data/lib/eye/dsl/group_opts.rb +32 -0
  66. data/lib/eye/dsl/helpers.rb +20 -0
  67. data/lib/eye/dsl/main.rb +51 -0
  68. data/lib/eye/dsl/opts.rb +151 -0
  69. data/lib/eye/dsl/process_opts.rb +36 -0
  70. data/lib/eye/dsl/pure_opts.rb +121 -0
  71. data/lib/eye/dsl/validation.rb +88 -0
  72. data/lib/eye/group.rb +140 -0
  73. data/lib/eye/group/chain.rb +81 -0
  74. data/lib/eye/loader.rb +10 -0
  75. data/lib/eye/local.rb +100 -0
  76. data/lib/eye/logger.rb +104 -0
  77. data/lib/eye/notify.rb +118 -0
  78. data/lib/eye/notify/jabber.rb +30 -0
  79. data/lib/eye/notify/mail.rb +48 -0
  80. data/lib/eye/process.rb +85 -0
  81. data/lib/eye/process/children.rb +60 -0
  82. data/lib/eye/process/commands.rb +280 -0
  83. data/lib/eye/process/config.rb +81 -0
  84. data/lib/eye/process/controller.rb +73 -0
  85. data/lib/eye/process/data.rb +78 -0
  86. data/lib/eye/process/monitor.rb +108 -0
  87. data/lib/eye/process/notify.rb +32 -0
  88. data/lib/eye/process/scheduler.rb +82 -0
  89. data/lib/eye/process/states.rb +86 -0
  90. data/lib/eye/process/states_history.rb +66 -0
  91. data/lib/eye/process/system.rb +97 -0
  92. data/lib/eye/process/trigger.rb +34 -0
  93. data/lib/eye/process/validate.rb +33 -0
  94. data/lib/eye/process/watchers.rb +66 -0
  95. data/lib/eye/reason.rb +20 -0
  96. data/lib/eye/server.rb +60 -0
  97. data/lib/eye/sigar.rb +5 -0
  98. data/lib/eye/system.rb +139 -0
  99. data/lib/eye/system_resources.rb +99 -0
  100. data/lib/eye/trigger.rb +136 -0
  101. data/lib/eye/trigger/check_dependency.rb +30 -0
  102. data/lib/eye/trigger/flapping.rb +41 -0
  103. data/lib/eye/trigger/stop_children.rb +17 -0
  104. data/lib/eye/trigger/transition.rb +15 -0
  105. data/lib/eye/trigger/wait_dependency.rb +49 -0
  106. data/lib/eye/utils.rb +45 -0
  107. data/lib/eye/utils/alive_array.rb +57 -0
  108. data/lib/eye/utils/celluloid_chain.rb +71 -0
  109. data/lib/eye/utils/celluloid_klass.rb +5 -0
  110. data/lib/eye/utils/leak_19.rb +10 -0
  111. data/lib/eye/utils/mini_active_support.rb +111 -0
  112. data/lib/eye/utils/pmap.rb +7 -0
  113. data/lib/eye/utils/tail.rb +20 -0
  114. metadata +398 -0
@@ -0,0 +1,11 @@
1
+ Eye.application "rbenv_example" do
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 ]))
4
+
5
+ process "some_process" do
6
+ pid_file "some.pid"
7
+ start_command "ruby some.rb"
8
+ daemonize true
9
+ stdall "some.log"
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ # Example: how to run sidekiq daemon
2
+
3
+ def sidekiq_process(proxy, name)
4
+ rails_env = proxy.env['RAILS_ENV']
5
+
6
+ proxy.process(name) do
7
+ start_command "ruby ./bin/sidekiq -e #{rails_env} -C ./config/sidekiq.#{rails_env}.yml"
8
+ pid_file "tmp/pids/#{name}.pid"
9
+ stdall "log/#{name}.log"
10
+ daemonize true
11
+ stop_signals [:QUIT, 5.seconds, :TERM, 5.seconds, :KILL]
12
+
13
+ check :cpu, :every => 30, :below => 100, :times => 5
14
+ check :memory, :every => 30, :below => 300.megabytes, :times => 5
15
+ end
16
+ end
17
+
18
+ Eye.application :sidekiq_test do
19
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
20
+ env "RAILS_ENV" => 'production'
21
+
22
+ sidekiq_process self, :sidekiq
23
+ end
@@ -0,0 +1,87 @@
1
+ # load submodules, here just for example
2
+ Eye.load('./eye/*.rb')
3
+
4
+ # Eye self-configuration section
5
+ Eye.config do
6
+ logger '/tmp/eye.log'
7
+ end
8
+
9
+ # Adding application
10
+ Eye.application 'test' do
11
+ # All options inherits down to the config leafs.
12
+ # except `env`, which merging down
13
+
14
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
15
+ stdall 'trash.log' # stdout,err logs for processes by default
16
+ env 'APP_ENV' => 'production' # global env for each processes
17
+ trigger :flapping, times: 10, within: 1.minute, retry_in: 10.minutes
18
+ check :cpu, every: 10.seconds, below: 100, times: 3 # global check for all processes
19
+
20
+ group 'samples' do
21
+ chain grace: 5.seconds # chained start-restart with 5s interval, one by one.
22
+
23
+ # eye daemonized process
24
+ process :sample1 do
25
+ pid_file '1.pid' # pid_path will be expanded with the working_dir
26
+ start_command 'ruby ./sample.rb'
27
+
28
+ # when no stop_command or stop_signals, default stop is [:TERM, 0.5, :KILL]
29
+ # default `restart` command is `stop; start`
30
+
31
+ daemonize true
32
+ stdall 'sample1.log'
33
+
34
+ # ensure the CPU is below 30% at least 3 out of the last 5 times checked
35
+ check :cpu, below: 30, times: [3, 5]
36
+ end
37
+
38
+ # self daemonized process
39
+ process :sample2 do
40
+ pid_file '2.pid'
41
+ start_command 'ruby ./sample.rb -d --pid 2.pid --log sample2.log'
42
+ stop_command 'kill -9 {PID}'
43
+
44
+ # ensure the memory is below 300Mb the last 3 times checked
45
+ check :memory, every: 20.seconds, below: 300.megabytes, times: 3
46
+ end
47
+ end
48
+
49
+ # daemon with 3 children
50
+ process :forking do
51
+ pid_file 'forking.pid'
52
+ start_command 'ruby ./forking.rb start'
53
+ stop_command 'ruby forking.rb stop'
54
+ stdall 'forking.log'
55
+
56
+ start_timeout 10.seconds
57
+ stop_timeout 5.seconds
58
+
59
+ monitor_children do
60
+ restart_command 'kill -2 {PID}' # for this child process
61
+ check :memory, below: 300.megabytes, times: 3
62
+ end
63
+ end
64
+
65
+ # eventmachine process, daemonized with eye
66
+ process :event_machine do |p|
67
+ pid_file 'em.pid'
68
+ start_command 'ruby em.rb'
69
+ stdout 'em.log'
70
+ daemonize true
71
+ stop_signals [:QUIT, 2.seconds, :KILL]
72
+
73
+ check :socket, addr: 'tcp://127.0.0.1:33221', every: 10.seconds, times: 2,
74
+ timeout: 1.second, send_data: 'ping', expect_data: /pong/
75
+ end
76
+
77
+ # thin process, self daemonized
78
+ process :thin do
79
+ pid_file 'thin.pid'
80
+ start_command 'bundle exec thin start -R thin.ru -p 33233 -d -l thin.log -P thin.pid'
81
+ stop_signals [:QUIT, 2.seconds, :TERM, 1.seconds, :KILL]
82
+
83
+ check :http, url: 'http://127.0.0.1:33233/hello', pattern: /World/,
84
+ every: 5.seconds, times: [2, 3], timeout: 1.second
85
+ end
86
+
87
+ end
@@ -0,0 +1,30 @@
1
+ RUBY = 'ruby'
2
+ BUNDLE = 'bundle'
3
+
4
+ Eye.load("process_thin.rb")
5
+
6
+ Eye.config do
7
+ logger "/tmp/eye.log"
8
+ end
9
+
10
+ Eye.app 'thin-farm' do
11
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
12
+ env "RAILS_ENV" => "production"
13
+
14
+ stop_on_delete true # this option means, when we change pids and load config,
15
+ # deleted processes will be stops
16
+
17
+ trigger :flapping, :times => 10, :within => 1.minute
18
+ check :memory, :below => 60.megabytes, :every => 30.seconds, :times => 5
19
+ start_timeout 30.seconds
20
+
21
+ group :web do
22
+ chain :action => :restart, :grace => 5.seconds
23
+ chain :action => :start, :grace => 0.2.seconds
24
+
25
+ (5555..5560).each do |port|
26
+ thin self, port
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,39 @@
1
+ # Example: now to run unicorn, and monitor its child processes
2
+
3
+ RUBY = '/usr/local/ruby/1.9.3/bin/ruby' # ruby on the server
4
+ RAILS_ENV = 'production'
5
+
6
+ Eye.application "rails_unicorn" do
7
+ env "RAILS_ENV" => RAILS_ENV
8
+
9
+ # unicorn requires to be `ruby` in path (for soft restart)
10
+ env "PATH" => "#{File.dirname(RUBY)}:#{ENV['PATH']}"
11
+
12
+ working_dir File.expand_path(File.join(File.dirname(__FILE__), %w[ processes ]))
13
+
14
+ process("unicorn") do
15
+ pid_file "tmp/pids/unicorn.pid"
16
+ start_command "#{RUBY} ./bin/unicorn -Dc ./config/unicorn.rb -E #{RAILS_ENV}"
17
+ stdall "log/unicorn.log"
18
+
19
+ # stop signals:
20
+ # http://unicorn.bogomips.org/SIGNALS.html
21
+ stop_signals [:TERM, 10.seconds]
22
+
23
+ # soft restart
24
+ restart_command "kill -USR2 {PID}"
25
+
26
+ check :cpu, :every => 30, :below => 80, :times => 3
27
+ check :memory, :every => 30, :below => 150.megabytes, :times => [3,5]
28
+
29
+ start_timeout 100.seconds
30
+ restart_grace 30.seconds
31
+
32
+ monitor_children do
33
+ stop_command "kill -QUIT {PID}"
34
+ check :cpu, :every => 30, :below => 80, :times => 3
35
+ check :memory, :every => 30, :below => 150.megabytes, :times => [3,5]
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path('../lib/eye', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = "Konstantin Makarchev"
5
+ gem.email = "eye-rb@googlegroups.com"
6
+
7
+ gem.description = gem.summary = \
8
+ %q{FORK FOR TESTING. Process monitoring tool. Inspired from Bluepill and God. Requires Ruby(MRI) >= 1.9.3-p194. Uses Celluloid and Celluloid::IO.}
9
+ gem.homepage = "http://github.com/kostya/eye"
10
+
11
+ gem.files = `git ls-files`.split($\).reject{|n| n =~ %r[png|gif\z]}.reject{|n| n =~ %r[^(test|spec|features)/]}
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ #gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "ace-eye"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Eye::VERSION
17
+ gem.license = "MIT"
18
+
19
+ gem.required_ruby_version = '>= 1.9.2'
20
+ gem.required_rubygems_version = '>= 1.3.6'
21
+
22
+ gem.add_dependency 'celluloid', '~> 0.15.0'
23
+ gem.add_dependency 'celluloid-io', '~> 0.15.0'
24
+ gem.add_dependency 'state_machine'
25
+ gem.add_dependency 'thor'
26
+ gem.add_dependency 'sigar', '~> 0.7.2'
27
+
28
+ gem.add_development_dependency 'rake'
29
+ gem.add_development_dependency 'rspec', '< 2.14'
30
+ gem.add_development_dependency 'rr'
31
+ gem.add_development_dependency 'ruby-graphviz'
32
+ gem.add_development_dependency 'forking'
33
+ gem.add_development_dependency 'fakeweb'
34
+ gem.add_development_dependency 'eventmachine', ">= 1.0.3"
35
+ gem.add_development_dependency 'sinatra'
36
+ gem.add_development_dependency 'thin'
37
+ gem.add_development_dependency 'xmpp4r'
38
+ gem.add_development_dependency 'coveralls'
39
+ gem.add_development_dependency 'simplecov', '>= 0.8.1'
40
+ end
@@ -0,0 +1,28 @@
1
+ module Eye
2
+ VERSION = "0.6.1"
3
+ ABOUT = "Eye v#{VERSION} (c) 2012-2014 @kostya"
4
+ PROCLINE = "eye monitoring v#{VERSION}"
5
+
6
+ autoload :Process, 'eye/process'
7
+ autoload :ChildProcess, 'eye/child_process'
8
+ autoload :Server, 'eye/server'
9
+ autoload :Logger, 'eye/logger'
10
+ autoload :System, 'eye/system'
11
+ autoload :SystemResources,'eye/system_resources'
12
+ autoload :Checker, 'eye/checker'
13
+ autoload :Trigger, 'eye/trigger'
14
+ autoload :Group, 'eye/group'
15
+ autoload :Dsl, 'eye/dsl'
16
+ autoload :Application, 'eye/application'
17
+ autoload :Local, 'eye/local'
18
+ autoload :Client, 'eye/client'
19
+ autoload :Utils, 'eye/utils'
20
+ autoload :Notify, 'eye/notify'
21
+ autoload :Config, 'eye/config'
22
+ autoload :Reason, 'eye/reason'
23
+ autoload :Sigar, 'eye/sigar'
24
+
25
+ autoload :Controller, 'eye/controller'
26
+ autoload :Control, 'eye/control'
27
+ autoload :Cli, 'eye/cli'
28
+ end
@@ -0,0 +1,73 @@
1
+ class Eye::Application
2
+
3
+ attr_reader :groups, :name
4
+
5
+ def initialize(name, config = {})
6
+ @groups = Eye::Utils::AliveArray.new
7
+ @name = name
8
+ @config = config
9
+ debug 'created'
10
+ end
11
+
12
+ def logger_tag
13
+ full_name
14
+ end
15
+
16
+ def full_name
17
+ @name
18
+ end
19
+
20
+ def add_group(group)
21
+ @groups << group
22
+ end
23
+
24
+ # sort processes in name order
25
+ def resort_groups
26
+ @groups = @groups.sort { |a, b| a.hidden ? 1 : (b.hidden ? -1 : (a.name <=> b.name)) }
27
+ end
28
+
29
+ def status_data(debug = false)
30
+ h = { name: @name, type: :application, subtree: @groups.map{|gr| gr.status_data(debug) }}
31
+ h.merge!(debug: debug_data) if debug
32
+ h
33
+ end
34
+
35
+ def status_data_short
36
+ h = Hash.new
37
+ @groups.each do |c|
38
+ c.processes.each do |p|
39
+ h[p.state] ||= 0
40
+ h[p.state] += 1
41
+ end
42
+ end
43
+ { name: @name, type: :application, states: h}
44
+ end
45
+
46
+ def debug_data
47
+ end
48
+
49
+ def send_command(command, *args)
50
+ info "send_command #{command}"
51
+
52
+ @groups.each do |group|
53
+ group.send_command(command, *args)
54
+ end
55
+ end
56
+
57
+ def alive?
58
+ true # emulate celluloid actor method
59
+ end
60
+
61
+ def sub_object?(obj)
62
+ res = @groups.include?(obj)
63
+ res = @groups.any?{|gr| gr.sub_object?(obj)} if !res
64
+ res
65
+ end
66
+
67
+ def processes
68
+ out = []
69
+ @groups.each{|gr| out += gr.processes.to_a }
70
+ Eye::Utils::AliveArray.new(out)
71
+ end
72
+
73
+ end
@@ -0,0 +1,258 @@
1
+ class Eye::Checker
2
+ include Eye::Dsl::Validation
3
+
4
+ autoload :Memory, 'eye/checker/memory'
5
+ autoload :Cpu, 'eye/checker/cpu'
6
+ autoload :Http, 'eye/checker/http'
7
+ autoload :FileCTime, 'eye/checker/file_ctime'
8
+ autoload :FileSize, 'eye/checker/file_size'
9
+ autoload :FileTouched,'eye/checker/file_touched'
10
+ autoload :Socket, 'eye/checker/socket'
11
+ autoload :Nop, 'eye/checker/nop'
12
+ autoload :Runtime, 'eye/checker/runtime'
13
+ autoload :Cputime, 'eye/checker/cputime'
14
+ autoload :ChildrenCount, 'eye/checker/children_count'
15
+ autoload :ChildrenMemory,'eye/checker/children_memory'
16
+
17
+ TYPES = {:memory => 'Memory', :cpu => 'Cpu', :http => 'Http',
18
+ :ctime => 'FileCTime', :fsize => 'FileSize', :file_touched => 'FileTouched',
19
+ :socket => 'Socket', :nop => 'Nop', :runtime => 'Runtime', :cputime => 'Cputime',
20
+ :children_count => "ChildrenCount", :children_memory => "ChildrenMemory" }
21
+
22
+ attr_accessor :value, :values, :options, :pid, :type, :check_count, :process
23
+
24
+ param :every, [Fixnum, Float], false, 5
25
+ param :times, [Fixnum, Array], nil, 1
26
+ param :fires, [Symbol, Array], nil, nil, [:stop, :restart, :unmonitor, :start, :delete, :nothing, :notify]
27
+ param :initial_grace, [Fixnum, Float]
28
+ param :skip_initial_fails, [TrueClass, FalseClass]
29
+
30
+ def self.name_and_class(type)
31
+ type = type.to_sym
32
+ return {:name => type, :type => type} if TYPES[type]
33
+
34
+ if type =~ /\A(.*?)_?[0-9]+\z/
35
+ ctype = $1.to_sym
36
+ return {:name => type, :type => ctype} if TYPES[ctype]
37
+ end
38
+ end
39
+
40
+ def self.get_class(type)
41
+ klass = eval("Eye::Checker::#{TYPES[type]}") rescue nil
42
+ raise "Unknown checker #{type}" unless klass
43
+ if deps = klass.requires
44
+ Array(deps).each { |d| require d }
45
+ end
46
+ klass
47
+ end
48
+
49
+ def self.create(pid, options = {}, process = nil)
50
+ get_class(options[:type]).new(pid, options, process)
51
+
52
+ rescue Exception, Timeout::Error => ex
53
+ log_ex(ex)
54
+ nil
55
+ end
56
+
57
+ def self.validate!(options)
58
+ get_class(options[:type]).validate(options)
59
+ end
60
+
61
+ def initialize(pid, options = {}, process = nil)
62
+ @process = process
63
+ @pid = pid
64
+ @options = options.dup
65
+ @type = options[:type]
66
+ @full_name = @process.full_name if @process
67
+ @initialized_at = Time.now
68
+
69
+ debug "create checker, with #{options}"
70
+
71
+ @value = nil
72
+ @values = Eye::Utils::Tail.new(max_tries)
73
+ @check_count = 0
74
+ end
75
+
76
+ def inspect
77
+ "<#{self.class} @process='#{@full_name}' @options=#{@options} @pid=#{@pid}>"
78
+ end
79
+
80
+ def logger_tag
81
+ @process.logger.prefix
82
+ end
83
+
84
+ def logger_sub_tag
85
+ "check:#{check_name}"
86
+ end
87
+
88
+ def last_human_values
89
+ h_values = @values.map do |v|
90
+ sign = v[:good] ? '' : '*'
91
+ sign + human_value(v[:value]).to_s
92
+ end
93
+
94
+ '[' + h_values * ', ' + ']'
95
+ end
96
+
97
+ def check
98
+ if initial_grace && (Time.now - @initialized_at < initial_grace)
99
+ debug 'skipped initial grace'
100
+ return true
101
+ else
102
+ @options[:initial_grace] = nil
103
+ end
104
+
105
+ @value = get_value_safe
106
+ @good_value = good?(value)
107
+ @values << {:value => @value, :good => @good_value}
108
+
109
+ result = true
110
+ @check_count += 1
111
+
112
+ if @values.size == max_tries
113
+ bad_count = @values.count{|v| !v[:good] }
114
+ result = false if bad_count >= min_tries
115
+ end
116
+
117
+ if skip_initial_fails
118
+ if @good_value
119
+ @options[:skip_initial_fails] = nil
120
+ else
121
+ result = true
122
+ end
123
+ end
124
+
125
+ info "#{last_human_values} => #{result ? 'OK' : 'Fail'}"
126
+ result
127
+
128
+ rescue Exception, Timeout::Error => ex
129
+ log_ex(ex)
130
+ end
131
+
132
+ def get_value_safe
133
+ get_value
134
+ end
135
+
136
+ def get_value
137
+ raise NotImplementedError
138
+ end
139
+
140
+ def human_value(value)
141
+ value.to_s
142
+ end
143
+
144
+ # true if check ok
145
+ # false if check bad
146
+ def good?(value)
147
+ value
148
+ end
149
+
150
+ def check_name
151
+ @check_name ||= @type.to_s
152
+ end
153
+
154
+ def max_tries
155
+ @max_tries ||= if times
156
+ if times.is_a?(Array)
157
+ times[-1].to_i
158
+ else
159
+ times.to_i
160
+ end
161
+ else
162
+ 1
163
+ end
164
+ end
165
+
166
+ def min_tries
167
+ @min_tries ||= if times
168
+ if times.is_a?(Array)
169
+ times[0].to_i
170
+ else
171
+ max_tries
172
+ end
173
+ else
174
+ max_tries
175
+ end
176
+ end
177
+
178
+ def previous_value
179
+ @values[-1][:value] if @values.present?
180
+ end
181
+
182
+ def run_in_process_context(p)
183
+ process.instance_exec(&p) if process.alive?
184
+ end
185
+
186
+ def fire
187
+ actions = fires ? Array(fires) : [:restart]
188
+ process.notify :warn, "Bounded #{check_name}: #{last_human_values} send to #{actions}"
189
+
190
+ actions.each do |action|
191
+ process.schedule action, Eye::Reason.new("bounded #{check_name}")
192
+ end
193
+ end
194
+
195
+ def defer(&block)
196
+ Celluloid::Future.new(&block).value
197
+ end
198
+
199
+ class Defer < Eye::Checker
200
+ def get_value_safe
201
+ Celluloid::Future.new{ get_value }.value
202
+ end
203
+ end
204
+
205
+ def self.register(base)
206
+ name = base.to_s.gsub('Eye::Checker::', '')
207
+ type = name.underscore.to_sym
208
+ Eye::Checker::TYPES[type] = name
209
+ Eye::Checker.const_set(name, base)
210
+ end
211
+
212
+ def self.requires
213
+ end
214
+
215
+ class CustomCell < Eye::Checker
216
+ def self.inherited(base)
217
+ super
218
+ register(base)
219
+ end
220
+ end
221
+
222
+ class Custom < Defer
223
+ def self.inherited(base)
224
+ super
225
+ register(base)
226
+ end
227
+ end
228
+
229
+ class CustomDefer < Defer
230
+ def self.inherited(base)
231
+ super
232
+ register(base)
233
+ end
234
+ end
235
+
236
+ class Measure < Eye::Checker
237
+ param :below, [Fixnum, Float]
238
+ param :above, [Fixnum, Float]
239
+
240
+ def good?(value)
241
+ return false if below && (value > below)
242
+ return false if above && (value < above)
243
+ true
244
+ end
245
+
246
+ def measure_str
247
+ if below && above
248
+ ">#{human_value(above)}<#{human_value(below)}"
249
+ elsif below
250
+ "<#{human_value(below)}"
251
+ elsif above
252
+ ">#{human_value(above)}"
253
+ else
254
+ '-'
255
+ end
256
+ end
257
+ end
258
+ end