sensu 0.9.5 → 0.9.6.beta

Sign up to get free protection for your applications and to get access to all the features.
data/README.org CHANGED
@@ -1,46 +1,12 @@
1
- * Welcome to Sensu
2
- Sensu, a monitoring framework that aims to be simple, malleable, and scalable.
1
+ * Sensu
2
+ A monitoring framework that aims to be simple, malleable, and scalable.
3
3
 
4
- [[https://github.com/sonian/sensu/raw/master/sensu-logo.png]]
4
+ [[https://github.com/sensu/sensu/raw/master/sensu-logo.png]]
5
5
 
6
- [[http://portertech.ca/2011/11/01/sensu-a-monitoring-framework][Blog post]]
6
+ [[https://secure.travis-ci.org/sensu/sensu.png]]
7
7
 
8
- [[http://www.sonian.com/cloud-tools/cloud-monitoring-sensu/][Homepage]]
9
- * Documentation
10
- - [[https://github.com/sonian/sensu/wiki][Sensu Wiki]].
11
- - [[http://joemiller.me/2012/01/19/getting-started-with-the-sensu-monitoring-framework/][Getting Started]]
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
- $: << File.dirname(__FILE__) + '/../lib' unless $:.include?(File.dirname(__FILE__) + '/../lib/')
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::Config.read_arguments(ARGV)
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
- $: << File.dirname(__FILE__) + '/../lib' unless $:.include?(File.dirname(__FILE__) + '/../lib/')
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::Config.read_arguments(ARGV)
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
- $: << File.dirname(__FILE__) + '/../lib' unless $:.include?(File.dirname(__FILE__) + '/../lib/')
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::Config.read_arguments(ARGV)
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__), 'config')
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.api.port)
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
- config = Sensu::Config.new(options)
30
- $logger = config.logger
31
- $settings = config.settings
32
- if options[:daemonize]
33
- Process.daemonize
34
- end
35
- if options[:pid_file]
36
- Process.write_pid(options[:pid_file])
37
- end
38
- $logger.debug('[setup] -- connecting to redis')
39
- $redis = Redis.connect($settings.redis.to_hash.symbolize_keys)
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.api.user && $settings.api.password
41
+ if $settings[:api][:user] && $settings[:api][:password]
44
42
  use Rack::Auth::Basic do |user, password|
45
- user == $settings.api.user && password == $settings.api.password
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
- $logger.debug('[info] -- ' + request.ip + ' -- GET -- request for sensu info')
72
+ request_log(env)
64
73
  response = {
65
74
  :sensu => {
66
- :version => Sensu::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
- $logger.debug('[clients] -- ' + request.ip + ' -- GET -- request for client list')
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 |client, index|
88
- $redis.get('client:' + client).callback do |client_json|
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 |client|
102
- $logger.debug('[client] -- ' + request.ip + ' -- GET -- request for client -- ' + client)
103
- $redis.get('client:' + client).callback do |client_json|
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 |client|
114
- $logger.debug('[client] -- ' + request.ip + ' -- DELETE -- request for client -- ' + client)
115
- $redis.sismember('clients', client).callback do |client_exists|
116
- if client_exists
117
- $redis.hgetall('events:' + client).callback do |events|
118
- events.keys.each do |check_name|
119
- $logger.info('[client] -- publishing check result to resolve event -- ' + client + ' -- ' + check_name)
120
- check = {
121
- :name => check_name,
122
- :output => 'Client is being removed on request of the API',
123
- :status => 0,
124
- :issued => Time.now.to_i,
125
- :force_resolve => true
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
- $amq.queue('results').publish({:client => client, :check => check}.to_json)
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
- $logger.info('[client] -- deleting client -- ' + client)
132
- $redis.srem('clients', client)
133
- $redis.del('events:' + client)
134
- $redis.del('client:' + client)
135
- $settings.checks.each_key do |check_name|
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
- $logger.debug('[checks] -- ' + request.ip + ' -- GET -- request for check list')
151
- response = $settings.checks.map { |check, details| details.merge(:name => check) }
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 |check|
156
- $logger.debug('[check] -- ' + request.ip + ' -- GET -- request for check -- ' + check)
157
- if $settings.checks.key?(check)
158
- response = $settings.checks[check].merge(:name => check)
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
- $logger.debug('[check] -- ' + request.ip + ' -- POST -- request to publish a check request')
182
+ request_log(env)
168
183
  begin
169
- post_body = Hashie::Mash.new(JSON.parse(request.body.read))
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.check.is_a?(String) && post_body.subscribers.is_a?(Array)
175
- post_body.subscribers.each do |exchange|
176
- $logger.info('[check] -- publishing check request -- ' + post_body.check + ' -- ' + exchange)
177
- $amq.fanout(exchange).publish({:name => post_body.check, :issued => Time.now.to_i}.to_json)
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
- $logger.debug('[events] -- ' + request.ip + ' -- GET -- request for event list')
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 |client, index|
192
- $redis.hgetall('events:' + client).callback do |events|
193
- events.each do |check, details|
194
- response.push(JSON.parse(details).merge(:client => client, :check => check))
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 |client, check|
208
- $logger.debug('[event] -- ' + request.ip + ' -- GET -- request for event -- ' + client + ' -- ' + check)
209
- $redis.hgetall('events:' + client).callback do |events|
210
- event_json = events[check]
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 => client, :check => check)
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
- $logger.debug('[event] -- ' + request.ip + ' -- POST -- request to resolve event')
244
+ request_log(env)
223
245
  begin
224
- post_body = Hashie::Mash.new(JSON.parse(request.body.read))
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.client.is_a?(String) && post_body.check.is_a?(String)
230
- $redis.hgetall('events:' + post_body.client).callback do |events|
231
- if events.include?(post_body.check)
232
- $logger.info('[event] -- publishing check result to resolve event -- ' + post_body.client + ' -- ' + post_body.check)
233
- check = {
234
- :name => post_body.check,
235
- :output => 'Resolving on request of the API',
236
- :status => 0,
237
- :issued => Time.now.to_i,
238
- :force_resolve => true
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
- $amq.queue('results').publish({:client => post_body.client, :check => check}.to_json)
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
- $logger.debug('[stash] -- ' + request.ip + ' -- POST -- request for stash -- ' + path)
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
- $logger.debug('[stash] -- ' + request.ip + ' -- GET -- request for stash -- ' + path)
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
- $logger.debug('[stash] -- ' + request.ip + ' -- DELETE -- request for stash -- ' + path)
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
- $logger.debug('[stashes] -- ' + request.ip + ' -- GET -- request for list of stashes')
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
- $logger.debug('[stashes] -- ' + request.ip + ' -- POST -- request for multiple stashes')
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.client.timestamp = Time.now.to_i
334
- $redis.set('client:' + $settings.client.name, $settings.client.to_json).callback do
335
- $redis.sadd('clients', $settings.client.name).callback do
336
- $redis.hset('events:' + $settings.client.name, 'test', {
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.utc.iso8601,
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.api.port)
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('[stop] -- stopping sensu api -- ' + signal)
357
- $logger.warn('[stop] -- stopping reactor')
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