ace-eye 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
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