sensu 0.27.1 → 0.28.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|