Class: Sensu::Handler

Inherits:
Object
  • Object
show all
Includes:
Mixlib::CLI, Plugin::Utils
Defined in:
lib/sensu-handler.rb

Constant Summary collapse

@@autorun =

This works just like Plugin::CLI’s autorun.

self

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Plugin::Utils

#config_files, #deep_merge, #load_config, #net_http_req_class, #read_event, #settings

Constructor Details

#initialize(argv = ARGV) ⇒ Handler

Returns a new instance of Handler.



16
17
18
19
# File 'lib/sensu-handler.rb', line 16

def initialize(argv = ARGV)
  super()
  self.argv = parse_options(argv)
end

Instance Attribute Details

#argvObject

Returns the value of attribute argv.



14
15
16
# File 'lib/sensu-handler.rb', line 14

def argv
  @argv
end

Class Method Details

.disable_autorunObject



74
75
76
# File 'lib/sensu-handler.rb', line 74

def self.disable_autorun
  @@autorun = false
end

.method_added(name) ⇒ Object



67
68
69
70
71
# File 'lib/sensu-handler.rb', line 67

def method_added(name)
  if name == :handle
    @@autorun = self
  end
end

Instance Method Details

#api_request(method, path) {|req| ... } ⇒ Object

Yields:

  • (req)


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/sensu-handler.rb', line 132

def api_request(method, path, &blk)
  if api_settings.nil?
    raise "api.json settings not found."
  end
  domain = api_settings['host'].start_with?('http') ? api_settings['host'] : 'http://' + api_settings['host']
  uri = URI("#{domain}:#{api_settings['port']}#{path}")
  req = net_http_req_class(method).new(uri.path)
  if api_settings['user'] && api_settings['password']
    req.basic_auth(api_settings['user'], api_settings['password'])
  end
  yield(req) if block_given?
  res = Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') do |http|
    http.request(req)
  end
  res
end

#api_settingsHash

Return a hash of API settings derived first from ENV if set, then Sensu config ‘api` scope if configured, and finally falling back to to ipv4 localhost address on default API port.

Returns:

  • (Hash)


113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/sensu-handler.rb', line 113

def api_settings
  return @api_settings if @api_settings
  case
  when ENV['SENSU_API_URL']
    uri = URI(ENV['SENSU_API_URL'])
    @api_settings = {
      'host' => uri.host,
      'port' => uri.port,
      'user' => uri.user,
      'password' => uri.password
    }
  else
    @api_settings = settings['api'] || {}
    @api_settings['host'] ||= '127.0.0.1'
    @api_settings['port'] ||= 4567
  end
  @api_settings
end

#bail(msg) ⇒ Object



101
102
103
104
105
106
# File 'lib/sensu-handler.rb', line 101

def bail(msg)
  client_name = @event['client']['name'] || 'error:no-client-name'
  check_name = @event['check']['name'] || 'error:no-check-name'
  puts "#{msg}: #{client_name}/#{check_name}"
  exit 0
end

#deprecated_filtering_enabled?TrueClass, FalseClass

Evaluates whether the event should be processed by any of the filter methods in this library. Defaults to true, i.e. deprecated filters are run by default.

Returns:

  • (TrueClass, FalseClass)


50
51
52
# File 'lib/sensu-handler.rb', line 50

def deprecated_filtering_enabled?
  @event['check'].fetch('enable_deprecated_filtering', false).to_s == "true"
end

#deprecated_occurrence_filtering_enabled?TrueClass, FalseClass

Evaluates whether the event should be processed by the filter_repeated method. Defaults to true, i.e. filter_repeated will filter events by default.

Returns:

  • (TrueClass, FalseClass)


59
60
61
# File 'lib/sensu-handler.rb', line 59

def deprecated_occurrence_filtering_enabled?
  @event['check'].fetch('enable_deprecated_occurrence_filtering', false).to_s == "true"
end

#event_exists?(client, check) ⇒ Boolean

Returns:

  • (Boolean)


205
206
207
# File 'lib/sensu-handler.rb', line 205

def event_exists?(client, check)
  api_request(:GET, '/events/' + client + '/' + check).code == '200'
end

#event_summary(trim_at = 100) ⇒ Object

Helpers and filters.



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/sensu-handler.rb', line 89

def event_summary(trim_at=100)
  summary = @event['check']['notification'] || @event['check']['description']
  if summary.nil?
    source = @event['check']['source'] || @event['client']['name']
    event_context = [source, @event['check']['name']].join('/')
    output = @event['check']['output'].chomp
    output = output.length > trim_at ? output[0..trim_at] + '...' : output
    summary = [event_context, output].join(' : ')
  end
  summary
end

#filterObject

Filters exit the proccess if the event should not be handled.

Filtering events is deprecated and will be removed in a future release.



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/sensu-handler.rb', line 32

def filter
  if deprecated_filtering_enabled?
    puts 'warning: event filtering in sensu-plugin is deprecated, see http://bit.ly/sensu-plugin'
    filter_disabled
    filter_silenced
    filter_dependencies
    if deprecated_occurrence_filtering_enabled?
      puts 'warning: occurrence filtering in sensu-plugin is deprecated, see http://bit.ly/sensu-plugin'
      filter_repeated
    end
  end
end

#filter_dependenciesObject



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/sensu-handler.rb', line 209

def filter_dependencies
  if @event['check'].has_key?('dependencies')
    if @event['check']['dependencies'].is_a?(Array)
      @event['check']['dependencies'].each do |dependency|
        begin
          next if dependency.to_s.empty?
          Timeout.timeout(2) do
            check, client = dependency.split('/').reverse
            if event_exists?(client || @event['client']['name'], check)
              bail 'check dependency event exists'
            end
          end
        rescue Errno::ECONNREFUSED
          puts 'connection refused attempting to query the sensu api for an event'
        rescue Timeout::Error
          puts 'timed out while attempting to query the sensu api for an event'
        end
      end
    end
  end
end

#filter_disabledObject



149
150
151
152
153
# File 'lib/sensu-handler.rb', line 149

def filter_disabled
  if @event['check']['alert'] == false
    bail 'alert disabled'
  end
end

#filter_repeatedObject



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/sensu-handler.rb', line 155

def filter_repeated
  defaults = {
    'occurrences' => 1,
    'interval' => 30,
    'refresh' => 1800
  }

  if settings['sensu_plugin'].is_a?(Hash)
    defaults.merge!(settings['sensu_plugin'])
  end

  occurrences = (@event['check']['occurrences'] || defaults['occurrences']).to_i
  interval = (@event['check']['interval'] || defaults['interval']).to_i
  refresh = (@event['check']['refresh'] || defaults['refresh']).to_i
  if @event['occurrences'] < occurrences
    bail 'not enough occurrences'
  end
  if @event['occurrences'] > occurrences && @event['action'] == 'create'
    number = refresh.fdiv(interval).to_i
    unless number == 0 || (@event['occurrences'] - occurrences) % number == 0
      bail 'only handling every ' + number.to_s + ' occurrences'
    end
  end
end

#filter_silencedObject



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/sensu-handler.rb', line 184

def filter_silenced
  stashes = [
    ['client', '/silence/' + @event['client']['name']],
    ['check', '/silence/' + @event['client']['name'] + '/' + @event['check']['name']],
    ['check', '/silence/all/' + @event['check']['name']]
  ]
  stashes.each do |(scope, path)|
    begin
      Timeout.timeout(5) do
        if stash_exists?(path)
          bail scope + ' alerts silenced'
        end
      end
    rescue Errno::ECONNREFUSED
      puts 'connection refused attempting to query the sensu api for a stash'
    rescue Timeout::Error
      puts 'timed out while attempting to query the sensu api for a stash'
    end
  end
end

#handleObject

Implementing classes should override this.



23
24
25
# File 'lib/sensu-handler.rb', line 23

def handle
  puts 'ignoring event -- no handler defined'
end

#stash_exists?(path) ⇒ Boolean

Returns:

  • (Boolean)


180
181
182
# File 'lib/sensu-handler.rb', line 180

def stash_exists?(path)
  api_request(:GET, '/stash' + path).code == '200'
end