sensu 0.9.9.beta → 0.9.9.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +7 -0
- data/lib/sensu/api.rb +49 -10
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/server.rb +62 -13
- data/lib/sensu/settings.rb +101 -28
- metadata +4 -3
data/CHANGELOG.md
CHANGED
@@ -8,14 +8,21 @@ via the API (/info).
|
|
8
8
|
Aggregate results available via the API when using a parameter
|
9
9
|
(?results=true).
|
10
10
|
|
11
|
+
Event filters; filtering events for handlers, using event attribute
|
12
|
+
matching.
|
13
|
+
|
11
14
|
### Other
|
12
15
|
|
13
16
|
Server is now using basic AMQP QoS (prefetch), just enough back pressure.
|
14
17
|
|
18
|
+
Improved check execution scheduling.
|
19
|
+
|
15
20
|
Fixed server execute command method error handling.
|
16
21
|
|
17
22
|
Events with a resolve action bypass handler severity filtering.
|
18
23
|
|
24
|
+
Check flap detection configuration validation.
|
25
|
+
|
19
26
|
## 0.9.8 - 2012-11-15
|
20
27
|
|
21
28
|
### Features
|
data/lib/sensu/api.rb
CHANGED
@@ -443,17 +443,25 @@ module Sensu
|
|
443
443
|
response = Array.new
|
444
444
|
$redis.smembers('aggregates').callback do |checks|
|
445
445
|
unless checks.empty?
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
446
|
+
limit = 10
|
447
|
+
if params[:limit]
|
448
|
+
limit = params[:limit] =~ /^[0-9]+$/ ? params[:limit].to_i : nil
|
449
|
+
end
|
450
|
+
unless limit.nil?
|
451
|
+
checks.each_with_index do |check_name, index|
|
452
|
+
$redis.smembers('aggregates:' + check_name).callback do |aggregates|
|
453
|
+
collection = {
|
454
|
+
:check => check_name,
|
455
|
+
:issued => aggregates.sort.reverse.take(limit)
|
456
|
+
}
|
457
|
+
response.push(collection)
|
458
|
+
if index == checks.size - 1
|
459
|
+
body response.to_json
|
460
|
+
end
|
455
461
|
end
|
456
462
|
end
|
463
|
+
else
|
464
|
+
bad_request!
|
457
465
|
end
|
458
466
|
else
|
459
467
|
body response.to_json
|
@@ -463,7 +471,38 @@ module Sensu
|
|
463
471
|
|
464
472
|
aget %r{/aggregates/([\w\.-]+)$} do |check_name|
|
465
473
|
$redis.smembers('aggregates:' + check_name).callback do |aggregates|
|
466
|
-
|
474
|
+
unless aggregates.empty?
|
475
|
+
limit = 10
|
476
|
+
if params[:limit]
|
477
|
+
limit = params[:limit] =~ /^[0-9]+$/ ? params[:limit].to_i : nil
|
478
|
+
end
|
479
|
+
unless limit.nil?
|
480
|
+
body aggregates.sort.reverse.take(limit).to_json
|
481
|
+
else
|
482
|
+
bad_request!
|
483
|
+
end
|
484
|
+
else
|
485
|
+
not_found!
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
adelete %r{/aggregates/([\w\.-]+)$} do |check_name|
|
491
|
+
$redis.smembers('aggregates:' + check_name).callback do |aggregates|
|
492
|
+
unless aggregates.empty?
|
493
|
+
aggregates.each do |check_issued|
|
494
|
+
result_set = check_name + ':' + check_issued
|
495
|
+
$redis.del('aggregation:' + result_set)
|
496
|
+
$redis.del('aggregate:' + result_set)
|
497
|
+
end
|
498
|
+
$redis.del('aggregates:' + check_name).callback do
|
499
|
+
$redis.srem('aggregates', check_name).callback do
|
500
|
+
no_content!
|
501
|
+
end
|
502
|
+
end
|
503
|
+
else
|
504
|
+
not_found!
|
505
|
+
end
|
467
506
|
end
|
468
507
|
end
|
469
508
|
|
data/lib/sensu/constants.rb
CHANGED
data/lib/sensu/server.rb
CHANGED
@@ -136,6 +136,21 @@ module Sensu
|
|
136
136
|
subdue && subdue_at == (check[:subdue][:at] || 'handler').to_sym
|
137
137
|
end
|
138
138
|
|
139
|
+
def event_filtered?(filter_name, event)
|
140
|
+
if @settings.filter_exists?(filter_name)
|
141
|
+
filter = @settings[:filters][filter_name]
|
142
|
+
matched = hash_values_equal?(filter[:attributes], event)
|
143
|
+
filter[:negate] ? matched : !matched
|
144
|
+
else
|
145
|
+
@logger.error('unknown filter', {
|
146
|
+
:filter => {
|
147
|
+
:name => filter_name
|
148
|
+
}
|
149
|
+
})
|
150
|
+
false
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
139
154
|
def derive_handlers(handler_list, nested=false)
|
140
155
|
handler_list.inject(Array.new) do |handlers, handler_name|
|
141
156
|
if @settings.handler_exists?(handler_name)
|
@@ -167,23 +182,43 @@ module Sensu
|
|
167
182
|
handlers = derive_handlers(handler_list)
|
168
183
|
event_severity = Sensu::SEVERITIES[event[:check][:status]] || 'unknown'
|
169
184
|
handlers.select do |handler|
|
170
|
-
if
|
171
|
-
@logger.info('
|
185
|
+
if event[:action] == :flapping && !handler[:handle_flapping]
|
186
|
+
@logger.info('handler does not handle flapping events', {
|
172
187
|
:event => event,
|
173
188
|
:handler => handler
|
174
189
|
})
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
@logger.debug('handler does not handle event severity', {
|
190
|
+
next
|
191
|
+
end
|
192
|
+
if check_subdued?(event[:check], :handler)
|
193
|
+
@logger.info('check is subdued at handler', {
|
180
194
|
:event => event,
|
181
195
|
:handler => handler
|
182
196
|
})
|
183
|
-
|
184
|
-
else
|
185
|
-
true
|
197
|
+
next
|
186
198
|
end
|
199
|
+
if handler.has_key?(:severities) && !handler[:severities].include?(event_severity)
|
200
|
+
unless event[:action] == :resolve
|
201
|
+
@logger.debug('handler does not handle event severity', {
|
202
|
+
:event => event,
|
203
|
+
:handler => handler
|
204
|
+
})
|
205
|
+
next
|
206
|
+
end
|
207
|
+
end
|
208
|
+
if handler.has_key?(:filters) || handler.has_key?(:filter)
|
209
|
+
filter_list = Array(handler[:filters] || handler[:filter])
|
210
|
+
filtered = filter_list.any? do |filter_name|
|
211
|
+
event_filtered?(filter_name, event)
|
212
|
+
end
|
213
|
+
if filtered
|
214
|
+
@logger.debug('event filtered for handler', {
|
215
|
+
:event => event,
|
216
|
+
:handler => handler
|
217
|
+
})
|
218
|
+
next
|
219
|
+
end
|
220
|
+
end
|
221
|
+
true
|
187
222
|
end
|
188
223
|
end
|
189
224
|
|
@@ -417,8 +452,8 @@ module Sensu
|
|
417
452
|
:flapping => is_flapping,
|
418
453
|
:occurrences => event[:occurrences]
|
419
454
|
}.to_json).callback do
|
420
|
-
unless check[:handle] == false
|
421
|
-
event[:action] = :create
|
455
|
+
unless check[:handle] == false
|
456
|
+
event[:action] = is_flapping ? :flapping : :create
|
422
457
|
handle_event(event)
|
423
458
|
end
|
424
459
|
end
|
@@ -545,7 +580,7 @@ module Sensu
|
|
545
580
|
checks.each do |check_name|
|
546
581
|
@redis.smembers('aggregates:' + check_name).callback do |aggregates|
|
547
582
|
aggregates.sort!
|
548
|
-
until aggregates.size <=
|
583
|
+
until aggregates.size <= 20
|
549
584
|
check_issued = aggregates.shift
|
550
585
|
@redis.srem('aggregates:' + check_name, check_issued).callback do
|
551
586
|
result_set = check_name + ':' + check_issued.to_s
|
@@ -719,5 +754,19 @@ module Sensu
|
|
719
754
|
end
|
720
755
|
end
|
721
756
|
end
|
757
|
+
|
758
|
+
def hash_values_equal?(hash_one, hash_two)
|
759
|
+
hash_one.keys.all? do |key|
|
760
|
+
if hash_one[key] == hash_two[key]
|
761
|
+
true
|
762
|
+
else
|
763
|
+
if hash_one[key].is_a?(Hash) && hash_two[key].is_a?(Hash)
|
764
|
+
hash_values_equal?(hash_one[key], hash_two[key])
|
765
|
+
else
|
766
|
+
false
|
767
|
+
end
|
768
|
+
end
|
769
|
+
end
|
770
|
+
end
|
722
771
|
end
|
723
772
|
end
|
data/lib/sensu/settings.rb
CHANGED
@@ -5,7 +5,7 @@ module Sensu
|
|
5
5
|
def initialize
|
6
6
|
@logger = Sensu::Logger.get
|
7
7
|
@settings = Hash.new
|
8
|
-
[:checks, :
|
8
|
+
[:checks, :filters, :mutators, :handlers].each do |key|
|
9
9
|
@settings[key] = Hash.new
|
10
10
|
end
|
11
11
|
@indifferent_access = false
|
@@ -89,7 +89,7 @@ module Sensu
|
|
89
89
|
ENV['SENSU_CONFIG_FILES'] = @loaded_files.join(':')
|
90
90
|
end
|
91
91
|
|
92
|
-
[:checks, :
|
92
|
+
[:checks, :filters, :mutators, :handlers].each do |key|
|
93
93
|
define_method(key) do
|
94
94
|
@settings[key].map do |name, details|
|
95
95
|
details.merge(:name => name.to_s)
|
@@ -217,6 +217,27 @@ module Sensu
|
|
217
217
|
:check => check
|
218
218
|
})
|
219
219
|
end
|
220
|
+
check[:handlers].each do |handler_name|
|
221
|
+
unless handler_name.is_a?(String)
|
222
|
+
invalid('check handlers items must be strings', {
|
223
|
+
:check => check
|
224
|
+
})
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
if check.has_key?(:low_flap_threshold)
|
229
|
+
unless check[:low_flap_threshold].is_a?(Integer)
|
230
|
+
invalid('flap thresholds must be integers', {
|
231
|
+
:check => check
|
232
|
+
})
|
233
|
+
end
|
234
|
+
end
|
235
|
+
if check.has_key?(:high_flap_threshold)
|
236
|
+
unless check[:high_flap_threshold].is_a?(Integer)
|
237
|
+
invalid('flap thresholds must be integers', {
|
238
|
+
:check => check
|
239
|
+
})
|
240
|
+
end
|
220
241
|
end
|
221
242
|
if check.has_key?(:subdue)
|
222
243
|
unless check[:subdue].is_a?(Hash)
|
@@ -315,6 +336,33 @@ module Sensu
|
|
315
336
|
end
|
316
337
|
|
317
338
|
def validate_server
|
339
|
+
unless @settings[:filters].is_a?(Hash)
|
340
|
+
invalid('filters must be a hash')
|
341
|
+
end
|
342
|
+
filters.each do |filter|
|
343
|
+
unless filter[:attributes].is_a?(Hash)
|
344
|
+
invalid('filter attributes must be a hash', {
|
345
|
+
:filter => filter
|
346
|
+
})
|
347
|
+
end
|
348
|
+
if filter.has_key?(:negate)
|
349
|
+
unless !!filter[:negate] == filter[:negate]
|
350
|
+
invalid('filter negate must be boolean', {
|
351
|
+
:filter => filter
|
352
|
+
})
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
unless @settings[:mutators].is_a?(Hash)
|
357
|
+
invalid('mutators must be a hash')
|
358
|
+
end
|
359
|
+
mutators.each do |mutator|
|
360
|
+
unless mutator[:command].is_a?(String)
|
361
|
+
invalid('mutator is missing command', {
|
362
|
+
:mutator => mutator
|
363
|
+
})
|
364
|
+
end
|
365
|
+
end
|
318
366
|
unless @settings[:handlers].is_a?(Hash)
|
319
367
|
invalid('handlers must be a hash')
|
320
368
|
end
|
@@ -327,20 +375,6 @@ module Sensu
|
|
327
375
|
:handler => handler
|
328
376
|
})
|
329
377
|
end
|
330
|
-
if handler.has_key?(:severities)
|
331
|
-
unless handler[:severities].is_a?(Array) && !handler[:severities].empty?
|
332
|
-
invalid('handler severities must be an array and not empty', {
|
333
|
-
:handler => handler
|
334
|
-
})
|
335
|
-
end
|
336
|
-
handler[:severities].each do |severity|
|
337
|
-
unless Sensu::SEVERITIES.include?(severity)
|
338
|
-
invalid('handler severities are invalid', {
|
339
|
-
:handler => handler
|
340
|
-
})
|
341
|
-
end
|
342
|
-
end
|
343
|
-
end
|
344
378
|
case handler[:type]
|
345
379
|
when 'pipe'
|
346
380
|
unless handler[:command].is_a?(String)
|
@@ -383,14 +417,14 @@ module Sensu
|
|
383
417
|
end
|
384
418
|
end
|
385
419
|
when 'set'
|
386
|
-
unless handler[:handlers].is_a?(Array)
|
387
|
-
invalid('handler set
|
420
|
+
unless handler[:handlers].is_a?(Array)
|
421
|
+
invalid('handler set handlers must be an array', {
|
388
422
|
:handler => handler
|
389
423
|
})
|
390
424
|
end
|
391
425
|
handler[:handlers].each do |handler_name|
|
392
426
|
unless handler_name.is_a?(String)
|
393
|
-
invalid('handler set handlers must be strings', {
|
427
|
+
invalid('handler set handlers items must be strings', {
|
394
428
|
:handler => handler
|
395
429
|
})
|
396
430
|
end
|
@@ -400,15 +434,54 @@ module Sensu
|
|
400
434
|
:handler => handler
|
401
435
|
})
|
402
436
|
end
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
437
|
+
if handler.has_key?(:filter)
|
438
|
+
unless handler[:filter].is_a?(String)
|
439
|
+
invalid('handler filter must be a string', {
|
440
|
+
:handler => handler
|
441
|
+
})
|
442
|
+
end
|
443
|
+
end
|
444
|
+
if handler.has_key?(:filters)
|
445
|
+
unless handler[:filters].is_a?(Array)
|
446
|
+
invalid('handler filters must be an array', {
|
447
|
+
:handler => handler
|
448
|
+
})
|
449
|
+
end
|
450
|
+
handler[:filters].each do |filter_name|
|
451
|
+
unless filter_name.is_a?(String)
|
452
|
+
invalid('handler filters items must be strings', {
|
453
|
+
:handler => handler
|
454
|
+
})
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|
458
|
+
if handler.has_key?(:mutator)
|
459
|
+
unless handler[:mutator].is_a?(String)
|
460
|
+
invalid('handler mutator must be a string', {
|
461
|
+
:handler => handler
|
462
|
+
})
|
463
|
+
end
|
464
|
+
end
|
465
|
+
if handler.has_key?(:handle_flapping)
|
466
|
+
unless !!handler[:handle_flapping] == handler[:handle_flapping]
|
467
|
+
invalid('handler handle_flapping must be boolean', {
|
468
|
+
:handler => handler
|
469
|
+
})
|
470
|
+
end
|
471
|
+
end
|
472
|
+
if handler.has_key?(:severities)
|
473
|
+
unless handler[:severities].is_a?(Array) && !handler[:severities].empty?
|
474
|
+
invalid('handler severities must be an array and not empty', {
|
475
|
+
:handler => handler
|
476
|
+
})
|
477
|
+
end
|
478
|
+
handler[:severities].each do |severity|
|
479
|
+
unless Sensu::SEVERITIES.include?(severity)
|
480
|
+
invalid('handler severities are invalid', {
|
481
|
+
:handler => handler
|
482
|
+
})
|
483
|
+
end
|
484
|
+
end
|
412
485
|
end
|
413
486
|
end
|
414
487
|
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1653984923
|
5
5
|
prerelease: true
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
9
|
- 9
|
10
10
|
- beta
|
11
|
-
|
11
|
+
- 1
|
12
|
+
version: 0.9.9.beta.1
|
12
13
|
platform: ruby
|
13
14
|
authors:
|
14
15
|
- Sean Porter
|
@@ -17,7 +18,7 @@ autorequire:
|
|
17
18
|
bindir: bin
|
18
19
|
cert_chain: []
|
19
20
|
|
20
|
-
date: 2012-
|
21
|
+
date: 2012-12-06 00:00:00 -08:00
|
21
22
|
default_executable:
|
22
23
|
dependencies:
|
23
24
|
- !ruby/object:Gem::Dependency
|