sensu 0.9.2 → 0.9.3.beta

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sensu.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sensu
2
- VERSION = "0.9.2"
2
+ VERSION = "0.9.3.beta"
3
3
  end
data/lib/sensu/client.rb CHANGED
@@ -10,6 +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
14
  EM::run do
14
15
  client.setup_amqp
15
16
  client.setup_keepalives
@@ -150,13 +151,13 @@ module Sensu
150
151
 
151
152
  def setup_standalone(options={})
152
153
  @logger.debug('[standalone] -- setup standalone')
153
- standalone_count = 0
154
+ standalone_check_count = 0
154
155
  @settings.checks.each do |name, details|
155
156
  if details.standalone
156
- standalone_count += 1
157
- check = Hashie::Mash.new(details.merge({:name => name}))
157
+ standalone_check_count += 1
158
+ check = Hashie::Mash.new(details.merge(:name => name))
158
159
  stagger = options[:test] ? 0 : 7
159
- @timers << EM::Timer.new(stagger*standalone_count) do
160
+ @timers << EM::Timer.new(stagger*standalone_check_count) do
160
161
  interval = options[:test] ? 0.5 : details.interval
161
162
  @timers << EM::PeriodicTimer.new(interval) do
162
163
  check.issued = Time.now.to_i
@@ -207,29 +208,33 @@ module Sensu
207
208
  attr_accessor :settings, :logger, :amq
208
209
 
209
210
  def receive_data(data)
210
- @logger.debug('[socket] -- new connection -- received data from external source')
211
- begin
212
- check = Hashie::Mash.new(JSON.parse(data))
213
- validates = %w[name status output].all? do |key|
214
- check.key?(key)
215
- end
216
- if validates
217
- @logger.info('[socket] -- publishing check result -- ' + check.name)
218
- @amq.queue('results').publish({
219
- :client => @settings.client.name,
220
- :check => check.to_hash
221
- }.to_json)
222
- else
223
- @logger.warn('[socket] -- a check name, exit status, and output are required -- e.g. {"name": "x", "status": 0, "output": "y"}')
211
+ if data == 'ping'
212
+ @logger.debug('[socket] -- received ping')
213
+ send_data('pong')
214
+ else
215
+ @logger.debug('[socket] -- received data -- ' + data)
216
+ begin
217
+ check = Hashie::Mash.new(JSON.parse(data))
218
+ validates = %w[name output].all? do |key|
219
+ check[key].is_a?(String)
220
+ end
221
+ check.status ||= 0
222
+ if validates && check.status.is_a?(Integer)
223
+ @logger.info('[socket] -- publishing check result -- ' + [check.name, check.status, check.output].join(' -- '))
224
+ @amq.queue('results').publish({
225
+ :client => @settings.client.name,
226
+ :check => check.to_hash
227
+ }.to_json)
228
+ send_data('ok')
229
+ else
230
+ @logger.warn('[socket] -- check name and output must be strings, status defaults to 0 -- e.g. {"name": "x", "output": "y"}')
231
+ send_data('invalid')
232
+ end
233
+ rescue JSON::ParserError => error
234
+ @logger.warn('[socket] -- check result must be valid JSON: ' + error.to_s)
235
+ send_data('invalid')
224
236
  end
225
- rescue JSON::ParserError => error
226
- @logger.warn('[socket] -- check result must be valid JSON: ' + error.to_s)
227
237
  end
228
- close_connection
229
- end
230
-
231
- def unbind
232
- @logger.debug('[socket] -- connection closed')
233
238
  end
234
239
  end
235
240
  end
data/lib/sensu/config.rb CHANGED
@@ -55,6 +55,9 @@ module Sensu
55
55
 
56
56
  def validate_common_settings
57
57
  @settings.checks.each do |name, details|
58
+ if details.key?('status') || details.key?('output')
59
+ invalid_config('reserved key (status or output) defined in check ' + name)
60
+ end
58
61
  unless details.interval.is_a?(Integer) && details.interval > 0
59
62
  invalid_config('missing interval for check ' + name)
60
63
  end
@@ -1,3 +1,9 @@
1
+ class Array
2
+ def deep_merge(other_array, &merger)
3
+ concat(other_array).uniq
4
+ end
5
+ end
6
+
1
7
  class Hash
2
8
  def symbolize_keys(item=self)
3
9
  case item
@@ -31,17 +37,11 @@ class Hash
31
37
  end
32
38
  end
33
39
 
34
- def deep_merge(hash)
35
- merger = proc do |key, value1, value2|
36
- if value1.is_a?(Hash) && value2.is_a?(Hash)
37
- value1.merge(value2, &merger)
38
- elsif value1.is_a?(Array) && value2.is_a?(Array)
39
- value1.concat(value2).uniq
40
- else
41
- value2
42
- end
40
+ def deep_merge(other_hash, &merger)
41
+ merger ||= proc do |key, oldval, newval|
42
+ oldval.deep_merge(newval, &merger) rescue newval
43
43
  end
44
- self.merge(hash, &merger)
44
+ merge(other_hash, &merger)
45
45
  end
46
46
  end
47
47
 
data/lib/sensu/server.rb CHANGED
@@ -91,22 +91,20 @@ module Sensu
91
91
  details = @settings.handlers[handler]
92
92
  case details['type']
93
93
  when 'pipe'
94
- handle = proc do
95
- output = ''
94
+ execute = proc do
96
95
  Bundler.with_clean_env do
97
96
  begin
98
97
  IO.popen(details.command + ' 2>&1', 'r+') do |io|
99
98
  io.write(event.to_json)
100
99
  io.close_write
101
- output = io.read
100
+ io.read
102
101
  end
103
102
  rescue Errno::EPIPE => error
104
- output = handler + ' -- broken pipe: ' + error.to_s
103
+ handler + ' -- broken pipe: ' + error.to_s
105
104
  end
106
105
  end
107
- output
108
106
  end
109
- EM::defer(handle, report)
107
+ EM::defer(execute, report)
110
108
  when 'amqp'
111
109
  exchange = details.exchange.name
112
110
  exchange_type = details.exchange.key?('type') ? details.exchange['type'].to_sym : :direct
@@ -130,79 +128,86 @@ module Sensu
130
128
  @redis.get('client:' + result.client).callback do |client_json|
131
129
  unless client_json.nil?
132
130
  client = Hashie::Mash.new(JSON.parse(client_json))
133
- check = @settings.checks.key?(result.check.name) ? result.check.merge(@settings.checks[result.check.name]) : result.check
134
- event = Hashie::Mash.new({
131
+ check = @settings.checks.key?(result.check.name) ? @settings.checks[result.check.name].merge(result.check) : result.check
132
+ event = Hashie::Mash.new(
135
133
  :client => client,
136
134
  :check => check,
137
135
  :occurrences => 1
138
- })
139
- if check['type'] == 'metric'
140
- handle_event(event)
141
- else
142
- history_key = 'history:' + client.name + ':' + check.name
143
- @redis.rpush(history_key, check.status).callback do
144
- @redis.lrange(history_key, -21, -1).callback do |history|
145
- event.check.history = history
146
- total_state_change = 0
147
- unless history.count < 21
148
- state_changes = 0
149
- change_weight = 0.8
150
- history.each do |status|
151
- previous_status ||= status
152
- unless status == previous_status
153
- state_changes += change_weight
154
- end
155
- change_weight += 0.02
156
- previous_status = status
136
+ )
137
+ history_key = 'history:' + client.name + ':' + check.name
138
+ @redis.rpush(history_key, check.status).callback do
139
+ @redis.lrange(history_key, -21, -1).callback do |history|
140
+ event.check.history = history
141
+ total_state_change = 0
142
+ unless history.count < 21
143
+ state_changes = 0
144
+ change_weight = 0.8
145
+ history.each do |status|
146
+ previous_status ||= status
147
+ unless status == previous_status
148
+ state_changes += change_weight
149
+ end
150
+ change_weight += 0.02
151
+ previous_status = status
152
+ end
153
+ total_state_change = (state_changes.fdiv(20) * 100).to_i
154
+ @redis.lpop(history_key)
155
+ end
156
+ @redis.hget('events:' + client.name, check.name).callback do |event_json|
157
+ previous_occurrence = event_json ? Hashie::Mash.new(JSON.parse(event_json)) : false
158
+ is_flapping = false
159
+ if check.key?('low_flap_threshold') && check.key?('high_flap_threshold')
160
+ was_flapping = previous_occurrence ? previous_occurrence.flapping : false
161
+ is_flapping = case
162
+ when total_state_change >= check.high_flap_threshold
163
+ true
164
+ when was_flapping && total_state_change <= check.low_flap_threshold
165
+ false
166
+ else
167
+ was_flapping
157
168
  end
158
- total_state_change = (state_changes.fdiv(20) * 100).to_i
159
- @redis.lpop(history_key)
160
169
  end
161
- @redis.hget('events:' + client.name, check.name).callback do |event_json|
162
- previous_occurrence = event_json ? Hashie::Mash.new(JSON.parse(event_json)) : false
163
- is_flapping = false
164
- if check.key?('low_flap_threshold') && check.key?('high_flap_threshold')
165
- was_flapping = previous_occurrence ? previous_occurrence.flapping : false
166
- is_flapping = case
167
- when total_state_change >= check.high_flap_threshold
168
- true
169
- when was_flapping && total_state_change <= check.low_flap_threshold
170
- false
170
+ if check.status != 0
171
+ if previous_occurrence && check.status == previous_occurrence.status
172
+ event.occurrences = previous_occurrence.occurrences += 1
173
+ end
174
+ @redis.hset('events:' + client.name, check.name, {
175
+ :status => check.status,
176
+ :output => check.output,
177
+ :flapping => is_flapping,
178
+ :occurrences => event.occurrences
179
+ }.to_json).callback do
180
+ unless check.handle == false
181
+ event.check.flapping = is_flapping
182
+ event.action = 'create'
183
+ handle_event(event)
171
184
  else
172
- was_flapping
185
+ @logger.debug('[result] -- handling disabled -- ' + [client.name, check.name, check.status].join(' -- '))
173
186
  end
174
187
  end
175
- if previous_occurrence && check.status == 0
176
- unless is_flapping
177
- unless check.auto_resolve == false && !check.force_resolve
178
- @redis.hdel('events:' + client.name, check.name).callback do
179
- unless check.handle == false
180
- event.action = 'resolve'
181
- handle_event(event)
182
- end
188
+ elsif previous_occurrence
189
+ unless is_flapping
190
+ unless check.auto_resolve == false && !check.force_resolve
191
+ @redis.hdel('events:' + client.name, check.name).callback do
192
+ unless check.handle == false
193
+ event.action = 'resolve'
194
+ handle_event(event)
195
+ else
196
+ @logger.debug('[result] -- handling disabled -- ' + [client.name, check.name, check.status].join(' -- '))
183
197
  end
184
198
  end
185
- else
186
- @logger.debug('[result] -- check is flapping -- ' + client.name + ' -- ' + check.name)
187
- @redis.hset('events:' + client.name, check.name, previous_occurrence.merge({'flapping' => true}).to_json)
188
- end
189
- elsif check.status != 0
190
- if previous_occurrence && check.status == previous_occurrence.status
191
- event.occurrences = previous_occurrence.occurrences += 1
192
199
  end
193
- @redis.hset('events:' + client.name, check.name, {
194
- :status => check.status,
195
- :output => check.output,
196
- :flapping => is_flapping,
197
- :occurrences => event.occurrences
198
- }.to_json).callback do
199
- unless check.handle == false
200
+ else
201
+ @logger.debug('[result] -- check is flapping -- ' + [client.name, check.name, check.status].join(' -- '))
202
+ @redis.hset('events:' + client.name, check.name, previous_occurrence.merge(:flapping => true).to_json).callback do
203
+ if check['type'] == 'metric'
200
204
  event.check.flapping = is_flapping
201
- event.action = 'create'
202
205
  handle_event(event)
203
206
  end
204
207
  end
205
208
  end
209
+ elsif check['type'] == 'metric'
210
+ handle_event(event)
206
211
  end
207
212
  end
208
213
  end
@@ -225,7 +230,7 @@ module Sensu
225
230
  @logger.debug('[publisher] -- setup publisher')
226
231
  stagger = options[:test] ? 0 : 7
227
232
  @settings.checks.each_with_index do |(name, details), index|
228
- check_request = Hashie::Mash.new({:name => name})
233
+ check_request = Hashie::Mash.new(:name => name)
229
234
  unless details.publish == false || details.standalone
230
235
  @timers << EM::Timer.new(stagger*index) do
231
236
  details.subscribers.each do |exchange|
@@ -250,13 +255,13 @@ module Sensu
250
255
  @redis.get('client:' + client_id).callback do |client_json|
251
256
  client = Hashie::Mash.new(JSON.parse(client_json))
252
257
  time_since_last_keepalive = Time.now.to_i - client.timestamp
253
- result = Hashie::Mash.new({
258
+ result = Hashie::Mash.new(
254
259
  :client => client.name,
255
260
  :check => {
256
261
  :name => 'keepalive',
257
262
  :issued => Time.now.to_i
258
263
  }
259
- })
264
+ )
260
265
  case
261
266
  when time_since_last_keepalive >= 180
262
267
  result.check.status = 2
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu
3
3
  version: !ruby/object:Gem::Version
4
- hash: 63
5
- prerelease: false
4
+ hash: 31098117
5
+ prerelease: true
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 2
10
- version: 0.9.2
9
+ - 3
10
+ - beta
11
+ version: 0.9.3.beta
11
12
  platform: ruby
12
13
  authors:
13
14
  - Sean Porter
@@ -16,7 +17,7 @@ autorequire:
16
17
  bindir: bin
17
18
  cert_chain: []
18
19
 
19
- date: 2012-01-05 00:00:00 -08:00
20
+ date: 2012-01-12 00:00:00 -08:00
20
21
  default_executable:
21
22
  dependencies:
22
23
  - !ruby/object:Gem::Dependency
@@ -258,12 +259,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
258
259
  required_rubygems_version: !ruby/object:Gem::Requirement
259
260
  none: false
260
261
  requirements:
261
- - - ">="
262
+ - - ">"
262
263
  - !ruby/object:Gem::Version
263
- hash: 3
264
+ hash: 25
264
265
  segments:
265
- - 0
266
- version: "0"
266
+ - 1
267
+ - 3
268
+ - 1
269
+ version: 1.3.1
267
270
  requirements: []
268
271
 
269
272
  rubyforge_project: