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.


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

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
# 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


215
216
217
218
219
220
# File 'lib/eye/checker.rb', line 215

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


222
# File 'lib/eye/checker.rb', line 222

def self.requires; end

.validate!(options) ⇒ Object


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

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

Instance Method Details

#checkObject


98
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
# File 'lib/eye/checker.rb', line 98

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


153
154
155
# File 'lib/eye/checker.rb', line 153

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

#defer(&block) ⇒ Object


203
204
205
# File 'lib/eye/checker.rb', line 203

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

#fireObject


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

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)

139
140
141
# File 'lib/eye/checker.rb', line 139

def get_value
  raise NotImplementedError
end

#get_value_safeObject


135
136
137
# File 'lib/eye/checker.rb', line 135

def get_value_safe
  get_value
end

#good?(value) ⇒ Boolean

true if check ok false if check bad

Returns:

  • (Boolean)

149
150
151
# File 'lib/eye/checker.rb', line 149

def good?(value)
  value
end

#human_value(value) ⇒ Object


143
144
145
# File 'lib/eye/checker.rb', line 143

def human_value(value)
  value.to_s
end

#inspectObject


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

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

#last_human_valuesObject


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

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


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

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

#logger_tagObject


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

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

#max_triesObject


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

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


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

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


181
182
183
# File 'lib/eye/checker.rb', line 181

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

#run_in_process_context(p) ⇒ Object


185
186
187
# File 'lib/eye/checker.rb', line 185

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