sensu 0.27.1 → 0.28.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -0
- data/lib/sensu/api/routes/clients.rb +1 -1
- data/lib/sensu/api/routes/info.rb +15 -10
- data/lib/sensu/api/routes/request.rb +7 -1
- data/lib/sensu/api/routes/silenced.rb +2 -1
- data/lib/sensu/api/utilities/servers_info.rb +36 -0
- data/lib/sensu/api/utilities/transport_info.rb +1 -0
- data/lib/sensu/client/process.rb +72 -55
- data/lib/sensu/client/socket.rb +1 -1
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/daemon.rb +3 -2
- data/lib/sensu/sandbox.rb +19 -0
- data/lib/sensu/server/filter.rb +1 -95
- data/lib/sensu/server/handle.rb +14 -7
- data/lib/sensu/server/process.rb +179 -43
- data/lib/sensu/server/socket.rb +1 -1
- data/lib/sensu/timers.rb +26 -0
- data/lib/sensu/utilities.rb +168 -2
- data/sensu.gemspec +2 -1
- metadata +21 -5
- data/lib/sensu/server/sandbox.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36cc218210482434f3c8fd4e27e662d109f336f6
|
4
|
+
data.tar.gz: 25fd707fa69a6228cd9979e80d726facb8d4325b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d16c1695e58f06722efb401f28759ce0b187bd66893e371eaf9e6e6f3df1d4d55b2c1c943de0e53334f09e8a678677b8ec7b5d94ba083bd3c288c7c46cd68dc3
|
7
|
+
data.tar.gz: fe9d61057a7d5914b8c8dd901d0bb4630783fcf21b0bd48befa1f07abe8b1e38bc1c23672321baa870bdd46260968c798104970bbd7eb0b45236be5d29bfb947
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,40 @@
|
|
1
|
+
## 0.28.0 - 2017-02-23
|
2
|
+
|
3
|
+
### Features
|
4
|
+
|
5
|
+
Added proxy check requests to improve Sensu's ability to monitor external
|
6
|
+
resources that have an associated Sensu proxy client. Publish a check
|
7
|
+
request to the configured `subscribers` (e.g.
|
8
|
+
`["round-robin:snmp_pollers"]`) for every Sensu client in the registry
|
9
|
+
that matches the configured client attributes in `client_attributes` on
|
10
|
+
the configured `interval` (e.g. `60`). Client tokens in the check
|
11
|
+
definition (e.g. `"check-snmp-if.rb -h :::address::: -i eth0"`) are
|
12
|
+
substituted prior to publishing the check request. The check request check
|
13
|
+
`source` is set to the client `name`.
|
14
|
+
|
15
|
+
Schedule check requests and standalone executions with the Cron syntax.
|
16
|
+
|
17
|
+
Added the Sensu server registry, containing information about the running
|
18
|
+
Sensu servers. Information about the Sensu servers is now accessible via
|
19
|
+
the Sensu API `/info` endpoint.
|
20
|
+
|
21
|
+
Added two optional attributes to Sensu API POST `/request`, `"reason"` and
|
22
|
+
`"creator"`, for additional context. The check request reason and creator
|
23
|
+
are added to the check request payload under `"api_requested"` and become
|
24
|
+
part of the check result.
|
25
|
+
|
26
|
+
Added event IDs to event handler log events for additional context, making
|
27
|
+
it easier to trace an event through the Sensu pipeline.
|
28
|
+
|
29
|
+
### Fixes
|
30
|
+
|
31
|
+
The Sensu interval timers, used for scheduling tasks, now account for
|
32
|
+
drift. The check request and standalone execution scheduler timers are now
|
33
|
+
more accurate.
|
34
|
+
|
35
|
+
Fixed a bug in the Sensu `deep_merge()` method that was responsible for
|
36
|
+
mutating arrays of the original provided objects.
|
37
|
+
|
1
38
|
## 0.27.1 - 2017-02-17
|
2
39
|
|
3
40
|
### Other
|
@@ -1,26 +1,31 @@
|
|
1
1
|
require "sensu/api/utilities/transport_info"
|
2
|
+
require "sensu/api/utilities/servers_info"
|
2
3
|
|
3
4
|
module Sensu
|
4
5
|
module API
|
5
6
|
module Routes
|
6
7
|
module Info
|
7
8
|
include Utilities::TransportInfo
|
9
|
+
include Utilities::ServersInfo
|
8
10
|
|
9
11
|
INFO_URI = /^\/info$/
|
10
12
|
|
11
13
|
# GET /info
|
12
14
|
def get_info
|
13
|
-
transport_info do |
|
14
|
-
|
15
|
-
|
16
|
-
:
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
:
|
15
|
+
transport_info do |transport|
|
16
|
+
servers_info do |servers|
|
17
|
+
@response_content = {
|
18
|
+
:sensu => {
|
19
|
+
:version => VERSION
|
20
|
+
},
|
21
|
+
:transport => transport,
|
22
|
+
:redis => {
|
23
|
+
:connected => @redis.connected?
|
24
|
+
},
|
25
|
+
:servers => servers
|
21
26
|
}
|
22
|
-
|
23
|
-
|
27
|
+
respond
|
28
|
+
end
|
24
29
|
end
|
25
30
|
end
|
26
31
|
end
|
@@ -12,7 +12,9 @@ module Sensu
|
|
12
12
|
def post_request
|
13
13
|
rules = {
|
14
14
|
:check => {:type => String, :nil_ok => false},
|
15
|
-
:subscribers => {:type => Array, :nil_ok => true}
|
15
|
+
:subscribers => {:type => Array, :nil_ok => true},
|
16
|
+
:reason => {:type => String, :nil_ok => true},
|
17
|
+
:creator => {:type => String, :nil_ok => true}
|
16
18
|
}
|
17
19
|
read_data(rules) do |data|
|
18
20
|
if @settings[:checks][data[:check]]
|
@@ -20,6 +22,10 @@ module Sensu
|
|
20
22
|
check[:name] = data[:check]
|
21
23
|
check[:subscribers] ||= Array.new
|
22
24
|
check[:subscribers] = data[:subscribers] if data[:subscribers]
|
25
|
+
check[:api_requested] = {
|
26
|
+
:reason => data[:reason],
|
27
|
+
:creator => data[:creator]
|
28
|
+
}
|
23
29
|
publish_check_request(check)
|
24
30
|
@response_content = {:issued => Time.now.to_i}
|
25
31
|
accepted!
|
@@ -64,7 +64,8 @@ module Sensu
|
|
64
64
|
:check => data[:check],
|
65
65
|
:reason => data[:reason],
|
66
66
|
:creator => data[:creator],
|
67
|
-
:expire_on_resolve => data.fetch(:expire_on_resolve, false)
|
67
|
+
:expire_on_resolve => data.fetch(:expire_on_resolve, false),
|
68
|
+
:timestamp => Time.now.to_i
|
68
69
|
}
|
69
70
|
silenced_key = "silence:#{silenced_id}"
|
70
71
|
@redis.set(silenced_key, Sensu::JSON.dump(silenced_info)) do
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sensu
|
2
|
+
module API
|
3
|
+
module Utilities
|
4
|
+
module ServersInfo
|
5
|
+
# Retreive the Sensu servers info.
|
6
|
+
#
|
7
|
+
# @yield [Hash] passes servers info to the callback/block.
|
8
|
+
def servers_info
|
9
|
+
info = []
|
10
|
+
if @redis.connected?
|
11
|
+
@redis.smembers("servers") do |servers|
|
12
|
+
unless servers.empty?
|
13
|
+
servers.each_with_index do |server_id, index|
|
14
|
+
@redis.get("server:#{server_id}") do |server_json|
|
15
|
+
unless server_json.nil?
|
16
|
+
info << Sensu::JSON.load(server_json)
|
17
|
+
else
|
18
|
+
@redis.srem("servers", server_id)
|
19
|
+
end
|
20
|
+
if index == servers.length - 1
|
21
|
+
yield(info)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
else
|
26
|
+
yield(info)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
else
|
30
|
+
yield(info)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/sensu/client/process.rb
CHANGED
@@ -69,7 +69,7 @@ module Sensu
|
|
69
69
|
def setup_keepalives
|
70
70
|
@logger.debug("scheduling keepalives")
|
71
71
|
publish_keepalive
|
72
|
-
@timers[:run] <<
|
72
|
+
@timers[:run] << PeriodicTimer.new(20) do
|
73
73
|
publish_keepalive
|
74
74
|
end
|
75
75
|
end
|
@@ -100,33 +100,6 @@ module Sensu
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
-
# Perform token substitution for an object. String values are
|
104
|
-
# passed to `substitute_tokens()`, arrays and sub-hashes are
|
105
|
-
# processed recursively. Numeric values are ignored.
|
106
|
-
#
|
107
|
-
# @param object [Object]
|
108
|
-
# @return [Array] containing the updated object with substituted
|
109
|
-
# values and an array of unmatched tokens.
|
110
|
-
def object_substitute_tokens(object)
|
111
|
-
unmatched_tokens = []
|
112
|
-
case object
|
113
|
-
when Hash
|
114
|
-
object.each do |key, value|
|
115
|
-
object[key], unmatched = object_substitute_tokens(value)
|
116
|
-
unmatched_tokens.push(*unmatched)
|
117
|
-
end
|
118
|
-
when Array
|
119
|
-
object.map! do |value|
|
120
|
-
value, unmatched = object_substitute_tokens(value)
|
121
|
-
unmatched_tokens.push(*unmatched)
|
122
|
-
value
|
123
|
-
end
|
124
|
-
when String
|
125
|
-
object, unmatched_tokens = substitute_tokens(object, @settings[:client])
|
126
|
-
end
|
127
|
-
[object, unmatched_tokens.uniq]
|
128
|
-
end
|
129
|
-
|
130
103
|
# Execute a check command, capturing its output (STDOUT/ERR),
|
131
104
|
# exit status code, execution duration, timestamp, and publish
|
132
105
|
# the result. This method guards against multiple executions for
|
@@ -144,7 +117,7 @@ module Sensu
|
|
144
117
|
@logger.debug("attempting to execute check command", :check => check)
|
145
118
|
unless @checks_in_progress.include?(check[:name])
|
146
119
|
@checks_in_progress << check[:name]
|
147
|
-
substituted, unmatched_tokens = object_substitute_tokens(check.dup)
|
120
|
+
substituted, unmatched_tokens = object_substitute_tokens(check.dup, @settings[:client])
|
148
121
|
check = substituted.merge(:command => check[:command])
|
149
122
|
started = Time.now.to_f
|
150
123
|
check[:executed] = started.to_i
|
@@ -292,58 +265,102 @@ module Sensu
|
|
292
265
|
end
|
293
266
|
end
|
294
267
|
|
268
|
+
# Create a check execution proc, used to execute standalone
|
269
|
+
# checks. Checks are not executed if subdued. The check
|
270
|
+
# `:issued` timestamp is set here, to mimic check requests
|
271
|
+
# issued by a Sensu server. Check definitions are duplicated
|
272
|
+
# before processing them, in case they are mutated.
|
273
|
+
#
|
274
|
+
# @param check [Hash] definition.
|
275
|
+
def create_check_execution_proc(check)
|
276
|
+
Proc.new do
|
277
|
+
unless check_subdued?(check)
|
278
|
+
check[:issued] = Time.now.to_i
|
279
|
+
process_check_request(check.dup)
|
280
|
+
else
|
281
|
+
@logger.info("check execution was subdued", :check => check)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
# Schedule a check execution, using the check cron. This method
|
287
|
+
# determines the time until the next cron time (in seconds) and
|
288
|
+
# creats an EventMachine timer for the execution. This method
|
289
|
+
# will be called after every check cron execution for subsequent
|
290
|
+
# executions. The timer is stored in the timers hash under
|
291
|
+
# `:run`, so it can be cancelled etc. The check cron execution
|
292
|
+
# timer object is removed from the timer hash after the
|
293
|
+
# execution, to stop the timer hash from growing infinitely.
|
294
|
+
#
|
295
|
+
# @param check [Hash] definition.
|
296
|
+
def schedule_check_cron_execution(check)
|
297
|
+
cron_time = determine_check_cron_time(check)
|
298
|
+
@timers[:run] << Timer.new(cron_time) do |timer|
|
299
|
+
create_check_execution_proc(check).call
|
300
|
+
@timers[:run].delete(timer)
|
301
|
+
schedule_check_cron_execution(check)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
295
305
|
# Calculate a check execution splay, taking into account the
|
296
306
|
# current time and the execution interval to ensure it's
|
297
307
|
# consistent between process restarts.
|
298
308
|
#
|
299
309
|
# @param check [Hash] definition.
|
300
|
-
def
|
310
|
+
def calculate_check_execution_splay(check)
|
301
311
|
key = [@settings[:client][:name], check[:name]].join(":")
|
302
312
|
splay_hash = Digest::MD5.digest(key).unpack("Q<").first
|
303
313
|
current_time = (Time.now.to_f * 1000).to_i
|
304
314
|
(splay_hash - current_time) % (check[:interval] * 1000) / 1000.0
|
305
315
|
end
|
306
316
|
|
307
|
-
# Schedule check executions, using
|
308
|
-
# using
|
309
|
-
#
|
310
|
-
#
|
311
|
-
#
|
312
|
-
#
|
313
|
-
# check
|
317
|
+
# Schedule check executions, using the check interval. This
|
318
|
+
# method using an intial calculated execution splay EventMachine
|
319
|
+
# timer and an EventMachine periodic timer for subsequent check
|
320
|
+
# executions. The timers are stored in the timers hash under
|
321
|
+
# `:run`, so they can be cancelled etc.
|
322
|
+
#
|
323
|
+
# @param check [Hash] definition.
|
324
|
+
def schedule_check_interval_executions(check)
|
325
|
+
execution_splay = testing? ? 0 : calculate_check_execution_splay(check)
|
326
|
+
interval = testing? ? 0.5 : check[:interval]
|
327
|
+
@timers[:run] << Timer.new(execution_splay) do
|
328
|
+
execute_check = create_check_execution_proc(check)
|
329
|
+
execute_check.call
|
330
|
+
@timers[:run] << PeriodicTimer.new(interval, &execute_check)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# Schedule check executions. This method iterates through defined
|
335
|
+
# checks and uses the appropriate method of check execution
|
336
|
+
# scheduling, either with the cron syntax or a numeric interval.
|
314
337
|
#
|
315
338
|
# @param checks [Array] of definitions.
|
316
339
|
def schedule_checks(checks)
|
317
340
|
checks.each do |check|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
else
|
323
|
-
@logger.info("check execution was subdued", :check => check)
|
324
|
-
end
|
325
|
-
end
|
326
|
-
execution_splay = testing? ? 0 : calculate_execution_splay(check)
|
327
|
-
interval = testing? ? 0.5 : check[:interval]
|
328
|
-
@timers[:run] << EM::Timer.new(execution_splay) do
|
329
|
-
execute_check.call
|
330
|
-
@timers[:run] << EM::PeriodicTimer.new(interval, &execute_check)
|
341
|
+
if check[:cron]
|
342
|
+
schedule_check_cron_execution(check)
|
343
|
+
else
|
344
|
+
schedule_check_interval_executions(check)
|
331
345
|
end
|
332
346
|
end
|
333
347
|
end
|
334
348
|
|
335
349
|
# Setup standalone check executions, scheduling standard check
|
336
350
|
# definition and check extension executions. Check definitions
|
337
|
-
# and extensions with `:standalone` set to `true`, have
|
338
|
-
#
|
339
|
-
# will be scheduled by the Sensu client for
|
351
|
+
# and extensions with `:standalone` set to `true`, do not have
|
352
|
+
# `:publish` set to `false`, and have a integer `:interval` or a
|
353
|
+
# string `cron` will be scheduled by the Sensu client for
|
354
|
+
# execution.
|
340
355
|
def setup_standalone
|
341
356
|
@logger.debug("scheduling standalone checks")
|
342
357
|
standard_checks = @settings.checks.select do |check|
|
343
|
-
check[:standalone] && check[:
|
358
|
+
check[:standalone] && check[:publish] != false &&
|
359
|
+
(check[:interval].is_a?(Integer) || check[:cron].is_a?(String))
|
344
360
|
end
|
345
361
|
extension_checks = @extensions.checks.select do |check|
|
346
|
-
check[:standalone] && check[:
|
362
|
+
check[:standalone] && check[:publish] != false &&
|
363
|
+
(check[:interval].is_a?(Integer) || check[:cron].is_a?(String))
|
347
364
|
end
|
348
365
|
schedule_checks(standard_checks + extension_checks)
|
349
366
|
end
|
data/lib/sensu/client/socket.rb
CHANGED
@@ -106,7 +106,7 @@ module Sensu
|
|
106
106
|
# Reset (or start) the connection watchdog.
|
107
107
|
def reset_watchdog
|
108
108
|
cancel_watchdog
|
109
|
-
@watchdog =
|
109
|
+
@watchdog = Timer.new(WATCHDOG_DELAY) do
|
110
110
|
@mode = MODE_REJECT
|
111
111
|
@logger.warn("discarding data buffer for sender and closing connection", {
|
112
112
|
:data => @data_buffer,
|
data/lib/sensu/constants.rb
CHANGED
data/lib/sensu/daemon.rb
CHANGED
@@ -4,7 +4,7 @@ gem "eventmachine", "1.2.2"
|
|
4
4
|
|
5
5
|
gem "sensu-json", "2.0.1"
|
6
6
|
gem "sensu-logger", "1.2.1"
|
7
|
-
gem "sensu-settings", "9.
|
7
|
+
gem "sensu-settings", "9.9.0"
|
8
8
|
gem "sensu-extension", "1.5.1"
|
9
9
|
gem "sensu-extensions", "1.7.1"
|
10
10
|
gem "sensu-transport", "7.0.2"
|
@@ -18,6 +18,7 @@ if RUBY_PLATFORM =~ /aix/ || RUBY_PLATFORM =~ /solaris/
|
|
18
18
|
require "em/pure_ruby"
|
19
19
|
end
|
20
20
|
|
21
|
+
require "sensu/timers"
|
21
22
|
require "sensu/json"
|
22
23
|
require "sensu/logger"
|
23
24
|
require "sensu/settings"
|
@@ -227,7 +228,7 @@ module Sensu
|
|
227
228
|
@signals << signal
|
228
229
|
end
|
229
230
|
end
|
230
|
-
|
231
|
+
PeriodicTimer.new(1) do
|
231
232
|
signal = @signals.shift
|
232
233
|
if STOP_SIGNALS.include?(signal)
|
233
234
|
@logger.warn("received signal", :signal => signal)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sensu
|
2
|
+
module Sandbox
|
3
|
+
# Evaluate a Ruby expression within the context of a simple
|
4
|
+
# "sandbox", a Proc in a module method. As of Ruby 2.3.0,
|
5
|
+
# `$SAFE` no longer supports levels > 1, so its use has been
|
6
|
+
# removed from this method. A single value is provided to the
|
7
|
+
# "sandbox".
|
8
|
+
#
|
9
|
+
# @param expression [String] to be evaluated.
|
10
|
+
# @param value [Object] to provide the "sandbox" with.
|
11
|
+
# @return [Object]
|
12
|
+
def self.eval(expression, value=nil)
|
13
|
+
result = Proc.new do
|
14
|
+
Kernel.eval(expression)
|
15
|
+
end
|
16
|
+
result.call
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/sensu/server/filter.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
|
-
require "sensu/server/sandbox"
|
2
|
-
|
3
1
|
module Sensu
|
4
2
|
module Server
|
5
3
|
module Filter
|
6
|
-
EVAL_PREFIX = "eval:".freeze
|
7
|
-
|
8
4
|
# Determine if an event handler is silenced.
|
9
5
|
#
|
10
6
|
# @param handler [Hash] definition.
|
@@ -68,96 +64,6 @@ module Sensu
|
|
68
64
|
end
|
69
65
|
end
|
70
66
|
|
71
|
-
# Process a filter eval attribute, a Ruby `eval()` string
|
72
|
-
# containing an expression to be evaluated within the
|
73
|
-
# scope/context of a sandbox. This methods strips away the
|
74
|
-
# expression prefix, `eval:`, and substitues any dot notation
|
75
|
-
# tokens with the corresponding event data values. If there are
|
76
|
-
# unmatched tokens, this method will return `nil`.
|
77
|
-
#
|
78
|
-
# @event [Hash]
|
79
|
-
# @raw_eval_string [String]
|
80
|
-
# @return [String] processed eval string.
|
81
|
-
def process_eval_string(event, raw_eval_string)
|
82
|
-
eval_string = raw_eval_string.slice(5..-1)
|
83
|
-
eval_string, unmatched_tokens = substitute_tokens(eval_string, event)
|
84
|
-
if unmatched_tokens.empty?
|
85
|
-
eval_string
|
86
|
-
else
|
87
|
-
@logger.error("filter eval unmatched tokens", {
|
88
|
-
:raw_eval_string => raw_eval_string,
|
89
|
-
:unmatched_tokens => unmatched_tokens,
|
90
|
-
:event => event
|
91
|
-
})
|
92
|
-
nil
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# Ruby `eval()` a string containing an expression, within the
|
97
|
-
# scope/context of a sandbox. This method is for filter
|
98
|
-
# attribute values starting with "eval:", with the Ruby
|
99
|
-
# expression following the colon. A single variable is provided
|
100
|
-
# to the expression, `value`, equal to the corresponding event
|
101
|
-
# attribute value. Dot notation tokens in the expression, e.g.
|
102
|
-
# `:::mysql.user:::`, are substituted with the corresponding
|
103
|
-
# event data values prior to evaluation. The expression is
|
104
|
-
# expected to return a boolean value.
|
105
|
-
#
|
106
|
-
# @param event [Hash]
|
107
|
-
# @param raw_eval_string [String] containing the Ruby
|
108
|
-
# expression to be evaluated.
|
109
|
-
# @param raw_value [Object] of the corresponding event
|
110
|
-
# attribute value.
|
111
|
-
# @return [TrueClass, FalseClass]
|
112
|
-
def eval_attribute_value(event, raw_eval_string, raw_value)
|
113
|
-
eval_string = process_eval_string(event, raw_eval_string)
|
114
|
-
unless eval_string.nil?
|
115
|
-
begin
|
116
|
-
value = Marshal.load(Marshal.dump(raw_value))
|
117
|
-
!!Sandbox.eval(eval_string, value)
|
118
|
-
rescue StandardError, SyntaxError => error
|
119
|
-
@logger.error("filter attribute eval error", {
|
120
|
-
:event => event,
|
121
|
-
:raw_eval_string => raw_eval_string,
|
122
|
-
:raw_value => raw_value,
|
123
|
-
:error => error.to_s
|
124
|
-
})
|
125
|
-
false
|
126
|
-
end
|
127
|
-
else
|
128
|
-
false
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# Determine if all filter attribute values match those of the
|
133
|
-
# corresponding event attributes. Attributes match if the value
|
134
|
-
# objects are equivalent, are both hashes with matching
|
135
|
-
# key/value pairs (recursive), have equal string values, or
|
136
|
-
# evaluate to true (Ruby eval).
|
137
|
-
#
|
138
|
-
# @param event [Hash]
|
139
|
-
# @param filter_attributes [Object]
|
140
|
-
# @param event_attributes [Object]
|
141
|
-
# @return [TrueClass, FalseClass]
|
142
|
-
def filter_attributes_match?(event, filter_attributes, event_attributes=nil)
|
143
|
-
event_attributes ||= event
|
144
|
-
filter_attributes.all? do |key, value_one|
|
145
|
-
value_two = event_attributes[key]
|
146
|
-
case
|
147
|
-
when value_one == value_two
|
148
|
-
true
|
149
|
-
when value_one.is_a?(Hash) && value_two.is_a?(Hash)
|
150
|
-
filter_attributes_match?(event, value_one, value_two)
|
151
|
-
when value_one.to_s == value_two.to_s
|
152
|
-
true
|
153
|
-
when value_one.is_a?(String) && value_one.start_with?(EVAL_PREFIX)
|
154
|
-
eval_attribute_value(event, value_one, value_two)
|
155
|
-
else
|
156
|
-
false
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
67
|
# Determine if a filter is to be evoked for the current time. A
|
162
68
|
# filter can be configured with a time window defining when it
|
163
69
|
# is to be evoked, e.g. Monday through Friday, 9-5.
|
@@ -184,7 +90,7 @@ module Sensu
|
|
184
90
|
def native_filter(filter_name, event)
|
185
91
|
filter = @settings[:filters][filter_name]
|
186
92
|
if in_filter_time_windows?(filter)
|
187
|
-
matched =
|
93
|
+
matched = attributes_match?(event, filter[:attributes])
|
188
94
|
yield(filter[:negate] ? matched : !matched, filter_name)
|
189
95
|
else
|
190
96
|
yield(false, filter_name)
|