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

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/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