sensu 0.17.2 → 0.18.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 +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
|