Class: Reacter::DeciderAgent

Inherits:
Agent
  • Object
show all
Defined in:
lib/reacter/agents/decider.rb

Defined Under Namespace

Classes: EmitAlert, MemoryPersist, RedisPersist

Constant Summary collapse

STATES =
[:okay, :warning, :critical]
COMPARISONS =
%w{not is above below}
DEFAULT_PERSISTENCE =
'memory'
DEFAULT_PERSISTENCE_OBJECT =
({
  :count           => 1,
  :last_state      => nil,
  :last_seen       => nil,
  :new_alert       => false,
  :has_ever_failed => false,
  :total_value     => nil
})

Instance Attribute Summary

Attributes inherited from Agent

#config, #type

Instance Method Summary collapse

Methods inherited from Agent

create

Constructor Details

#initializeDeciderAgent

Returns a new instance of DeciderAgent.



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/reacter/agents/decider.rb', line 82

def initialize()
  super

  @_state_names = {}
  STATES.each_index do |i|
    @_state_names[STATES[i]] = i
  end

  @_persistence = DeciderAgent.const_get(@config.get('options.persistence.type', DEFAULT_PERSISTENCE).capitalize+'Persist')
  @_persistence.setup(@config.get('options.persistence', {}))
end

Instance Method Details

#received(message) ⇒ Object



94
95
96
97
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/reacter/agents/decider.rb', line 94

def received(message)
# early exit conditions
  return false unless @config
  return false unless @config['sources']
  return false unless message.metric
  unless message.source
    return false unless @config['sources']['any']
  end

  s = message.source
  m = message.metric

# build effective configuration rule for this message
  general = (@config['sources']['any'][m] or {} rescue {})
  specific = (@config['sources'][s][m] or {} rescue {})
  rule = specific.deep_merge!(general)

# quit early for empty rules
  return false if rule.empty?

# quit early for invalid rules
  return false unless (rule['threshold'] and rule['actions'])

# passthrough mode
#   if in passthrough mode, all messages that are present in the configuration
#   will be passed regardless of state.  this is useful in conjunction with
#   the relay agent to offload the decision making to another reacter instance
  return message if (@config['options'] and @config['options']['passthrough'])

# default return value: false
  rv = false

# initialize persistence for this source/metric
  persist_init(s,m)

# get current state of this message according to the rule
  state, comparison = state_of(message, rule)

  begin
    # a non-okay alert has occurred, this metric can now be said to have failed
      unless state == :okay
        persist_set(s,m, :has_ever_failed, true)
      end

    # the state has changed, reset counter
      if persist_get(s,m, :last_state) != state
        persist_set(s,m, :new_alert, true)
        persist_set(s,m, :count, 1)
      end

      hits = ((rule['threshold'][state.to_s][hits] rescue rule['hits']) or rule['hits'] or 1).to_i
      persist = ((rule['threshold'][state.to_s]['persist'] === true) rescue false)

    # only raise every n alerts
      if persist_get(s,m, :count) >= hits
      # raise the alert if it's new or if we're persistently reminding of alerts
        if persist_get(s,m, :new_alert) or persist
        # only emit if this metric has ever failed
          if persist_get(s,m, :has_ever_failed)
            raise EmitAlert
          end
        end
      end


  rescue EmitAlert
    message[:state] = state
    message[:comparison] = comparison
    message[:check_value] = (rule['threshold'][state][comparison] rescue nil)
    message[:alerted_at] = Time.now.to_i

    rv = message

  # alert is emitted, it's not new anymore
    persist_set(s,m, :new_alert, false)

  ensure
    persist_set(s,m, :count, persist_get(s,m, :count) + 1)
    persist_set(s,m, :last_state, state)
    persist_set(s,m, :last_seen, Time.now.to_i)
  end

  return rv
end