sensu 0.9.3.beta.1 → 0.9.3.beta.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sensu/api.rb CHANGED
@@ -54,7 +54,9 @@ module Sensu
54
54
  clients.each_with_index do |client, index|
55
55
  $redis.get('client:' + client).callback do |client_json|
56
56
  response.push(JSON.parse(client_json))
57
- body response.to_json if index == clients.size - 1
57
+ if index == clients.size - 1
58
+ body response.to_json
59
+ end
58
60
  end
59
61
  end
60
62
  else
@@ -66,7 +68,9 @@ module Sensu
66
68
  aget '/client/:name' do |client|
67
69
  $logger.debug('[client] -- ' + request.ip + ' -- GET -- request for client -- ' + client)
68
70
  $redis.get('client:' + client).callback do |client_json|
69
- status 404 if client_json.nil?
71
+ if client_json.nil?
72
+ status 404
73
+ end
70
74
  body client_json
71
75
  end
72
76
  end
@@ -77,6 +81,7 @@ module Sensu
77
81
  if client_exists
78
82
  $redis.hgetall('events:' + client).callback do |events|
79
83
  events.keys.each do |check_name|
84
+ $logger.info('[client] -- publishing check result to resolve event -- ' + client + ' -- ' + check_name)
80
85
  check = {
81
86
  :name => check_name,
82
87
  :issued => Time.now.to_i,
@@ -86,7 +91,9 @@ module Sensu
86
91
  }
87
92
  $amq.queue('results').publish({:client => client, :check => check}.to_json)
88
93
  end
94
+ $logger.info('[client] -- client will be deleted -- ' + client)
89
95
  EM::Timer.new(5) do
96
+ $logger.info('[client] -- deleting client -- ' + client)
90
97
  $redis.srem('clients', client)
91
98
  $redis.del('events:' + client)
92
99
  $redis.del('client:' + client)
@@ -119,6 +126,26 @@ module Sensu
119
126
  end
120
127
  end
121
128
 
129
+ apost '/check/request' do
130
+ $logger.debug('[check] -- ' + request.ip + ' -- POST -- request to publish a check request')
131
+ begin
132
+ post_body = Hashie::Mash.new(JSON.parse(request.body.read))
133
+ rescue JSON::ParserError
134
+ status 400
135
+ body nil
136
+ end
137
+ if post_body.check.is_a?(String) && post_body.subscribers.is_a?(Array)
138
+ post_body.subscribers.each do |exchange|
139
+ $logger.info('[check] -- publishing check request -- ' + post_body.check + ' -- ' + exchange)
140
+ $amq.fanout(exchange).publish({:name => post_body.check, :issued => Time.now.to_i}.to_json)
141
+ end
142
+ status 201
143
+ else
144
+ status 400
145
+ end
146
+ body nil
147
+ end
148
+
122
149
  aget '/events' do
123
150
  $logger.debug('[events] -- ' + request.ip + ' -- GET -- request for event list')
124
151
  response = Hash.new
@@ -129,8 +156,12 @@ module Sensu
129
156
  events.each do |key, value|
130
157
  events[key] = JSON.parse(value)
131
158
  end
132
- response[client] = events unless events.empty?
133
- body response.to_json if index == clients.size - 1
159
+ unless events.empty?
160
+ response[client] = events
161
+ end
162
+ if index == clients.size - 1
163
+ body response.to_json
164
+ end
134
165
  end
135
166
  end
136
167
  else
@@ -142,31 +173,34 @@ module Sensu
142
173
  aget '/event/:client/:check' do |client, check|
143
174
  $logger.debug('[event] -- ' + request.ip + ' -- GET -- request for event -- ' + client + ' -- ' + check)
144
175
  $redis.hgetall('events:' + client).callback do |events|
145
- event = events[check]
146
- status 404 if event.nil?
147
- body event
176
+ event_json = events[check]
177
+ if event_json.nil?
178
+ status 404
179
+ end
180
+ body event_json
148
181
  end
149
182
  end
150
183
 
151
184
  apost '/event/resolve' do
152
185
  $logger.debug('[event] -- ' + request.ip + ' -- POST -- request to resolve event')
153
186
  begin
154
- event = JSON.parse(request.body.read)
187
+ post_body = Hashie::Mash.new(JSON.parse(request.body.read))
155
188
  rescue JSON::ParserError
156
189
  status 400
157
190
  body nil
158
191
  end
159
- if event.has_key?('client') && event.has_key?('check')
160
- $redis.hgetall('events:' + event['client']).callback do |events|
161
- if events.has_key?(event['check'])
192
+ if post_body.client.is_a?(String) && post_body.check.is_a?(String)
193
+ $redis.hgetall('events:' + post_body.client).callback do |events|
194
+ if events.include?(post_body.check)
195
+ $logger.info('[event] -- publishing check result to resolve event -- ' + post_body.client + ' -- ' + post_body.check)
162
196
  check = {
163
- :name => event['check'],
197
+ :name => post_body.check,
164
198
  :issued => Time.now.to_i,
165
199
  :status => 0,
166
200
  :output => 'Resolving on request of the API',
167
201
  :force_resolve => true
168
202
  }
169
- $amq.queue('results').publish({:client => event['client'], :check => check}.to_json)
203
+ $amq.queue('results').publish({:client => post_body.client, :check => check}.to_json)
170
204
  status 201
171
205
  else
172
206
  status 404
@@ -182,12 +216,12 @@ module Sensu
182
216
  apost '/stash/*' do |path|
183
217
  $logger.debug('[stash] -- ' + request.ip + ' -- POST -- request for stash -- ' + path)
184
218
  begin
185
- stash = JSON.parse(request.body.read)
219
+ post_body = JSON.parse(request.body.read)
186
220
  rescue JSON::ParserError
187
221
  status 400
188
222
  body nil
189
223
  end
190
- $redis.set('stash:' + path, stash.to_json).callback do
224
+ $redis.set('stash:' + path, post_body.to_json).callback do
191
225
  $redis.sadd('stashes', path).callback do
192
226
  status 201
193
227
  body nil
@@ -197,16 +231,18 @@ module Sensu
197
231
 
198
232
  aget '/stash/*' do |path|
199
233
  $logger.debug('[stash] -- ' + request.ip + ' -- GET -- request for stash -- ' + path)
200
- $redis.get('stash:' + path).callback do |stash|
201
- status 404 if stash.nil?
202
- body stash
234
+ $redis.get('stash:' + path).callback do |stash_json|
235
+ if stash_json.nil?
236
+ status 404
237
+ end
238
+ body stash_json
203
239
  end
204
240
  end
205
241
 
206
242
  adelete '/stash/*' do |path|
207
243
  $logger.debug('[stash] -- ' + request.ip + ' -- DELETE -- request for stash -- ' + path)
208
- $redis.exists('stash:' + path).callback do |stash_exist|
209
- if stash_exist
244
+ $redis.exists('stash:' + path).callback do |stash_exists|
245
+ if stash_exists
210
246
  $redis.srem('stashes', path).callback do
211
247
  $redis.del('stash:' + path).callback do
212
248
  status 204
@@ -230,17 +266,21 @@ module Sensu
230
266
  apost '/stashes' do
231
267
  $logger.debug('[stashes] -- ' + request.ip + ' -- POST -- request for multiple stashes')
232
268
  begin
233
- paths = JSON.parse(request.body.read)
269
+ post_body = JSON.parse(request.body.read)
234
270
  rescue JSON::ParserError
235
271
  status 400
236
272
  body nil
237
273
  end
238
274
  response = Hash.new
239
- if paths.is_a?(Array) && paths.size > 0
240
- paths.each_with_index do |path, index|
241
- $redis.get('stash:' + path).callback do |stash|
242
- response[path] = JSON.parse(stash) unless stash.nil?
243
- body response.to_json if index == paths.size - 1
275
+ if post_body.is_a?(Array) && post_body.size > 0
276
+ post_body.each_with_index do |path, index|
277
+ $redis.get('stash:' + path).callback do |stash_json|
278
+ unless stash_json.nil?
279
+ response[path] = JSON.parse(stash_json)
280
+ end
281
+ if index == post_body.size - 1
282
+ body response.to_json
283
+ end
244
284
  end
245
285
  end
246
286
  else
@@ -249,20 +289,22 @@ module Sensu
249
289
  end
250
290
  end
251
291
 
252
- def self.setup_test_scaffolding(options={})
292
+ def self.run_test(options={}, &block)
253
293
  self.setup(options)
254
294
  $settings.client.timestamp = Time.now.to_i
255
295
  $redis.set('client:' + $settings.client.name, $settings.client.to_json).callback do
256
296
  $redis.sadd('clients', $settings.client.name).callback do
257
297
  $redis.hset('events:' + $settings.client.name, 'test', {
258
298
  :status => 2,
259
- :output => 'CRITICAL',
299
+ :output => "CRITICAL\n",
300
+ :issued => Time.now.utc.iso8601,
260
301
  :flapping => false,
261
302
  :occurrences => 1
262
303
  }.to_json).callback do
263
304
  $redis.set('stash:test/test', '{"key": "value"}').callback do
264
305
  Thin::Logging.silent = true
265
306
  Thin::Server.start(self, $settings.api.port)
307
+ block.call
266
308
  end
267
309
  end
268
310
  end
data/lib/sensu/client.rb CHANGED
@@ -10,7 +10,7 @@ module Sensu
10
10
  if options[:pid_file]
11
11
  Process.write_pid(options[:pid_file])
12
12
  end
13
- EM::threadpool_size = 16
13
+ EM::threadpool_size = 14
14
14
  EM::run do
15
15
  client.setup_amqp
16
16
  client.setup_keepalives
@@ -86,9 +86,15 @@ module Sensu
86
86
  if unmatched_tokens.empty?
87
87
  execute = proc do
88
88
  Bundler.with_clean_env do
89
- IO.popen(command + ' 2>&1') do |io|
90
- check.output = io.read
89
+ started = Time.now.to_f
90
+ begin
91
+ IO.popen(command + ' 2>&1') do |io|
92
+ check.output = io.read
93
+ end
94
+ rescue => error
95
+ check.output = 'unexpected error: ' + error.to_s
91
96
  end
97
+ check.duration = ('%.3f' % (Time.now.to_f - started)).to_f
92
98
  end
93
99
  check.status = $?.exitstatus
94
100
  end
@@ -218,6 +224,7 @@ module Sensu
218
224
  validates = %w[name output].all? do |key|
219
225
  check[key].is_a?(String)
220
226
  end
227
+ check.issued = Time.now.to_i
221
228
  check.status ||= 0
222
229
  if validates && check.status.is_a?(Integer)
223
230
  @logger.info('[socket] -- publishing check result -- ' + [check.name, check.status, check.output].join(' -- '))
data/lib/sensu/config.rb CHANGED
@@ -1,17 +1,22 @@
1
1
  require File.join(File.dirname(__FILE__), 'patches', 'ruby')
2
2
 
3
- require 'rubygems' if RUBY_VERSION < '1.9.0'
3
+ require 'rubygems'
4
4
  require 'bundler'
5
5
  require 'bundler/setup'
6
6
 
7
7
  gem 'eventmachine', '~> 1.0.0.beta.4'
8
8
 
9
9
  require 'optparse'
10
+ require 'time'
10
11
  require 'json'
11
12
  require 'hashie'
12
13
  require 'amqp'
13
14
  require 'cabin'
14
- require 'cabin/outputs/em-stdlib-logger'
15
+ require 'cabin/outputs/em/stdlib-logger'
16
+
17
+ if ENV['RBTRACE']
18
+ require 'rbtrace'
19
+ end
15
20
 
16
21
  module Sensu
17
22
  class Config
@@ -44,7 +49,7 @@ module Sensu
44
49
  end
45
50
  @logger = Cabin::Channel.new
46
51
  log_output = File.basename($0) == 'rake' ? '/tmp/sensu_test.log' : STDOUT
47
- @logger.subscribe(Cabin::Outputs::EmStdlibLogger.new(Logger.new(log_output)))
52
+ @logger.subscribe(Cabin::Outputs::EM::StdlibLogger.new(Logger.new(log_output)))
48
53
  @logger.level = @options[:verbose] ? :debug : :info
49
54
  if Signal.list.include?('USR1')
50
55
  Signal.trap('USR1') do
@@ -93,7 +98,7 @@ module Sensu
93
98
  unless details['type'].is_a?(String)
94
99
  invalid_config('missing type for handler ' + name)
95
100
  end
96
- case details['type']
101
+ case details.type
97
102
  when 'pipe'
98
103
  unless details.command.is_a?(String)
99
104
  invalid_config('missing command for pipe handler ' + name)
@@ -176,7 +181,7 @@ module Sensu
176
181
  invalid_config('configuration snippet file (' + snippet_file + ') must be valid JSON: ' + error.to_s)
177
182
  end
178
183
  merged_settings = @settings.to_hash.deep_merge(snippet_hash)
179
- @logger.warn('[settings] configuration snippet (' + snippet_file + ') applied changes: ' + @settings.deep_diff(merged_settings).to_json)
184
+ @logger.warn('[settings] -- configuration snippet (' + snippet_file + ') applied changes: ' + @settings.deep_diff(merged_settings).to_json)
180
185
  @settings = Hashie::Mash.new(merged_settings)
181
186
  else
182
187
  invalid_config('configuration snippet file is not readable: ' + snippet_file)
data/lib/sensu/server.rb CHANGED
@@ -16,7 +16,7 @@ module Sensu
16
16
  if options[:pid_file]
17
17
  Process.write_pid(options[:pid_file])
18
18
  end
19
- EM::threadpool_size = 16
19
+ EM::threadpool_size = 14
20
20
  EM::run do
21
21
  server.setup_redis
22
22
  server.setup_amqp
@@ -74,7 +74,7 @@ module Sensu
74
74
  ['default']
75
75
  end
76
76
  handlers.map! do |handler|
77
- @settings.handlers[handler]['type'] == 'set' ? @settings.handlers[handler].handlers : handler
77
+ @settings.handlers[handler].type == 'set' ? @settings.handlers[handler].handlers : handler
78
78
  end
79
79
  handlers.flatten!
80
80
  handlers.uniq!
@@ -89,7 +89,7 @@ module Sensu
89
89
  @logger.debug('[event] -- handling event -- ' + [handler, event.client.name, event.check.name].join(' -- '))
90
90
  @handlers_in_progress += 1
91
91
  details = @settings.handlers[handler]
92
- case details['type']
92
+ case details.type
93
93
  when 'pipe'
94
94
  execute = proc do
95
95
  Bundler.with_clean_env do
@@ -99,15 +99,19 @@ module Sensu
99
99
  io.close_write
100
100
  io.read
101
101
  end
102
+ rescue Errno::ENOENT => error
103
+ handler + ' -- does not exist: ' + error.to_s
102
104
  rescue Errno::EPIPE => error
103
105
  handler + ' -- broken pipe: ' + error.to_s
106
+ rescue => error
107
+ handler + ' -- unexpected error: ' + error.to_s
104
108
  end
105
109
  end
106
110
  end
107
111
  EM::defer(execute, report)
108
112
  when 'amqp'
109
113
  exchange = details.exchange.name
110
- exchange_type = details.exchange.key?('type') ? details.exchange['type'].to_sym : :direct
114
+ exchange_type = details.exchange.key?('type') ? details.exchange.type.to_sym : :direct
111
115
  exchange_options = details.exchange.reject { |key, value| %w[name type].include?(key) }
112
116
  @logger.debug('[event] -- publishing event to rabbitmq exchange -- ' + [exchange, event.client.name, event.check.name].join(' -- '))
113
117
  payload = details.send_only_check_output ? event.check.output : event.to_json
@@ -174,10 +178,11 @@ module Sensu
174
178
  @redis.hset('events:' + client.name, check.name, {
175
179
  :status => check.status,
176
180
  :output => check.output,
181
+ :issued => Time.at(check.issued).utc.iso8601,
177
182
  :flapping => is_flapping,
178
183
  :occurrences => event.occurrences
179
184
  }.to_json).callback do
180
- unless check.internal || check.handle == false
185
+ unless check.handle == false
181
186
  event.check.flapping = is_flapping
182
187
  event.action = 'create'
183
188
  handle_event(event)
@@ -189,7 +194,7 @@ module Sensu
189
194
  unless is_flapping
190
195
  unless check.auto_resolve == false && !check.force_resolve
191
196
  @redis.hdel('events:' + client.name, check.name).callback do
192
- unless check.internal || check.handle == false
197
+ unless check.handle == false
193
198
  event.action = 'resolve'
194
199
  handle_event(event)
195
200
  else
@@ -200,13 +205,13 @@ module Sensu
200
205
  else
201
206
  @logger.debug('[result] -- check is flapping -- ' + [client.name, check.name, check.status].join(' -- '))
202
207
  @redis.hset('events:' + client.name, check.name, previous_occurrence.merge(:flapping => true).to_json).callback do
203
- if check['type'] == 'metric'
208
+ if check.type == 'metric'
204
209
  event.check.flapping = is_flapping
205
210
  handle_event(event)
206
211
  end
207
212
  end
208
213
  end
209
- elsif check['type'] == 'metric'
214
+ elsif check.type == 'metric'
210
215
  handle_event(event)
211
216
  end
212
217
  end
data/lib/sensu.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sensu
2
- VERSION = "0.9.3.beta.1"
2
+ VERSION = "0.9.3.beta.2"
3
3
  end
data/sensu.gemspec CHANGED
@@ -16,8 +16,8 @@ Gem::Specification.new do |s|
16
16
  s.add_dependency("eventmachine", "~> 1.0.0.beta.4")
17
17
  s.add_dependency("amqp", "0.7.4")
18
18
  s.add_dependency("json")
19
- s.add_dependency("hashie")
20
- s.add_dependency("cabin", "0.1.7")
19
+ s.add_dependency("hashie", "~> 1.2.0")
20
+ s.add_dependency("cabin", "0.1.8")
21
21
  s.add_dependency("ruby-redis")
22
22
  s.add_dependency("rack", "~> 1.3.4")
23
23
  s.add_dependency("async_sinatra")
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.add_development_dependency("rake")
27
27
  s.add_development_dependency("em-spec")
28
28
  s.add_development_dependency("em-http-request")
29
+ s.add_development_dependency("rbtrace")
29
30
 
30
31
  s.files = Dir.glob("{bin,lib}/**/*") + %w[sensu.gemspec README.org MIT-LICENSE.txt]
31
32
  s.executables = Dir.glob("bin/**/*").map { |file| File.basename(file) }
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu
3
3
  version: !ruby/object:Gem::Version
4
- hash: 62196265
4
+ hash: 62196271
5
5
  prerelease: true
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
9
  - 3
10
10
  - beta
11
- - 1
12
- version: 0.9.3.beta.1
11
+ - 2
12
+ version: 0.9.3.beta.2
13
13
  platform: ruby
14
14
  authors:
15
15
  - Sean Porter
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2012-01-12 00:00:00 -08:00
21
+ date: 2012-01-17 00:00:00 -08:00
22
22
  default_executable:
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
@@ -89,12 +89,14 @@ dependencies:
89
89
  requirement: &id005 !ruby/object:Gem::Requirement
90
90
  none: false
91
91
  requirements:
92
- - - ">="
92
+ - - ~>
93
93
  - !ruby/object:Gem::Version
94
- hash: 3
94
+ hash: 31
95
95
  segments:
96
+ - 1
97
+ - 2
96
98
  - 0
97
- version: "0"
99
+ version: 1.2.0
98
100
  type: :runtime
99
101
  version_requirements: *id005
100
102
  - !ruby/object:Gem::Dependency
@@ -105,12 +107,12 @@ dependencies:
105
107
  requirements:
106
108
  - - "="
107
109
  - !ruby/object:Gem::Version
108
- hash: 21
110
+ hash: 11
109
111
  segments:
110
112
  - 0
111
113
  - 1
112
- - 7
113
- version: 0.1.7
114
+ - 8
115
+ version: 0.1.8
114
116
  type: :runtime
115
117
  version_requirements: *id006
116
118
  - !ruby/object:Gem::Dependency
@@ -213,6 +215,20 @@ dependencies:
213
215
  version: "0"
214
216
  type: :development
215
217
  version_requirements: *id013
218
+ - !ruby/object:Gem::Dependency
219
+ name: rbtrace
220
+ prerelease: false
221
+ requirement: &id014 !ruby/object:Gem::Requirement
222
+ none: false
223
+ requirements:
224
+ - - ">="
225
+ - !ruby/object:Gem::Version
226
+ hash: 3
227
+ segments:
228
+ - 0
229
+ version: "0"
230
+ type: :development
231
+ version_requirements: *id014
216
232
  description: A monitoring framework that aims to be simple, malleable, and scalable. Uses the publish/subscribe model.
217
233
  email:
218
234
  - sean.porter@sonian.net