sensu 0.9.2 → 0.9.3.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/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: