sensu 0.22.2 → 0.23.0.beta
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 +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
|