sensu 0.9.5 → 0.9.6.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.
- data/README.org +8 -42
- data/bin/sensu-api +5 -2
- data/bin/sensu-client +5 -2
- data/bin/sensu-server +5 -2
- data/lib/sensu/api.rb +125 -95
- data/lib/sensu/base.rb +57 -0
- data/lib/sensu/cli.rb +37 -0
- data/lib/sensu/client.rb +126 -129
- data/lib/sensu/constants.rb +8 -0
- data/lib/sensu/logger.rb +39 -0
- data/lib/sensu/patches/ruby.rb +4 -80
- data/lib/sensu/process.rb +57 -0
- data/lib/sensu/server.rb +229 -163
- data/lib/sensu/settings.rb +280 -0
- data/lib/sensu/socket.rb +52 -0
- data/sensu.gemspec +22 -23
- metadata +171 -185
- data/lib/sensu/config.rb +0 -266
- data/lib/sensu/version.rb +0 -3
data/README.org
CHANGED
@@ -1,46 +1,12 @@
|
|
1
|
-
*
|
2
|
-
|
1
|
+
* Sensu
|
2
|
+
A monitoring framework that aims to be simple, malleable, and scalable.
|
3
3
|
|
4
|
-
[[https://github.com/
|
4
|
+
[[https://github.com/sensu/sensu/raw/master/sensu-logo.png]]
|
5
5
|
|
6
|
-
[[
|
6
|
+
[[https://secure.travis-ci.org/sensu/sensu.png]]
|
7
7
|
|
8
|
-
[[
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
- [[http://joemiller.me/2012/01/24/re-use-nagios-plugins-in-sensu-for-quick-profit/][How to reuse your existing Nagios plugins]]
|
13
|
-
- [[http://joemiller.me/2012/02/02/sensu-and-graphite/][Sensu and Graphite]]
|
14
|
-
* Other Projects
|
15
|
-
- [[https://github.com/sonian/sensu-community-plugins][Sensu Community Plugins]]
|
16
|
-
- [[https://github.com/sonian/sensu-dashboard][Sensu Dashboard]]
|
17
|
-
- [[https://github.com/sonian/sensu-plugin][Sensu Plugin & Handler Helper]]
|
18
|
-
* License
|
8
|
+
[[https://gemnasium.com/portertech/sensu.png]]
|
9
|
+
** Documentation
|
10
|
+
Please refer to the [[https://github.com/sensu/sensu/wiki][Sensu Wiki]].
|
11
|
+
** License
|
19
12
|
Sensu is released under the [[https://github.com/sonian/sensu/blob/master/MIT-LICENSE.txt][MIT license]].
|
20
|
-
* Contributing
|
21
|
-
- [[http://help.github.com/fork-a-repo/][Fork]] Sensu
|
22
|
-
- Use a [[https://github.com/dchelimsky/rspec/wiki/Topic-Branches][topic branch]]
|
23
|
-
- Create a [[http://help.github.com/send-pull-requests/][pull request]]
|
24
|
-
|
25
|
-
Keep it simple.
|
26
|
-
** Testing
|
27
|
-
*** Travis CI
|
28
|
-
[[https://secure.travis-ci.org/sonian/sensu.png]]
|
29
|
-
*** System Dependencies
|
30
|
-
- Ruby (MRI) & Rubygems
|
31
|
-
- RabbitMQ
|
32
|
-
- Redis
|
33
|
-
*** Running
|
34
|
-
: bundle install
|
35
|
-
: rake
|
36
|
-
* Contributors
|
37
|
-
- [[http://twitter.com/portertech][Sean Porter]]
|
38
|
-
- [[http://twitter.com/amdprophet][Justin Kolberg]]
|
39
|
-
- [[http://twitter.com/kartar][James Turnbull]]
|
40
|
-
- [[http://twitter.com/joshpasqualetto][Josh Pasqualetto]]
|
41
|
-
- [[http://github.com/lum][Steve Lum]]
|
42
|
-
- [[http://twitter.com/miller_joe][Joe Miller]]
|
43
|
-
- [[http://twitter.com/decklin][Decklin Foster]]
|
44
|
-
- [[http://twitter.com/ohlol][Scott Smith]]
|
45
|
-
- [[http://twitter.com/webframp][Sean Escriva]]
|
46
|
-
- [[http://twitter.com/fujin_][AJ Christensen]]
|
data/bin/sensu-api
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
unless $:.include?(File.dirname(__FILE__) + '/../lib/')
|
4
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
5
|
+
end
|
6
|
+
|
4
7
|
require 'sensu/api'
|
5
8
|
|
6
|
-
options = Sensu::
|
9
|
+
options = Sensu::CLI.read
|
7
10
|
Sensu::API.run(options)
|
data/bin/sensu-client
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
unless $:.include?(File.dirname(__FILE__) + '/../lib/')
|
4
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
5
|
+
end
|
6
|
+
|
4
7
|
require 'sensu/client'
|
5
8
|
|
6
|
-
options = Sensu::
|
9
|
+
options = Sensu::CLI.read
|
7
10
|
Sensu::Client.run(options)
|
data/bin/sensu-server
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
unless $:.include?(File.dirname(__FILE__) + '/../lib/')
|
4
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
5
|
+
end
|
6
|
+
|
4
7
|
require 'sensu/server'
|
5
8
|
|
6
|
-
options = Sensu::
|
9
|
+
options = Sensu::CLI.read
|
7
10
|
Sensu::Server.run(options)
|
data/lib/sensu/api.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '
|
1
|
+
require File.join(File.dirname(__FILE__), 'base')
|
2
2
|
|
3
3
|
require 'thin'
|
4
4
|
require 'sinatra/async'
|
@@ -15,7 +15,7 @@ module Sensu
|
|
15
15
|
self.setup(options)
|
16
16
|
|
17
17
|
Thin::Logging.silent = true
|
18
|
-
Thin::Server.start(self, $settings
|
18
|
+
Thin::Server.start(self, $settings[:api][:port])
|
19
19
|
|
20
20
|
%w[INT TERM].each do |signal|
|
21
21
|
Signal.trap(signal) do
|
@@ -26,27 +26,36 @@ module Sensu
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.setup(options={})
|
29
|
-
|
30
|
-
$logger =
|
31
|
-
$settings =
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
$
|
40
|
-
$logger.debug('[setup] -- connecting to rabbitmq')
|
41
|
-
$rabbitmq = AMQP.connect($settings.rabbitmq.to_hash.symbolize_keys)
|
29
|
+
base = Sensu::Base.new(options)
|
30
|
+
$logger = base.logger
|
31
|
+
$settings = base.settings
|
32
|
+
$logger.debug('connecting to redis', {
|
33
|
+
:settings => $settings[:redis]
|
34
|
+
})
|
35
|
+
$redis = Redis.connect($settings[:redis])
|
36
|
+
$logger.debug('connecting to rabbitmq', {
|
37
|
+
:settings => $settings[:rabbitmq]
|
38
|
+
})
|
39
|
+
$rabbitmq = AMQP.connect($settings[:rabbitmq])
|
42
40
|
$amq = AMQP::Channel.new($rabbitmq)
|
43
|
-
if $settings
|
41
|
+
if $settings[:api][:user] && $settings[:api][:password]
|
44
42
|
use Rack::Auth::Basic do |user, password|
|
45
|
-
user == $settings
|
43
|
+
user == $settings[:api][:user] && password == $settings[:api][:password]
|
46
44
|
end
|
47
45
|
end
|
48
46
|
end
|
49
47
|
|
48
|
+
def request_log(env)
|
49
|
+
$logger.info([env['REQUEST_METHOD'], env['REQUEST_PATH']].join(' '), {
|
50
|
+
:remote_address => env['REMOTE_ADDR'],
|
51
|
+
:user_agent => env['HTTP_USER_AGENT'],
|
52
|
+
:request_method => env['REQUEST_METHOD'],
|
53
|
+
:request_uri => env['REQUEST_URI'],
|
54
|
+
:request_body => env['rack.input'].read
|
55
|
+
})
|
56
|
+
env['rack.input'].rewind
|
57
|
+
end
|
58
|
+
|
50
59
|
configure do
|
51
60
|
disable :protection
|
52
61
|
end
|
@@ -60,10 +69,10 @@ module Sensu
|
|
60
69
|
end
|
61
70
|
|
62
71
|
aget '/info' do
|
63
|
-
|
72
|
+
request_log(env)
|
64
73
|
response = {
|
65
74
|
:sensu => {
|
66
|
-
:version =>
|
75
|
+
:version => VERSION
|
67
76
|
},
|
68
77
|
:health => {
|
69
78
|
:redis => 'ok',
|
@@ -80,12 +89,12 @@ module Sensu
|
|
80
89
|
end
|
81
90
|
|
82
91
|
aget '/clients' do
|
83
|
-
|
92
|
+
request_log(env)
|
84
93
|
response = Array.new
|
85
94
|
$redis.smembers('clients').callback do |clients|
|
86
95
|
unless clients.empty?
|
87
|
-
clients.each_with_index do |
|
88
|
-
$redis.get('client:' +
|
96
|
+
clients.each_with_index do |client_name, index|
|
97
|
+
$redis.get('client:' + client_name).callback do |client_json|
|
89
98
|
response.push(JSON.parse(client_json))
|
90
99
|
if index == clients.size - 1
|
91
100
|
body response.to_json
|
@@ -98,9 +107,9 @@ module Sensu
|
|
98
107
|
end
|
99
108
|
end
|
100
109
|
|
101
|
-
aget '/client/:name' do |
|
102
|
-
|
103
|
-
$redis.get('client:' +
|
110
|
+
aget '/client/:name' do |client_name|
|
111
|
+
request_log(env)
|
112
|
+
$redis.get('client:' + client_name).callback do |client_json|
|
104
113
|
unless client_json.nil?
|
105
114
|
body client_json
|
106
115
|
else
|
@@ -110,30 +119,37 @@ module Sensu
|
|
110
119
|
end
|
111
120
|
end
|
112
121
|
|
113
|
-
adelete '/client/:name' do |
|
114
|
-
|
115
|
-
$redis.
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
:
|
125
|
-
:
|
122
|
+
adelete '/client/:name' do |client_name|
|
123
|
+
request_log(env)
|
124
|
+
$redis.get('client:' + client_name).callback do |client_json|
|
125
|
+
unless client_json.nil?
|
126
|
+
client = JSON.parse(client_json, :symbolize_names => true)
|
127
|
+
$logger.info('deleting client', {
|
128
|
+
:client => client
|
129
|
+
})
|
130
|
+
$redis.hgetall('events:' + client_name).callback do |events|
|
131
|
+
events.each_key do |check_name|
|
132
|
+
payload = {
|
133
|
+
:client => client_name,
|
134
|
+
:check => {
|
135
|
+
:name => check_name,
|
136
|
+
:output => 'Client is being removed on request of the API',
|
137
|
+
:status => 0,
|
138
|
+
:issued => Time.now.to_i,
|
139
|
+
:force_resolve => true
|
140
|
+
}
|
126
141
|
}
|
127
|
-
$
|
142
|
+
$logger.info('publishing check result', {
|
143
|
+
:payload => payload
|
144
|
+
})
|
145
|
+
$amq.queue('results').publish(payload.to_json)
|
128
146
|
end
|
129
|
-
$logger.info('[client] -- client will be deleted -- ' + client)
|
130
147
|
EM::Timer.new(5) do
|
131
|
-
$
|
132
|
-
$redis.
|
133
|
-
$redis.del('
|
134
|
-
$
|
135
|
-
|
136
|
-
$redis.del('history:' + client + ':' + check_name)
|
148
|
+
$redis.srem('clients', client_name)
|
149
|
+
$redis.del('events:' + client_name)
|
150
|
+
$redis.del('client:' + client_name)
|
151
|
+
$settings[:checks].each_key do |check_name|
|
152
|
+
$redis.del('history:' + client_name + ':' + check_name)
|
137
153
|
end
|
138
154
|
end
|
139
155
|
status 204
|
@@ -147,15 +163,14 @@ module Sensu
|
|
147
163
|
end
|
148
164
|
|
149
165
|
aget '/checks' do
|
150
|
-
|
151
|
-
|
152
|
-
body response.to_json
|
166
|
+
request_log(env)
|
167
|
+
body $settings.checks.to_json
|
153
168
|
end
|
154
169
|
|
155
|
-
aget '/check/:name' do |
|
156
|
-
|
157
|
-
if $settings.
|
158
|
-
response = $settings
|
170
|
+
aget '/check/:name' do |check_name|
|
171
|
+
request_log(env)
|
172
|
+
if $settings.check_exists?(check_name)
|
173
|
+
response = $settings[:checks][check_name].merge(:name => check_name)
|
159
174
|
body response.to_json
|
160
175
|
else
|
161
176
|
status 404
|
@@ -164,17 +179,24 @@ module Sensu
|
|
164
179
|
end
|
165
180
|
|
166
181
|
apost '/check/request' do
|
167
|
-
|
182
|
+
request_log(env)
|
168
183
|
begin
|
169
|
-
post_body =
|
184
|
+
post_body = JSON.parse(request.body.read, :symbolize_names => true)
|
170
185
|
rescue JSON::ParserError
|
171
186
|
status 400
|
172
187
|
body ''
|
173
188
|
end
|
174
|
-
if post_body
|
175
|
-
|
176
|
-
|
177
|
-
|
189
|
+
if post_body[:check].is_a?(String) && post_body[:subscribers].is_a?(Array)
|
190
|
+
payload = {
|
191
|
+
:name => post_body[:check],
|
192
|
+
:issued => Time.now.to_i
|
193
|
+
}
|
194
|
+
$logger.info('publishing check request', {
|
195
|
+
:payload => payload,
|
196
|
+
:subscribers => post_body[:subscribers]
|
197
|
+
})
|
198
|
+
post_body[:subscribers].uniq.each do |exchange_name|
|
199
|
+
$amq.fanout(exchange_name).publish(payload.to_json)
|
178
200
|
end
|
179
201
|
status 201
|
180
202
|
else
|
@@ -184,14 +206,14 @@ module Sensu
|
|
184
206
|
end
|
185
207
|
|
186
208
|
aget '/events' do
|
187
|
-
|
209
|
+
request_log(env)
|
188
210
|
response = Array.new
|
189
211
|
$redis.smembers('clients').callback do |clients|
|
190
212
|
unless clients.empty?
|
191
|
-
clients.each_with_index do |
|
192
|
-
$redis.hgetall('events:' +
|
193
|
-
events.each do |
|
194
|
-
response.push(JSON.parse(
|
213
|
+
clients.each_with_index do |client_name, index|
|
214
|
+
$redis.hgetall('events:' + client_name).callback do |events|
|
215
|
+
events.each do |check_name, event_json|
|
216
|
+
response.push(JSON.parse(event_json).merge(:client => client_name, :check => check_name))
|
195
217
|
end
|
196
218
|
if index == clients.size - 1
|
197
219
|
body response.to_json
|
@@ -204,12 +226,12 @@ module Sensu
|
|
204
226
|
end
|
205
227
|
end
|
206
228
|
|
207
|
-
aget '/event/:client/:check' do |
|
208
|
-
|
209
|
-
$redis.hgetall('events:' +
|
210
|
-
event_json = events[
|
229
|
+
aget '/event/:client/:check' do |client_name, check_name|
|
230
|
+
request_log(env)
|
231
|
+
$redis.hgetall('events:' + client_name).callback do |events|
|
232
|
+
event_json = events[check_name]
|
211
233
|
unless event_json.nil?
|
212
|
-
response = JSON.parse(event_json).merge(:client =>
|
234
|
+
response = JSON.parse(event_json).merge(:client => client_name, :check => check_name)
|
213
235
|
body response.to_json
|
214
236
|
else
|
215
237
|
status 404
|
@@ -219,25 +241,30 @@ module Sensu
|
|
219
241
|
end
|
220
242
|
|
221
243
|
apost '/event/resolve' do
|
222
|
-
|
244
|
+
request_log(env)
|
223
245
|
begin
|
224
|
-
post_body =
|
246
|
+
post_body = JSON.parse(request.body.read, :symbolize_names => true)
|
225
247
|
rescue JSON::ParserError
|
226
248
|
status 400
|
227
249
|
body ''
|
228
250
|
end
|
229
|
-
if post_body
|
230
|
-
$redis.hgetall('events:' + post_body
|
231
|
-
if events.include?(post_body
|
232
|
-
|
233
|
-
|
234
|
-
:
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
251
|
+
if post_body[:client].is_a?(String) && post_body[:check].is_a?(String)
|
252
|
+
$redis.hgetall('events:' + post_body[:client]).callback do |events|
|
253
|
+
if events.include?(post_body[:check])
|
254
|
+
payload = {
|
255
|
+
:client => post_body[:client],
|
256
|
+
:check => {
|
257
|
+
:name => post_body[:check],
|
258
|
+
:output => 'Resolving on request of the API',
|
259
|
+
:status => 0,
|
260
|
+
:issued => Time.now.to_i,
|
261
|
+
:force_resolve => true
|
262
|
+
}
|
239
263
|
}
|
240
|
-
$
|
264
|
+
$logger.info('publishing check result', {
|
265
|
+
:payload => payload
|
266
|
+
})
|
267
|
+
$amq.queue('results').publish(payload.to_json)
|
241
268
|
status 201
|
242
269
|
else
|
243
270
|
status 404
|
@@ -251,7 +278,7 @@ module Sensu
|
|
251
278
|
end
|
252
279
|
|
253
280
|
apost '/stash/*' do |path|
|
254
|
-
|
281
|
+
request_log(env)
|
255
282
|
begin
|
256
283
|
post_body = JSON.parse(request.body.read)
|
257
284
|
rescue JSON::ParserError
|
@@ -267,7 +294,7 @@ module Sensu
|
|
267
294
|
end
|
268
295
|
|
269
296
|
aget '/stash/*' do |path|
|
270
|
-
|
297
|
+
request_log(env)
|
271
298
|
$redis.get('stash:' + path).callback do |stash_json|
|
272
299
|
if stash_json.nil?
|
273
300
|
status 404
|
@@ -279,7 +306,7 @@ module Sensu
|
|
279
306
|
end
|
280
307
|
|
281
308
|
adelete '/stash/*' do |path|
|
282
|
-
|
309
|
+
request_log(env)
|
283
310
|
$redis.exists('stash:' + path).callback do |stash_exists|
|
284
311
|
if stash_exists
|
285
312
|
$redis.srem('stashes', path).callback do
|
@@ -296,14 +323,14 @@ module Sensu
|
|
296
323
|
end
|
297
324
|
|
298
325
|
aget '/stashes' do
|
299
|
-
|
326
|
+
request_log(env)
|
300
327
|
$redis.smembers('stashes') do |stashes|
|
301
328
|
body stashes.to_json
|
302
329
|
end
|
303
330
|
end
|
304
331
|
|
305
332
|
apost '/stashes' do
|
306
|
-
|
333
|
+
request_log(env)
|
307
334
|
begin
|
308
335
|
post_body = JSON.parse(request.body.read)
|
309
336
|
rescue JSON::ParserError
|
@@ -330,20 +357,20 @@ module Sensu
|
|
330
357
|
|
331
358
|
def self.run_test(options={}, &block)
|
332
359
|
self.setup(options)
|
333
|
-
$settings
|
334
|
-
$redis.set('client:' + $settings
|
335
|
-
$redis.sadd('clients', $settings
|
336
|
-
$redis.hset('events:' + $settings
|
360
|
+
$settings[:client][:timestamp] = Time.now.to_i
|
361
|
+
$redis.set('client:' + $settings[:client][:name], $settings[:client].to_json).callback do
|
362
|
+
$redis.sadd('clients', $settings[:client][:name]).callback do
|
363
|
+
$redis.hset('events:' + $settings[:client][:name], 'test', {
|
337
364
|
:output => "CRITICAL\n",
|
338
365
|
:status => 2,
|
339
|
-
:issued => Time.now.
|
366
|
+
:issued => Time.now.to_i,
|
340
367
|
:flapping => false,
|
341
368
|
:occurrences => 1
|
342
369
|
}.to_json).callback do
|
343
370
|
$redis.set('stash:test/test', '{"key": "value"}').callback do
|
344
371
|
$redis.sadd('stashes', 'test/test').callback do
|
345
372
|
Thin::Logging.silent = true
|
346
|
-
Thin::Server.start(self, $settings
|
373
|
+
Thin::Server.start(self, $settings[:api][:port])
|
347
374
|
block.call
|
348
375
|
end
|
349
376
|
end
|
@@ -353,8 +380,11 @@ module Sensu
|
|
353
380
|
end
|
354
381
|
|
355
382
|
def self.stop(signal)
|
356
|
-
$logger.warn('
|
357
|
-
|
383
|
+
$logger.warn('received signal', {
|
384
|
+
:signal => signal
|
385
|
+
})
|
386
|
+
$logger.warn('stopping')
|
387
|
+
$logger.warn('stopping reactor')
|
358
388
|
EM::PeriodicTimer.new(0.25) do
|
359
389
|
EM::stop_event_loop
|
360
390
|
end
|