Class: Eye::Checker

Inherits:
Object show all
Includes:
Dsl::Validation
Defined in:
lib/eye/checker.rb

Direct Known Subclasses

CustomCell, Defer, FileCTime, FileTouched, Measure, Nop

Defined Under Namespace

Classes: ChildrenCount, ChildrenMemory, Cpu, Cputime, Custom, CustomCell, CustomDefer, Defer, FileCTime, FileSize, FileTouched, Http, Measure, Memory, Nop, Runtime, Socket, SslSocket

Constant Summary collapse

TYPES =
{ memory: 'Memory', cpu: 'Cpu', http: 'Http',
ctime: 'FileCTime', fsize: 'FileSize', file_touched: 'FileTouched',
socket: 'Socket', nop: 'Nop', runtime: 'Runtime', cputime: 'Cputime',
children_count: 'ChildrenCount', children_memory: 'ChildrenMemory', ssl_socket: 'SslSocket' }

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Dsl::Validation

included

Constructor Details

#initialize(pid, options = {}, process = nil) ⇒ Checker

Returns a new instance of Checker.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/eye/checker.rb', line 63

def initialize(pid, options = {}, process = nil)
  @process = process
  @pid = pid
  @options = options.dup
  @type = options[:type]
  @full_name = @process.full_name if @process
  @initialized_at = Time.now

  debug { "create checker, with #{options}" }

  @value = nil
  @values = Eye::Utils::Tail.new(max_tries)
  @check_count = 0
end

Instance Attribute Details

#check_countObject

Returns the value of attribute check_count.



24
25
26
# File 'lib/eye/checker.rb', line 24

def check_count
  @check_count
end

#optionsObject

Returns the value of attribute options.



24
25
26
# File 'lib/eye/checker.rb', line 24

def options
  @options
end

#pidObject

Returns the value of attribute pid.



24
25
26
# File 'lib/eye/checker.rb', line 24

def pid
  @pid
end

#processObject

Returns the value of attribute process.



24
25
26
# File 'lib/eye/checker.rb', line 24

def process
  @process
end

#typeObject

Returns the value of attribute type.



24
25
26
# File 'lib/eye/checker.rb', line 24

def type
  @type
end

#valueObject

Returns the value of attribute value.



24
25
26
# File 'lib/eye/checker.rb', line 24

def value
  @value
end

#valuesObject

Returns the value of attribute values.



24
25
26
# File 'lib/eye/checker.rb', line 24

def values
  @values
end

Class Method Details

.create(pid, options = {}, process = nil) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/eye/checker.rb', line 51

def self.create(pid, options = {}, process = nil)
  get_class(options[:type]).new(pid, options, process)

rescue Object => ex
  log_ex(ex)
  nil
end

.get_class(type) ⇒ Object



42
43
44
45
46
47
48
49
# File 'lib/eye/checker.rb', line 42

def self.get_class(type)
  klass = eval("Eye::Checker::#{TYPES[type]}") rescue nil
  raise "Unknown checker #{type}" unless klass
  if deps = klass.requires
    Array(deps).each { |d| require d }
  end
  klass
end

.name_and_class(type) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/eye/checker.rb', line 32

def self.name_and_class(type)
  type = type.to_sym
  return { name: type, type: type } if TYPES[type]

  if type =~ %r[\A(.*?)_?[0-9]+\z]
    ctype = Regexp.last_match(1).to_sym
    return { name: type, type: ctype } if TYPES[ctype]
  end
end

.register(base) ⇒ Object



217
218
219
220
221
222
# File 'lib/eye/checker.rb', line 217

def self.register(base)
  name = base.to_s.gsub('Eye::Checker::', '')
  type = name.underscore.to_sym
  Eye::Checker::TYPES[type] = name
  Eye::Checker.const_set(name, base)
end

.requiresObject



224
225
# File 'lib/eye/checker.rb', line 224

def self.requires
end

.validate!(options) ⇒ Object



59
60
61
# File 'lib/eye/checker.rb', line 59

def self.validate!(options)
  get_class(options[:type]).validate(options)
end

Instance Method Details

#checkObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/eye/checker.rb', line 99

def check
  if initial_grace
    if Time.now - @initialized_at < initial_grace
      debug { 'skipped initial grace' }
      return true
    else
      @options[:initial_grace] = nil
    end
  end

  @value = get_value_safe
  @good_value = good?(value)
  @values << { value: @value, good: @good_value }

  result = true
  @check_count += 1

  if @values.size == max_tries
    bad_count = @values.count { |v| !v[:good] }
    result = false if bad_count >= min_tries
  end

  if skip_initial_fails
    if @good_value
      @options[:skip_initial_fails] = nil
    else
      result = true
    end
  end

  info { "#{last_human_values} => #{result ? 'OK' : 'Fail'}" }
  result

rescue Object => ex
  raise(ex) if ex.class == Celluloid::TaskTerminated
  log_ex(ex)
end

#check_nameObject



155
156
157
# File 'lib/eye/checker.rb', line 155

def check_name
  @check_name ||= @type.to_s
end

#defer(&block) ⇒ Object



205
206
207
# File 'lib/eye/checker.rb', line 205

def defer(&block)
  Celluloid::Future.new(&block).value
end

#fireObject



191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/eye/checker.rb', line 191

def fire
  actions = fires ? Array(fires) : [:restart]
  process.notify :warn, "Bounded #{check_name}: #{last_human_values} send to #{actions}"

  actions.each do |action|
    reason = "bounded #{check_name}"
    if action.is_a?(Proc)
      process.schedule command: :instance_exec, reason: reason, block: action
    else
      process.schedule command: action, reason: reason
    end
  end
end

#get_valueObject

Raises:

  • (NotImplementedError)


141
142
143
# File 'lib/eye/checker.rb', line 141

def get_value
  raise NotImplementedError
end

#get_value_safeObject



137
138
139
# File 'lib/eye/checker.rb', line 137

def get_value_safe
  get_value
end

#good?(value) ⇒ Boolean

true if check ok false if check bad

Returns:

  • (Boolean)


151
152
153
# File 'lib/eye/checker.rb', line 151

def good?(value)
  value
end

#human_value(value) ⇒ Object



145
146
147
# File 'lib/eye/checker.rb', line 145

def human_value(value)
  value.to_s
end

#inspectObject



78
79
80
# File 'lib/eye/checker.rb', line 78

def inspect
  "<#{self.class} @process='#{@full_name}' @options=#{@options} @pid=#{@pid}>"
end

#last_human_valuesObject



90
91
92
93
94
95
96
97
# File 'lib/eye/checker.rb', line 90

def last_human_values
  h_values = @values.map do |v|
    sign = v[:good] ? '' : '*'
    sign + human_value(v[:value]).to_s
  end

  '[' + h_values * ', ' + ']'
end

#logger_sub_tagObject



86
87
88
# File 'lib/eye/checker.rb', line 86

def logger_sub_tag
  @logger_sub_tag ||= "check:#{check_name}"
end

#logger_tagObject



82
83
84
# File 'lib/eye/checker.rb', line 82

def logger_tag
  @logger_tag ||= @process ? @process.logger.prefix : nil
end

#max_triesObject



159
160
161
162
163
164
165
166
167
168
169
# File 'lib/eye/checker.rb', line 159

def max_tries
  @max_tries ||= if times
    if times.is_a?(Array)
      times[-1].to_i
    else
      times.to_i
    end
  else
    1
  end
end

#min_triesObject



171
172
173
174
175
176
177
178
179
180
181
# File 'lib/eye/checker.rb', line 171

def min_tries
  @min_tries ||= if times
    if times.is_a?(Array)
      times[0].to_i
    else
      max_tries
    end
  else
    max_tries
  end
end

#previous_valueObject



183
184
185
# File 'lib/eye/checker.rb', line 183

def previous_value
  @values[-1][:value] if @values.present?
end

#run_in_process_context(p) ⇒ Object



187
188
189
# File 'lib/eye/checker.rb', line 187

def run_in_process_context(p)
  process.instance_exec(&p) if process.alive?
end