sensu 0.22.2 → 0.23.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/MIT-LICENSE.txt +1 -1
- data/lib/sensu/api/process.rb +69 -65
- data/lib/sensu/cli.rb +3 -0
- data/lib/sensu/client/process.rb +9 -44
- data/lib/sensu/client/socket.rb +4 -4
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/daemon.rb +69 -40
- data/lib/sensu/server/filter.rb +63 -24
- data/lib/sensu/server/mutate.rb +1 -1
- data/lib/sensu/server/process.rb +68 -54
- data/lib/sensu/server/sandbox.rb +4 -4
- data/lib/sensu/utilities.rb +40 -4
- data/sensu.gemspec +7 -9
- metadata +21 -36
- data/lib/sensu/redis.rb +0 -25
data/lib/sensu/client/process.rb
CHANGED
@@ -51,7 +51,7 @@ module Sensu
|
|
51
51
|
def publish_keepalive
|
52
52
|
payload = keepalive_payload
|
53
53
|
@logger.debug("publishing keepalive", :payload => payload)
|
54
|
-
@transport.publish(:direct, "keepalives",
|
54
|
+
@transport.publish(:direct, "keepalives", Sensu::JSON.dump(payload)) do |info|
|
55
55
|
if info[:error]
|
56
56
|
@logger.error("failed to publish keepalive", {
|
57
57
|
:payload => payload,
|
@@ -89,7 +89,7 @@ module Sensu
|
|
89
89
|
}
|
90
90
|
payload[:signature] = @settings[:client][:signature] if @settings[:client][:signature]
|
91
91
|
@logger.info("publishing check result", :payload => payload)
|
92
|
-
@transport.publish(:direct, "results",
|
92
|
+
@transport.publish(:direct, "results", Sensu::JSON.dump(payload)) do |info|
|
93
93
|
if info[:error]
|
94
94
|
@logger.error("failed to publish check result", {
|
95
95
|
:payload => payload,
|
@@ -99,42 +99,6 @@ module Sensu
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
# Traverse the Sensu client definition (hash) for an attribute
|
103
|
-
# value, with a fallback default value if nil.
|
104
|
-
#
|
105
|
-
# @param tree [Hash] to traverse.
|
106
|
-
# @param path [Array] of attribute keys.
|
107
|
-
# @param default [Object] value if attribute value is nil.
|
108
|
-
# @return [Object] attribute or fallback default value.
|
109
|
-
def find_client_attribute(tree, path, default)
|
110
|
-
attribute = tree[path.shift]
|
111
|
-
if attribute.is_a?(Hash)
|
112
|
-
find_client_attribute(attribute, path, default)
|
113
|
-
else
|
114
|
-
attribute.nil? ? default : attribute
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# Substitue check command tokens (eg. :::db.name|production:::)
|
119
|
-
# with the associated client definition attribute value. Command
|
120
|
-
# tokens can provide a fallback default value, following a pipe.
|
121
|
-
#
|
122
|
-
# @param check [Hash]
|
123
|
-
# @return [Array] containing the check command string with
|
124
|
-
# tokens substituted and an array of unmatched command tokens.
|
125
|
-
def substitute_check_command_tokens(check)
|
126
|
-
unmatched_tokens = []
|
127
|
-
substituted = check[:command].gsub(/:::([^:].*?):::/) do
|
128
|
-
token, default = $1.to_s.split("|", -1)
|
129
|
-
matched = find_client_attribute(@settings[:client], token.split("."), default)
|
130
|
-
if matched.nil?
|
131
|
-
unmatched_tokens << token
|
132
|
-
end
|
133
|
-
matched
|
134
|
-
end
|
135
|
-
[substituted, unmatched_tokens]
|
136
|
-
end
|
137
|
-
|
138
102
|
# Execute a check command, capturing its output (STDOUT/ERR),
|
139
103
|
# exit status code, execution duration, timestamp, and publish
|
140
104
|
# the result. This method guards against multiple executions for
|
@@ -149,7 +113,7 @@ module Sensu
|
|
149
113
|
@logger.debug("attempting to execute check command", :check => check)
|
150
114
|
unless @checks_in_progress.include?(check[:name])
|
151
115
|
@checks_in_progress << check[:name]
|
152
|
-
command, unmatched_tokens =
|
116
|
+
command, unmatched_tokens = substitute_tokens(check[:command], @settings[:client])
|
153
117
|
if unmatched_tokens.empty?
|
154
118
|
check[:executed] = Time.now.to_i
|
155
119
|
started = Time.now.to_f
|
@@ -273,10 +237,10 @@ module Sensu
|
|
273
237
|
options = transport_subscribe_options(subscription)
|
274
238
|
@transport.subscribe(*options) do |message_info, message|
|
275
239
|
begin
|
276
|
-
check =
|
240
|
+
check = Sensu::JSON.load(message)
|
277
241
|
@logger.info("received check request", :check => check)
|
278
242
|
process_check_request(check)
|
279
|
-
rescue
|
243
|
+
rescue Sensu::JSON::ParseError => error
|
280
244
|
@logger.error("failed to parse the check request payload", {
|
281
245
|
:message => message,
|
282
246
|
:error => error.to_s
|
@@ -412,9 +376,10 @@ module Sensu
|
|
412
376
|
# transport connection, the sockets, and calling the
|
413
377
|
# `bootstrap()` method.
|
414
378
|
def start
|
415
|
-
setup_transport
|
416
|
-
|
417
|
-
|
379
|
+
setup_transport do
|
380
|
+
setup_sockets
|
381
|
+
bootstrap
|
382
|
+
end
|
418
383
|
end
|
419
384
|
|
420
385
|
# Pause the Sensu client process, unless it is being paused or
|
data/lib/sensu/client/socket.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "
|
1
|
+
require "sensu/json"
|
2
2
|
|
3
3
|
module Sensu
|
4
4
|
module Client
|
@@ -145,7 +145,7 @@ module Sensu
|
|
145
145
|
:check => check.merge(:issued => Time.now.to_i)
|
146
146
|
}
|
147
147
|
@logger.info("publishing check result", :payload => payload)
|
148
|
-
@transport.publish(:direct, "results",
|
148
|
+
@transport.publish(:direct, "results", Sensu::JSON.dump(payload))
|
149
149
|
end
|
150
150
|
|
151
151
|
# Process a check result. Set check result attribute defaults,
|
@@ -169,10 +169,10 @@ module Sensu
|
|
169
169
|
# @param [String] data to parse for a check result.
|
170
170
|
def parse_check_result(data)
|
171
171
|
begin
|
172
|
-
check =
|
172
|
+
check = Sensu::JSON.load(data)
|
173
173
|
cancel_watchdog
|
174
174
|
process_check_result(check)
|
175
|
-
rescue
|
175
|
+
rescue Sensu::JSON::ParseError, ArgumentError => error
|
176
176
|
if @protocol == :tcp
|
177
177
|
@parse_error = error.to_s
|
178
178
|
else
|
data/lib/sensu/constants.rb
CHANGED
data/lib/sensu/daemon.rb
CHANGED
@@ -1,31 +1,30 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
|
3
|
-
gem "
|
4
|
-
gem "eventmachine", "1.0.9.1"
|
3
|
+
gem "eventmachine", "1.2.0.1"
|
5
4
|
|
6
|
-
gem "sensu-
|
7
|
-
gem "sensu-
|
5
|
+
gem "sensu-json", "1.1.0"
|
6
|
+
gem "sensu-logger", "1.2.0"
|
7
|
+
gem "sensu-settings", "3.4.0"
|
8
8
|
gem "sensu-extension", "1.5.0"
|
9
|
-
gem "sensu-extensions", "1.
|
10
|
-
gem "sensu-transport", "
|
9
|
+
gem "sensu-extensions", "1.5.0"
|
10
|
+
gem "sensu-transport", "5.0.0"
|
11
11
|
gem "sensu-spawn", "1.8.0"
|
12
|
+
gem "sensu-redis", "1.2.0"
|
12
13
|
|
13
14
|
require "time"
|
14
15
|
require "uri"
|
15
16
|
|
17
|
+
require "sensu/json"
|
16
18
|
require "sensu/logger"
|
17
19
|
require "sensu/settings"
|
18
20
|
require "sensu/extensions"
|
19
21
|
require "sensu/transport"
|
20
22
|
require "sensu/spawn"
|
23
|
+
require "sensu/redis"
|
21
24
|
|
22
25
|
require "sensu/constants"
|
23
26
|
require "sensu/utilities"
|
24
27
|
require "sensu/cli"
|
25
|
-
require "sensu/redis"
|
26
|
-
|
27
|
-
# Symbolize hash keys when parsing JSON.
|
28
|
-
MultiJson.load_options = {:symbolize_keys => true}
|
29
28
|
|
30
29
|
module Sensu
|
31
30
|
module Daemon
|
@@ -73,10 +72,26 @@ module Sensu
|
|
73
72
|
end
|
74
73
|
end
|
75
74
|
|
75
|
+
# Print the Sensu settings and immediately exit the process. This
|
76
|
+
# method is used while troubleshooting configuration issues,
|
77
|
+
# triggered by a CLI argument, e.g. `--print_config`. Sensu
|
78
|
+
# settings with sensitive values (e.g. passwords) are first
|
79
|
+
# redacted.
|
80
|
+
#
|
81
|
+
# @param settings [Object]
|
82
|
+
def print_settings(settings)
|
83
|
+
redacted_settings = redact_sensitive(settings.to_hash)
|
84
|
+
@logger.warn("outputting compiled configuration and exiting")
|
85
|
+
puts Sensu::JSON.dump(redacted_settings, :pretty => true)
|
86
|
+
exit
|
87
|
+
end
|
88
|
+
|
76
89
|
# Load Sensu settings and validate them. If there are validation
|
77
90
|
# failures, log them (concerns), then cause the Sensu process to
|
78
91
|
# exit (2). This method creates the settings instance variable:
|
79
|
-
# `@settings`.
|
92
|
+
# `@settings`. If the `print_config` option is true, this method
|
93
|
+
# calls `print_settings()` to output the compiled configuration
|
94
|
+
# settings and then exit the process.
|
80
95
|
#
|
81
96
|
# https://github.com/sensu/sensu-settings
|
82
97
|
#
|
@@ -91,6 +106,7 @@ module Sensu
|
|
91
106
|
@logger.fatal("SENSU NOT RUNNING!")
|
92
107
|
exit 2
|
93
108
|
end
|
109
|
+
print_settings(@settings) if options[:print_config]
|
94
110
|
end
|
95
111
|
|
96
112
|
# Load Sensu extensions and log any concerns. Set the logger and
|
@@ -176,6 +192,9 @@ module Sensu
|
|
176
192
|
# method creates the transport instance variable: `@transport`.
|
177
193
|
#
|
178
194
|
# https://github.com/sensu/sensu-transport
|
195
|
+
#
|
196
|
+
# @yield [Object] passes initialized and connected Transport
|
197
|
+
# connection object to the callback/block.
|
179
198
|
def setup_transport
|
180
199
|
transport_name = @settings[:transport][:name]
|
181
200
|
transport_settings = @settings[transport_name]
|
@@ -184,24 +203,27 @@ module Sensu
|
|
184
203
|
:settings => transport_settings
|
185
204
|
})
|
186
205
|
Transport.logger = @logger
|
187
|
-
|
188
|
-
|
189
|
-
@
|
190
|
-
|
191
|
-
@transport
|
192
|
-
|
193
|
-
|
206
|
+
Transport.connect(transport_name, transport_settings) do |connection|
|
207
|
+
@transport = connection
|
208
|
+
@transport.on_error do |error|
|
209
|
+
@logger.error("transport connection error", :error => error.to_s)
|
210
|
+
if @settings[:transport][:reconnect_on_error]
|
211
|
+
@transport.reconnect
|
212
|
+
else
|
213
|
+
stop
|
214
|
+
end
|
194
215
|
end
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
216
|
+
@transport.before_reconnect do
|
217
|
+
unless testing?
|
218
|
+
@logger.warn("reconnecting to transport")
|
219
|
+
pause
|
220
|
+
end
|
200
221
|
end
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
222
|
+
@transport.after_reconnect do
|
223
|
+
@logger.info("reconnected to transport")
|
224
|
+
resume
|
225
|
+
end
|
226
|
+
yield(@transport)
|
205
227
|
end
|
206
228
|
end
|
207
229
|
|
@@ -210,22 +232,29 @@ module Sensu
|
|
210
232
|
# service will stop gracefully in the event of a Redis error, and
|
211
233
|
# pause/resume in the event of connectivity issues. This method
|
212
234
|
# creates the Redis instance variable: `@redis`.
|
235
|
+
#
|
236
|
+
# https://github.com/sensu/sensu-redis
|
237
|
+
#
|
238
|
+
# @yield [Object] passes initialized and connected Redis
|
239
|
+
# connection object to the callback/block.
|
213
240
|
def setup_redis
|
214
241
|
@logger.debug("connecting to redis", :settings => @settings[:redis])
|
215
|
-
|
216
|
-
|
217
|
-
@
|
218
|
-
|
219
|
-
end
|
220
|
-
@redis.before_reconnect do
|
221
|
-
unless testing?
|
222
|
-
@logger.warn("reconnecting to redis")
|
223
|
-
pause
|
242
|
+
Redis.connect(@settings[:redis]) do |connection|
|
243
|
+
@redis = connection
|
244
|
+
@redis.on_error do |error|
|
245
|
+
@logger.error("redis connection error", :error => error.to_s)
|
224
246
|
end
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
247
|
+
@redis.before_reconnect do
|
248
|
+
unless testing?
|
249
|
+
@logger.warn("reconnecting to redis")
|
250
|
+
pause
|
251
|
+
end
|
252
|
+
end
|
253
|
+
@redis.after_reconnect do
|
254
|
+
@logger.info("reconnected to redis")
|
255
|
+
resume
|
256
|
+
end
|
257
|
+
yield(@redis)
|
229
258
|
end
|
230
259
|
end
|
231
260
|
|
data/lib/sensu/server/filter.rb
CHANGED
@@ -3,6 +3,8 @@ require "sensu/server/sandbox"
|
|
3
3
|
module Sensu
|
4
4
|
module Server
|
5
5
|
module Filter
|
6
|
+
EVAL_PREFIX = "eval:".freeze
|
7
|
+
|
6
8
|
# Determine if a period of time (window) is subdued. The
|
7
9
|
# provided condition must have a `:begin` and `:end` time, eg.
|
8
10
|
# "11:30:00 PM", or `false` will be returned.
|
@@ -165,28 +167,63 @@ module Sensu
|
|
165
167
|
end
|
166
168
|
end
|
167
169
|
|
168
|
-
#
|
170
|
+
# Process a filter eval attribute, a Ruby `eval()` string
|
171
|
+
# containing an expression to be evaluated within the
|
172
|
+
# scope/context of a sandbox. This methods strips away the
|
173
|
+
# expression prefix, `eval:`, and substitues any dot notation
|
174
|
+
# tokens with the corresponding event data values. If there are
|
175
|
+
# unmatched tokens, this method will return `nil`.
|
176
|
+
#
|
177
|
+
# @event [Hash]
|
178
|
+
# @raw_eval_string [String]
|
179
|
+
# @return [String] processed eval string.
|
180
|
+
def process_eval_string(event, raw_eval_string)
|
181
|
+
eval_string = raw_eval_string.slice(5..-1)
|
182
|
+
eval_string, unmatched_tokens = substitute_tokens(eval_string, event)
|
183
|
+
if unmatched_tokens.empty?
|
184
|
+
eval_string
|
185
|
+
else
|
186
|
+
@logger.error("filter eval unmatched tokens", {
|
187
|
+
:raw_eval_string => raw_eval_string,
|
188
|
+
:unmatched_tokens => unmatched_tokens,
|
189
|
+
:event => event
|
190
|
+
})
|
191
|
+
nil
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Ruby `eval()` a string containing an expression, within the
|
169
196
|
# scope/context of a sandbox. This method is for filter
|
170
197
|
# attribute values starting with "eval:", with the Ruby
|
171
198
|
# expression following the colon. A single variable is provided
|
172
199
|
# to the expression, `value`, equal to the corresponding event
|
173
|
-
# attribute value.
|
174
|
-
#
|
200
|
+
# attribute value. Dot notation tokens in the expression, e.g.
|
201
|
+
# `:::mysql.user:::`, are substituted with the corresponding
|
202
|
+
# event data values prior to evaluation. The expression is
|
203
|
+
# expected to return a boolean value.
|
175
204
|
#
|
205
|
+
# @param event [Hash]
|
176
206
|
# @param raw_eval_string [String] containing the Ruby
|
177
207
|
# expression to be evaluated.
|
178
|
-
# @param
|
208
|
+
# @param raw_value [Object] of the corresponding event
|
209
|
+
# attribute value.
|
179
210
|
# @return [TrueClass, FalseClass]
|
180
|
-
def eval_attribute_value(raw_eval_string,
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
211
|
+
def eval_attribute_value(event, raw_eval_string, raw_value)
|
212
|
+
eval_string = process_eval_string(event, raw_eval_string)
|
213
|
+
unless eval_string.nil?
|
214
|
+
begin
|
215
|
+
value = Marshal.load(Marshal.dump(raw_value))
|
216
|
+
!!Sandbox.eval(eval_string, value)
|
217
|
+
rescue => error
|
218
|
+
@logger.error("filter attribute eval error", {
|
219
|
+
:event => event,
|
220
|
+
:raw_eval_string => raw_eval_string,
|
221
|
+
:raw_value => raw_value,
|
222
|
+
:error => error.to_s
|
223
|
+
})
|
224
|
+
false
|
225
|
+
end
|
226
|
+
else
|
190
227
|
false
|
191
228
|
end
|
192
229
|
end
|
@@ -197,21 +234,23 @@ module Sensu
|
|
197
234
|
# key/value pairs (recursive), have equal string values, or
|
198
235
|
# evaluate to true (Ruby eval).
|
199
236
|
#
|
200
|
-
# @param
|
201
|
-
# @param
|
237
|
+
# @param event [Hash]
|
238
|
+
# @param filter_attributes [Object]
|
239
|
+
# @param event_attributes [Object]
|
202
240
|
# @return [TrueClass, FalseClass]
|
203
|
-
def filter_attributes_match?(
|
204
|
-
|
205
|
-
|
241
|
+
def filter_attributes_match?(event, filter_attributes, event_attributes=nil)
|
242
|
+
event_attributes ||= event
|
243
|
+
filter_attributes.all? do |key, value_one|
|
244
|
+
value_two = event_attributes[key]
|
206
245
|
case
|
207
246
|
when value_one == value_two
|
208
247
|
true
|
209
248
|
when value_one.is_a?(Hash) && value_two.is_a?(Hash)
|
210
|
-
filter_attributes_match?(value_one, value_two)
|
211
|
-
when
|
249
|
+
filter_attributes_match?(event, value_one, value_two)
|
250
|
+
when value_one.to_s == value_two.to_s
|
212
251
|
true
|
213
|
-
when value_one.is_a?(String) && value_one.start_with?(
|
214
|
-
eval_attribute_value(value_one, value_two)
|
252
|
+
when value_one.is_a?(String) && value_one.start_with?(EVAL_PREFIX)
|
253
|
+
eval_attribute_value(event, value_one, value_two)
|
215
254
|
else
|
216
255
|
false
|
217
256
|
end
|
@@ -236,7 +275,7 @@ module Sensu
|
|
236
275
|
case
|
237
276
|
when @settings.filter_exists?(filter_name)
|
238
277
|
filter = @settings[:filters][filter_name]
|
239
|
-
matched = filter_attributes_match?(filter[:attributes]
|
278
|
+
matched = filter_attributes_match?(event, filter[:attributes])
|
240
279
|
yield(filter[:negate] ? matched : !matched)
|
241
280
|
when @extensions.filter_exists?(filter_name)
|
242
281
|
extension = @extensions[:filters][filter_name]
|
data/lib/sensu/server/mutate.rb
CHANGED
@@ -40,7 +40,7 @@ module Sensu
|
|
40
40
|
# @param callback [Proc] to call when the mutator executes
|
41
41
|
# successfully.
|
42
42
|
def pipe_mutator(mutator, event, &callback)
|
43
|
-
options = {:data =>
|
43
|
+
options = {:data => Sensu::JSON.dump(event), :timeout => mutator[:timeout]}
|
44
44
|
block = mutator_callback(mutator, event, &callback)
|
45
45
|
Spawn.process(mutator[:command], options, &block)
|
46
46
|
end
|
data/lib/sensu/server/process.rb
CHANGED
@@ -43,6 +43,20 @@ module Sensu
|
|
43
43
|
@handling_event_count = 0
|
44
44
|
end
|
45
45
|
|
46
|
+
# Set up the Redis and Transport connection objects, `@redis`
|
47
|
+
# and `@transport`. This method "drys" up many instances of
|
48
|
+
# `setup_redis()` and `setup_transport()`.
|
49
|
+
#
|
50
|
+
# @yield callback/block called after connecting to Redis and the
|
51
|
+
# Sensu Transport.
|
52
|
+
def setup_connections
|
53
|
+
setup_redis do
|
54
|
+
setup_transport do
|
55
|
+
yield
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
46
60
|
# Create a registration check definition for a client. Client
|
47
61
|
# definitions may contain `:registration` configuration,
|
48
62
|
# containing custom attributes and handler information. By
|
@@ -127,10 +141,11 @@ module Sensu
|
|
127
141
|
@redis.set(signature_key, client[:signature])
|
128
142
|
end
|
129
143
|
if signature.nil? || signature.empty? || (client[:signature] == signature)
|
130
|
-
@redis.
|
131
|
-
|
132
|
-
|
133
|
-
|
144
|
+
@redis.multi
|
145
|
+
@redis.set(client_key, Sensu::JSON.dump(client))
|
146
|
+
@redis.sadd("clients", client[:name])
|
147
|
+
@redis.exec do
|
148
|
+
yield(true) if block_given?
|
134
149
|
end
|
135
150
|
else
|
136
151
|
@logger.warn("invalid client signature", {
|
@@ -156,11 +171,11 @@ module Sensu
|
|
156
171
|
@transport.subscribe(:direct, "keepalives", "keepalives", :ack => true) do |message_info, message|
|
157
172
|
@logger.debug("received keepalive", :message => message)
|
158
173
|
begin
|
159
|
-
client =
|
174
|
+
client = Sensu::JSON.load(message)
|
160
175
|
update_client_registry(client) do
|
161
176
|
@transport.ack(message_info)
|
162
177
|
end
|
163
|
-
rescue
|
178
|
+
rescue Sensu::JSON::ParseError => error
|
164
179
|
@logger.error("failed to parse keepalive payload", {
|
165
180
|
:message => message,
|
166
181
|
:error => error.to_s
|
@@ -273,20 +288,18 @@ module Sensu
|
|
273
288
|
:check => check
|
274
289
|
})
|
275
290
|
result_set = "#{check[:name]}:#{check[:issued]}"
|
276
|
-
result_data =
|
277
|
-
@redis.
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
severity = (SEVERITIES[check[:status]] || "unknown")
|
282
|
-
@redis.hincrby("aggregate:#{result_set}", severity, 1) do
|
283
|
-
@redis.hincrby("aggregate:#{result_set}", "total", 1) do
|
284
|
-
@redis.sadd("aggregates:#{check[:name]}", check[:issued]) do
|
285
|
-
@redis.sadd("aggregates", check[:name])
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
291
|
+
result_data = Sensu::JSON.dump(:output => check[:output], :status => check[:status])
|
292
|
+
@redis.multi
|
293
|
+
@redis.hset("aggregation:#{result_set}", client[:name], result_data)
|
294
|
+
SEVERITIES.each do |severity|
|
295
|
+
@redis.hsetnx("aggregate:#{result_set}", severity, 0)
|
289
296
|
end
|
297
|
+
severity = (SEVERITIES[check[:status]] || "unknown")
|
298
|
+
@redis.hincrby("aggregate:#{result_set}", severity, 1)
|
299
|
+
@redis.hincrby("aggregate:#{result_set}", "total", 1)
|
300
|
+
@redis.sadd("aggregates:#{check[:name]}", check[:issued])
|
301
|
+
@redis.sadd("aggregates", check[:name])
|
302
|
+
@redis.exec
|
290
303
|
end
|
291
304
|
|
292
305
|
# Truncate check output. For metric checks, (`"type":
|
@@ -301,7 +314,7 @@ module Sensu
|
|
301
314
|
when METRIC_CHECK_TYPE
|
302
315
|
output_lines = check[:output].split("\n")
|
303
316
|
output = output_lines.first || check[:output]
|
304
|
-
if output_lines.
|
317
|
+
if output_lines.length > 1 || output.length > 255
|
305
318
|
output = output[0..255] + "\n..."
|
306
319
|
end
|
307
320
|
check.merge(:output => output)
|
@@ -323,15 +336,16 @@ module Sensu
|
|
323
336
|
# stored (history, etc).
|
324
337
|
def store_check_result(client, check)
|
325
338
|
@logger.debug("storing check result", :check => check)
|
326
|
-
@redis.sadd("result:#{client[:name]}", check[:name])
|
327
339
|
result_key = "#{client[:name]}:#{check[:name]}"
|
340
|
+
history_key = "history:#{result_key}"
|
328
341
|
check_truncated = truncate_check_output(check)
|
329
|
-
@redis.
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
342
|
+
@redis.multi
|
343
|
+
@redis.sadd("result:#{client[:name]}", check[:name])
|
344
|
+
@redis.set("result:#{result_key}", Sensu::JSON.dump(check_truncated))
|
345
|
+
@redis.rpush(history_key, check[:status])
|
346
|
+
@redis.ltrim(history_key, -21, -1)
|
347
|
+
@redis.exec do
|
348
|
+
yield
|
335
349
|
end
|
336
350
|
end
|
337
351
|
|
@@ -355,7 +369,7 @@ module Sensu
|
|
355
369
|
history_key = "history:#{client[:name]}:#{check[:name]}"
|
356
370
|
@redis.lrange(history_key, -21, -1) do |history|
|
357
371
|
total_state_change = 0
|
358
|
-
unless history.
|
372
|
+
unless history.length < 21
|
359
373
|
state_changes = 0
|
360
374
|
change_weight = 0.8
|
361
375
|
previous_status = history.first
|
@@ -427,7 +441,7 @@ module Sensu
|
|
427
441
|
# @yieldparam event [Hash]
|
428
442
|
def update_event_registry(client, check)
|
429
443
|
@redis.hget("events:#{client[:name]}", check[:name]) do |event_json|
|
430
|
-
stored_event = event_json ?
|
444
|
+
stored_event = event_json ? Sensu::JSON.load(event_json) : nil
|
431
445
|
flapping = check_flapping?(stored_event, check)
|
432
446
|
event = {
|
433
447
|
:id => random_uuid,
|
@@ -441,7 +455,7 @@ module Sensu
|
|
441
455
|
if stored_event && check[:status] == stored_event[:check][:status]
|
442
456
|
event[:occurrences] = stored_event[:occurrences] + 1
|
443
457
|
end
|
444
|
-
@redis.hset("events:#{client[:name]}", check[:name],
|
458
|
+
@redis.hset("events:#{client[:name]}", check[:name], Sensu::JSON.dump(event)) do
|
445
459
|
yield(event)
|
446
460
|
end
|
447
461
|
elsif stored_event
|
@@ -498,7 +512,7 @@ module Sensu
|
|
498
512
|
client_key = result[:check][:source] || result[:client]
|
499
513
|
@redis.get("client:#{client_key}") do |client_json|
|
500
514
|
unless client_json.nil?
|
501
|
-
client =
|
515
|
+
client = Sensu::JSON.load(client_json)
|
502
516
|
if client[:signature]
|
503
517
|
if client[:signature] == result[:signature]
|
504
518
|
yield(client)
|
@@ -563,10 +577,10 @@ module Sensu
|
|
563
577
|
@logger.debug("subscribing to results")
|
564
578
|
@transport.subscribe(:direct, "results", "results", :ack => true) do |message_info, message|
|
565
579
|
begin
|
566
|
-
result =
|
580
|
+
result = Sensu::JSON.load(message)
|
567
581
|
@logger.debug("received result", :result => result)
|
568
582
|
process_check_result(result)
|
569
|
-
rescue
|
583
|
+
rescue Sensu::JSON::ParseError => error
|
570
584
|
@logger.error("failed to parse result payload", {
|
571
585
|
:message => message,
|
572
586
|
:error => error.to_s
|
@@ -620,7 +634,7 @@ module Sensu
|
|
620
634
|
:subscribers => check[:subscribers]
|
621
635
|
})
|
622
636
|
check[:subscribers].each do |subscription|
|
623
|
-
options = transport_publish_options(subscription,
|
637
|
+
options = transport_publish_options(subscription, Sensu::JSON.dump(payload))
|
624
638
|
@transport.publish(*options) do |info|
|
625
639
|
if info[:error]
|
626
640
|
@logger.error("failed to publish check request", {
|
@@ -704,7 +718,7 @@ module Sensu
|
|
704
718
|
@redis.get("client:#{client_name}:signature") do |signature|
|
705
719
|
payload[:signature] = signature if signature
|
706
720
|
@logger.debug("publishing check result", :payload => payload)
|
707
|
-
@transport.publish(:direct, "results",
|
721
|
+
@transport.publish(:direct, "results", Sensu::JSON.dump(payload)) do |info|
|
708
722
|
if info[:error]
|
709
723
|
@logger.error("failed to publish check result", {
|
710
724
|
:payload => payload,
|
@@ -758,7 +772,7 @@ module Sensu
|
|
758
772
|
clients.each do |client_name|
|
759
773
|
@redis.get("client:#{client_name}") do |client_json|
|
760
774
|
unless client_json.nil?
|
761
|
-
client =
|
775
|
+
client = Sensu::JSON.load(client_json)
|
762
776
|
next if client[:keepalives] == false
|
763
777
|
check = create_keepalive_check(client)
|
764
778
|
time_since_last_keepalive = Time.now.to_i - client[:timestamp]
|
@@ -810,7 +824,7 @@ module Sensu
|
|
810
824
|
result_key = "#{client_name}:#{check_name}"
|
811
825
|
@redis.get("result:#{result_key}") do |result_json|
|
812
826
|
unless result_json.nil?
|
813
|
-
check =
|
827
|
+
check = Sensu::JSON.load(result_json)
|
814
828
|
next unless check[:ttl] && check[:executed] && !check[:force_resolve]
|
815
829
|
time_since_last_execution = Time.now.to_i - check[:executed]
|
816
830
|
if time_since_last_execution >= check[:ttl]
|
@@ -845,21 +859,21 @@ module Sensu
|
|
845
859
|
@redis.smembers("aggregates") do |checks|
|
846
860
|
checks.each do |check_name|
|
847
861
|
@redis.smembers("aggregates:#{check_name}") do |aggregates|
|
848
|
-
if aggregates.
|
862
|
+
if aggregates.length > 20
|
849
863
|
aggregates.sort!
|
850
|
-
aggregates.take(aggregates.
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
864
|
+
aggregates.take(aggregates.length - 20).each do |check_issued|
|
865
|
+
result_set = "#{check_name}:#{check_issued}"
|
866
|
+
@redis.multi
|
867
|
+
@redis.srem("aggregates:#{check_name}", check_issued)
|
868
|
+
@redis.del("aggregate:#{result_set}")
|
869
|
+
@redis.del("aggregation:#{result_set}")
|
870
|
+
@redis.exec do
|
871
|
+
@logger.debug("pruned aggregation", {
|
872
|
+
:check => {
|
873
|
+
:name => check_name,
|
874
|
+
:issued => check_issued
|
875
|
+
}
|
876
|
+
})
|
863
877
|
end
|
864
878
|
end
|
865
879
|
end
|
@@ -1059,9 +1073,9 @@ module Sensu
|
|
1059
1073
|
# Start the Sensu server process, connecting to Redis, the
|
1060
1074
|
# transport, and calling the `bootstrap()` method.
|
1061
1075
|
def start
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1076
|
+
setup_connections do
|
1077
|
+
bootstrap
|
1078
|
+
end
|
1065
1079
|
end
|
1066
1080
|
|
1067
1081
|
# Pause the Sensu server process, unless it is being paused or
|