sensu 0.17.2 → 0.18.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 +15 -0
- data/lib/sensu/api/process.rb +35 -14
- data/lib/sensu/constants.rb +1 -1
- data/lib/sensu/daemon.rb +1 -1
- data/lib/sensu/server/process.rb +83 -42
- data/sensu.gemspec +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3562490d63bf32fe403bb3395f673b9be6ffd4e4
|
4
|
+
data.tar.gz: ba043f59f239c29b9d8353d29ca892c6a3400384
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0aae29a7af64355686413c1a4d6f108a1c59276312f31755065a5901faf5a5c508a9514b04e98e9942a651877b1d375a8ab9e3a6ba75e461310dded889c35b50
|
7
|
+
data.tar.gz: d0cbbbd0000a734f411a4cdc5a396a40bb281cfcdbd77b009bc61365045de95eef0937a2ff169b25c76cea89b3371cb56a2779cfad31a817d04cccee0b2f57da
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## 0.18.0 - TBD
|
2
|
+
|
3
|
+
### Features
|
4
|
+
|
5
|
+
Dynamic (or JIT) client creation (in the registry) for check results for a
|
6
|
+
nonexistent client or a check source. Sensu clients can now monitor an
|
7
|
+
external resource on its behalf, using a check `source` to create a JIT
|
8
|
+
client for the resource, used to store the execution history and provide
|
9
|
+
context within event data. JIT client data in the registry can be
|
10
|
+
managed/updated via the Sensu API, POST `/clients`.
|
11
|
+
|
12
|
+
Storing the latest check result for every client/check pair. This data is
|
13
|
+
currently exposed via the API at `/clients/:client/history` and will be
|
14
|
+
used by several upcoming features.
|
15
|
+
|
1
16
|
## 0.17.2 - 2015-04-08
|
2
17
|
|
3
18
|
### Other
|
data/lib/sensu/api/process.rb
CHANGED
@@ -170,7 +170,9 @@ module Sensu
|
|
170
170
|
begin
|
171
171
|
data = MultiJson.load(env["rack.input"].read)
|
172
172
|
valid = rules.all? do |key, rule|
|
173
|
-
|
173
|
+
value = data[key]
|
174
|
+
(value.is_a?(rule[:type]) || (rule[:nil_ok] && value.nil?)) &&
|
175
|
+
rule[:regex].nil? || (rule[:regex] && (value =~ rule[:regex]) == 0)
|
174
176
|
end
|
175
177
|
if valid
|
176
178
|
callback.call(data)
|
@@ -302,6 +304,23 @@ module Sensu
|
|
302
304
|
end
|
303
305
|
end
|
304
306
|
|
307
|
+
apost "/clients/?" do
|
308
|
+
rules = {
|
309
|
+
:name => {:type => String, :nil_ok => false, :regex => /^[\w\.-]+$/},
|
310
|
+
:address => {:type => String, :nil_ok => false},
|
311
|
+
:subscriptions => {:type => Array, :nil_ok => false}
|
312
|
+
}
|
313
|
+
read_data(rules) do |data|
|
314
|
+
data[:keepalives] = false
|
315
|
+
data[:timestamp] = Time.now.to_i
|
316
|
+
settings.redis.set("client:#{data[:name]}", MultiJson.dump(data)) do
|
317
|
+
settings.redis.sadd("clients", data[:name]) do
|
318
|
+
created!(MultiJson.dump(:name => data[:name]))
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
305
324
|
aget "/clients/?" do
|
306
325
|
response = Array.new
|
307
326
|
settings.redis.smembers("clients") do |clients|
|
@@ -333,22 +352,25 @@ module Sensu
|
|
333
352
|
|
334
353
|
aget %r{/clients/([\w\.-]+)/history/?$} do |client_name|
|
335
354
|
response = Array.new
|
336
|
-
settings.redis.smembers("
|
355
|
+
settings.redis.smembers("result:#{client_name}") do |checks|
|
337
356
|
unless checks.empty?
|
338
357
|
checks.each_with_index do |check_name, index|
|
339
|
-
|
358
|
+
result_key = "#{client_name}:#{check_name}"
|
359
|
+
history_key = "history:#{result_key}"
|
340
360
|
settings.redis.lrange(history_key, -21, -1) do |history|
|
341
361
|
history.map! do |status|
|
342
362
|
status.to_i
|
343
363
|
end
|
344
|
-
|
345
|
-
|
364
|
+
settings.redis.get("result:#{result_key}") do |result_json|
|
365
|
+
result = MultiJson.load(result_json)
|
366
|
+
last_execution = result[:executed]
|
346
367
|
unless history.empty? || last_execution.nil?
|
347
368
|
item = {
|
348
369
|
:check => check_name,
|
349
370
|
:history => history,
|
350
371
|
:last_execution => last_execution.to_i,
|
351
|
-
:last_status => history.last
|
372
|
+
:last_status => history.last,
|
373
|
+
:last_result => result
|
352
374
|
}
|
353
375
|
response << item
|
354
376
|
end
|
@@ -373,18 +395,17 @@ module Sensu
|
|
373
395
|
end
|
374
396
|
EM::Timer.new(5) do
|
375
397
|
client = MultiJson.load(client_json)
|
376
|
-
settings.logger.info("deleting client",
|
377
|
-
:client => client
|
378
|
-
})
|
398
|
+
settings.logger.info("deleting client", :client => client)
|
379
399
|
settings.redis.srem("clients", client_name) do
|
380
400
|
settings.redis.del("client:#{client_name}")
|
381
401
|
settings.redis.del("events:#{client_name}")
|
382
|
-
settings.redis.smembers("
|
402
|
+
settings.redis.smembers("result:#{client_name}") do |checks|
|
383
403
|
checks.each do |check_name|
|
384
|
-
|
385
|
-
settings.redis.del("
|
404
|
+
result_key = "#{client_name}:#{check_name}"
|
405
|
+
settings.redis.del("result:#{result_key}")
|
406
|
+
settings.redis.del("history:#{result_key}")
|
386
407
|
end
|
387
|
-
settings.redis.del("
|
408
|
+
settings.redis.del("result:#{client_name}")
|
388
409
|
end
|
389
410
|
end
|
390
411
|
end
|
@@ -428,7 +449,7 @@ module Sensu
|
|
428
449
|
:subscribers => subscribers
|
429
450
|
})
|
430
451
|
subscribers.uniq.each do |exchange_name|
|
431
|
-
settings.transport.publish(:fanout, exchange_name, MultiJson.dump(payload)) do |info|
|
452
|
+
settings.transport.publish(:fanout, exchange_name.to_s, MultiJson.dump(payload)) do |info|
|
432
453
|
if info[:error]
|
433
454
|
settings.logger.error("failed to publish check request", {
|
434
455
|
:exchange_name => exchange_name,
|
data/lib/sensu/constants.rb
CHANGED
data/lib/sensu/daemon.rb
CHANGED
data/lib/sensu/server/process.rb
CHANGED
@@ -49,7 +49,7 @@ module Sensu
|
|
49
49
|
@logger.debug("updating client registry", :client => client)
|
50
50
|
@redis.set("client:#{client[:name]}", MultiJson.dump(client)) do
|
51
51
|
@redis.sadd("clients", client[:name]) do
|
52
|
-
callback.call
|
52
|
+
callback.call(client)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -178,13 +178,16 @@ module Sensu
|
|
178
178
|
# check execution across a number of Sensu clients. JSON
|
179
179
|
# serialization is used for storing check result data.
|
180
180
|
#
|
181
|
-
# @param
|
182
|
-
|
183
|
-
|
184
|
-
check
|
181
|
+
# @param client [Hash]
|
182
|
+
# @param check [Hash]
|
183
|
+
def aggregate_check_result(client, check)
|
184
|
+
@logger.debug("adding check result to aggregate", {
|
185
|
+
:client => client,
|
186
|
+
:check => check
|
187
|
+
})
|
185
188
|
result_set = "#{check[:name]}:#{check[:issued]}"
|
186
189
|
result_data = MultiJson.dump(:output => check[:output], :status => check[:status])
|
187
|
-
@redis.hset("aggregation:#{result_set}",
|
190
|
+
@redis.hset("aggregation:#{result_set}", client[:name], result_data) do
|
188
191
|
SEVERITIES.each do |severity|
|
189
192
|
@redis.hsetnx("aggregate:#{result_set}", severity, 0)
|
190
193
|
end
|
@@ -199,31 +202,34 @@ module Sensu
|
|
199
202
|
end
|
200
203
|
end
|
201
204
|
|
202
|
-
# Store check result data. This method stores
|
203
|
-
# check result statuses for a client/check
|
204
|
-
# is used for event context and flap detection.
|
205
|
-
# execution timestamp is also stored, to provide an
|
206
|
-
# of how recent the data is.
|
205
|
+
# Store check result data. This method stores check result data
|
206
|
+
# and the 21 most recent check result statuses for a client/check
|
207
|
+
# pair, this history is used for event context and flap detection.
|
208
|
+
# The check execution timestamp is also stored, to provide an
|
209
|
+
# indication of how recent the data is.
|
207
210
|
#
|
208
211
|
# @param client [Hash]
|
209
212
|
# @param check [Hash]
|
210
213
|
# @param callback [Proc] to call when the check result data has
|
211
214
|
# been stored (history, etc).
|
212
215
|
def store_check_result(client, check, &callback)
|
213
|
-
@
|
216
|
+
@logger.debug("storing check result", :check => check)
|
217
|
+
@redis.sadd("result:#{client[:name]}", check[:name])
|
214
218
|
result_key = "#{client[:name]}:#{check[:name]}"
|
215
|
-
|
216
|
-
@redis.
|
217
|
-
|
218
|
-
@redis.
|
219
|
-
|
219
|
+
check_truncated = check.merge(:output => check[:output][0..256])
|
220
|
+
@redis.set("result:#{result_key}", MultiJson.dump(check_truncated)) do
|
221
|
+
history_key = "history:#{result_key}"
|
222
|
+
@redis.rpush(history_key, check[:status]) do
|
223
|
+
@redis.ltrim(history_key, -21, -1)
|
224
|
+
callback.call
|
225
|
+
end
|
220
226
|
end
|
221
227
|
end
|
222
228
|
|
223
229
|
# Fetch the execution history for a client/check pair, the 21
|
224
230
|
# most recent check result statuses. This method also calculates
|
225
231
|
# the total state change percentage for the history, this value
|
226
|
-
# is use for check state
|
232
|
+
# is use for check state flap detection, using a similar
|
227
233
|
# algorithm to Nagios:
|
228
234
|
# http://nagios.sourceforge.net/docs/3_0/flapping.html
|
229
235
|
#
|
@@ -332,39 +338,73 @@ module Sensu
|
|
332
338
|
end
|
333
339
|
end
|
334
340
|
|
341
|
+
# Create a blank client (data) and add it to the client
|
342
|
+
# registry. Only the client name is known, the other client
|
343
|
+
# attributes must be updated via the API (POST /clients:client).
|
344
|
+
# Dynamically created clients and those updated via the API will
|
345
|
+
# have client keepalives disabled, `:keepalives` is set to
|
346
|
+
# `false`.
|
347
|
+
#
|
348
|
+
# @param name [Hash] to use for the client.
|
349
|
+
# @param callback [Proc] to be called with the dynamically
|
350
|
+
# created client data.
|
351
|
+
def create_client(name, &callback)
|
352
|
+
client = {
|
353
|
+
:name => name,
|
354
|
+
:address => "unknown",
|
355
|
+
:subscriptions => [],
|
356
|
+
:keepalives => false
|
357
|
+
}
|
358
|
+
update_client_registry(client, &callback)
|
359
|
+
end
|
360
|
+
|
361
|
+
# Retrieve a client (data) from Redis if it exists. If a client
|
362
|
+
# does not already exist, create one (a blank) using the
|
363
|
+
# `client_key` as the client name. Dynamically create client
|
364
|
+
# data can be updated using the API (POST /clients/:client).
|
365
|
+
#
|
366
|
+
# @param result [Hash] data.
|
367
|
+
# @param callback [Proc] to be called with client data, either
|
368
|
+
# retrieved from Redis, or dynamically created.
|
369
|
+
def retrieve_client(result, &callback)
|
370
|
+
client_key = result[:check][:source] || result[:client]
|
371
|
+
@redis.get("client:#{client_key}") do |client_json|
|
372
|
+
unless client_json.nil?
|
373
|
+
client = MultiJson.load(client_json)
|
374
|
+
callback.call(client)
|
375
|
+
else
|
376
|
+
create_client(client_key, &callback)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
335
381
|
# Process a check result, storing its data, inspecting its
|
336
382
|
# contents, and taking the appropriate actions (eg. update the
|
337
383
|
# event registry). A check result must have a valid client name,
|
338
|
-
# associated with a client in the registry
|
339
|
-
#
|
340
|
-
#
|
341
|
-
#
|
342
|
-
# merged with the check result for more context.
|
384
|
+
# associated with a client in the registry or one will be
|
385
|
+
# created. If a local check definition exists for the check
|
386
|
+
# name, and the check result is not from a standalone check
|
387
|
+
# execution, it's merged with the check result for more context.
|
343
388
|
#
|
344
389
|
# @param result [Hash] data.
|
345
390
|
def process_check_result(result)
|
346
391
|
@logger.debug("processing result", :result => result)
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
check
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
update_event_registry(client, check) do |event|
|
362
|
-
process_event(event)
|
363
|
-
end
|
392
|
+
retrieve_client(result) do |client|
|
393
|
+
check = case
|
394
|
+
when @settings.check_exists?(result[:check][:name]) && !result[:check][:standalone]
|
395
|
+
@settings[:checks][result[:check][:name]].merge(result[:check])
|
396
|
+
else
|
397
|
+
result[:check]
|
398
|
+
end
|
399
|
+
aggregate_check_result(client, check) if check[:aggregate]
|
400
|
+
store_check_result(client, check) do
|
401
|
+
check_history(client, check) do |history, total_state_change|
|
402
|
+
check[:history] = history
|
403
|
+
check[:total_state_change] = total_state_change
|
404
|
+
update_event_registry(client, check) do |event|
|
405
|
+
process_event(event)
|
364
406
|
end
|
365
407
|
end
|
366
|
-
else
|
367
|
-
@logger.warn("client not in registry", :client => result[:client])
|
368
408
|
end
|
369
409
|
end
|
370
410
|
end
|
@@ -549,6 +589,7 @@ module Sensu
|
|
549
589
|
@redis.get("client:#{client_name}") do |client_json|
|
550
590
|
unless client_json.nil?
|
551
591
|
client = MultiJson.load(client_json)
|
592
|
+
next if client[:keepalives] == false
|
552
593
|
check = create_keepalive_check(client)
|
553
594
|
time_since_last_keepalive = Time.now.to_i - client[:timestamp]
|
554
595
|
check[:output] = "No keepalive sent from client for "
|
data/sensu.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_dependency "eventmachine", "1.0.3"
|
20
20
|
s.add_dependency "sensu-em", "2.4.1"
|
21
21
|
s.add_dependency "sensu-logger", "1.0.0"
|
22
|
-
s.add_dependency "sensu-settings", "1.
|
22
|
+
s.add_dependency "sensu-settings", "1.4.0"
|
23
23
|
s.add_dependency "sensu-extension", "1.1.2"
|
24
24
|
s.add_dependency "sensu-extensions", "1.2.0"
|
25
25
|
s.add_dependency "sensu-transport", "2.4.0"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.0.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Porter
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-04-
|
12
|
+
date: 2015-04-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|
@@ -87,14 +87,14 @@ dependencies:
|
|
87
87
|
requirements:
|
88
88
|
- - '='
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: 1.
|
90
|
+
version: 1.4.0
|
91
91
|
type: :runtime
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - '='
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: 1.
|
97
|
+
version: 1.4.0
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: sensu-extension
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -297,9 +297,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
297
297
|
version: '0'
|
298
298
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
299
299
|
requirements:
|
300
|
-
- - "
|
300
|
+
- - ">"
|
301
301
|
- !ruby/object:Gem::Version
|
302
|
-
version:
|
302
|
+
version: 1.3.1
|
303
303
|
requirements: []
|
304
304
|
rubyforge_project:
|
305
305
|
rubygems_version: 2.2.2
|