sensu 0.9.1 → 0.9.2.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.1"
2
+ VERSION = "0.9.2.beta"
3
3
  end
data/lib/sensu/api.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), 'config')
2
2
 
3
+ require 'thin'
3
4
  require 'sinatra/async'
4
5
  require 'redis'
5
6
 
@@ -12,7 +13,9 @@ module Sensu
12
13
  def self.run(options={})
13
14
  EM::run do
14
15
  self.setup(options)
15
- self.run!(:port => $settings.api.port)
16
+
17
+ Thin::Logging.silent = true
18
+ Thin::Server.start(self, $settings.api.port)
16
19
 
17
20
  %w[INT TERM].each do |signal|
18
21
  Signal.trap(signal) do
@@ -24,8 +27,8 @@ module Sensu
24
27
 
25
28
  def self.setup(options={})
26
29
  config = Sensu::Config.new(options)
30
+ $logger = config.logger
27
31
  $settings = config.settings
28
- $logger = config.logger || config.open_log
29
32
  if options[:daemonize]
30
33
  Process.daemonize
31
34
  end
@@ -246,7 +249,7 @@ module Sensu
246
249
  end
247
250
  end
248
251
 
249
- def self.create_test_scaffolding(options={})
252
+ def self.setup_test_scaffolding(options={})
250
253
  self.setup(options)
251
254
  $settings.client.timestamp = Time.now.to_i
252
255
  $redis.set('client:' + $settings.client.name, $settings.client.to_json).callback do
@@ -258,7 +261,8 @@ module Sensu
258
261
  :occurrences => 1
259
262
  }.to_json).callback do
260
263
  $redis.set('stash:test/test', '{"key": "value"}').callback do
261
- self.run!(:port => $settings.api.port)
264
+ Thin::Logging.silent = true
265
+ Thin::Server.start(self, $settings.api.port)
262
266
  end
263
267
  end
264
268
  end
@@ -267,7 +271,8 @@ module Sensu
267
271
 
268
272
  def self.stop(signal)
269
273
  $logger.warn('[stop] -- stopping sensu api -- ' + signal)
270
- EM::Timer.new(1) do
274
+ $logger.warn('[stop] -- stopping reactor')
275
+ EM::PeriodicTimer.new(0.25) do
271
276
  EM::stop_event_loop
272
277
  end
273
278
  end
data/lib/sensu/client.rb CHANGED
@@ -15,6 +15,7 @@ module Sensu
15
15
  client.setup_keepalives
16
16
  client.setup_subscriptions
17
17
  client.setup_queue_monitor
18
+ client.setup_standalone
18
19
  client.setup_socket
19
20
 
20
21
  %w[INT TERM].each do |signal|
@@ -27,8 +28,10 @@ module Sensu
27
28
 
28
29
  def initialize(options={})
29
30
  config = Sensu::Config.new(options)
31
+ @logger = config.logger
30
32
  @settings = config.settings
31
- @logger = config.logger || config.open_log
33
+ @timers = Array.new
34
+ @checks_in_progress = Array.new
32
35
  end
33
36
 
34
37
  def setup_amqp
@@ -46,7 +49,7 @@ module Sensu
46
49
  def setup_keepalives
47
50
  @logger.debug('[keepalive] -- setup keepalives')
48
51
  publish_keepalive
49
- EM::PeriodicTimer.new(30) do
52
+ @timers << EM::PeriodicTimer.new(30) do
50
53
  publish_keepalive
51
54
  end
52
55
  end
@@ -60,16 +63,24 @@ module Sensu
60
63
  end
61
64
 
62
65
  def execute_check(check)
63
- @logger.debug('[execute] -- executing check -- ' + check.name)
64
- @checks_in_progress ||= Array.new
66
+ @logger.debug('[execute] -- attempting to execute check -- ' + check.name)
65
67
  if @settings.checks.key?(check.name)
66
68
  unless @checks_in_progress.include?(check.name)
69
+ @logger.debug('[execute] -- executing check -- ' + check.name)
67
70
  @checks_in_progress.push(check.name)
68
71
  unmatched_tokens = Array.new
69
72
  command = @settings.checks[check.name].command.gsub(/:::(.*?):::/) do
70
- key = $1.to_s
71
- unmatched_tokens.push(key) unless @settings.client.key?(key)
72
- @settings.client[key].to_s
73
+ token = $1.to_s
74
+ begin
75
+ value = @settings.client.instance_eval(token)
76
+ if value.nil?
77
+ unmatched_tokens.push(token)
78
+ end
79
+ rescue NoMethodError
80
+ value = nil
81
+ unmatched_tokens.push(token)
82
+ end
83
+ value
73
84
  end
74
85
  if unmatched_tokens.empty?
75
86
  execute = proc do
@@ -97,6 +108,8 @@ module Sensu
97
108
  publish_result(check)
98
109
  @checks_in_progress.delete(check.name)
99
110
  end
111
+ else
112
+ @logger.debug('[execute] -- previous check execution still in progress -- ' + check.name)
100
113
  end
101
114
  else
102
115
  @logger.warn('[execute] -- unkown check -- ' + check.name)
@@ -110,60 +123,50 @@ module Sensu
110
123
 
111
124
  def setup_subscriptions
112
125
  @logger.debug('[subscribe] -- setup subscriptions')
113
- @check_queue = @amq.queue(String.unique, :exclusive => true)
114
- @settings.client.subscriptions.push('uchiwa').uniq!
115
- @settings.client.subscriptions.each do |exchange|
126
+ @check_request_queue = @amq.queue(String.unique, :exclusive => true)
127
+ @settings.client.subscriptions.uniq.each do |exchange|
116
128
  @logger.debug('[subscribe] -- queue binding to exchange -- ' + exchange)
117
- @check_queue.bind(@amq.fanout(exchange))
129
+ @check_request_queue.bind(@amq.fanout(exchange))
118
130
  end
119
- @check_queue.subscribe do |check_json|
120
- check = Hashie::Mash.new(JSON.parse(check_json))
121
- @logger.info('[subscribe] -- received check -- ' + check.name)
122
- if check.key?('matching')
123
- @logger.info('[subscribe] -- check requires matching -- ' + check.name)
124
- matches = check.matching.all? do |key, value|
125
- desired = case key
126
- when /^!/
127
- key = key.slice(1..-1)
128
- false
129
- else
130
- true
131
- end
132
- matched = case key
133
- when 'subscribes'
134
- value.all? do |subscription|
135
- @settings.client.subscriptions.include?(subscription)
136
- end
137
- else
138
- @settings.client[key] == value
139
- end
140
- desired == matched
141
- end
142
- if matches
143
- @logger.info('[subscribe] -- client matches -- ' + check.name)
144
- execute_check(check)
145
- else
146
- @logger.info('[subscribe] -- client does not match -- ' + check.name)
147
- end
148
- else
149
- execute_check(check)
150
- end
131
+ @check_request_queue.subscribe do |check_request_json|
132
+ check = Hashie::Mash.new(JSON.parse(check_request_json))
133
+ @logger.info('[subscribe] -- received check request -- ' + check.name)
134
+ execute_check(check)
151
135
  end
152
136
  end
153
137
 
154
138
  def setup_queue_monitor
155
139
  @logger.debug('[monitor] -- setup queue monitor')
156
- EM::PeriodicTimer.new(5) do
157
- unless @check_queue.subscribed?
140
+ @timers << EM::PeriodicTimer.new(5) do
141
+ unless @check_request_queue.subscribed?
158
142
  @logger.warn('[monitor] -- re-subscribing to subscriptions')
159
- @check_queue.delete
160
- EM::Timer.new(1) do
143
+ @check_request_queue.delete
144
+ @timers << EM::Timer.new(1) do
161
145
  setup_subscriptions
162
146
  end
163
147
  end
164
148
  end
165
149
  end
166
150
 
151
+ def setup_standalone(options={})
152
+ @logger.debug('[standalone] -- setup standalone')
153
+ standalone_count = 0
154
+ @settings.checks.each do |name, details|
155
+ if details.standalone
156
+ standalone_count += 1
157
+ check = Hashie::Mash.new(details.merge({:name => name}))
158
+ stagger = options[:test] ? 0 : 7
159
+ @timers << EM::Timer.new(stagger*standalone_count) do
160
+ interval = options[:test] ? 0.5 : details.interval
161
+ @timers << EM::PeriodicTimer.new(interval) do
162
+ check.issued = Time.now.to_i
163
+ execute_check(check)
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+
167
170
  def setup_socket
168
171
  @logger.debug('[socket] -- starting up socket')
169
172
  EM::start_server('127.0.0.1', 3030, ClientSocket) do |socket|
@@ -173,10 +176,29 @@ module Sensu
173
176
  end
174
177
  end
175
178
 
179
+ def stop_reactor
180
+ @logger.info('[stop] -- completing checks in progress')
181
+ complete_in_progress = EM::tick_loop do
182
+ if @checks_in_progress.empty?
183
+ :stop
184
+ end
185
+ end
186
+ complete_in_progress.on_stop do
187
+ @logger.warn('[stop] -- stopping reactor')
188
+ EM::PeriodicTimer.new(0.25) do
189
+ EM::stop_event_loop
190
+ end
191
+ end
192
+ end
193
+
176
194
  def stop(signal)
177
195
  @logger.warn('[stop] -- stopping sensu client -- ' + signal)
178
- EM::Timer.new(1) do
179
- EM::stop_event_loop
196
+ @timers.each do |timer|
197
+ timer.cancel
198
+ end
199
+ @logger.warn('[stop] -- unsubscribing from subscriptions')
200
+ @check_request_queue.unsubscribe do
201
+ stop_reactor
180
202
  end
181
203
  end
182
204
  end
@@ -201,7 +223,7 @@ module Sensu
201
223
  @logger.warn('[socket] -- a check name, exit status, and output are required -- e.g. {"name": "x", "status": 0, "output": "y"}')
202
224
  end
203
225
  rescue JSON::ParserError => error
204
- @logger.warn('[socket] -- check result must be valid JSON: ' + error.to_s)
226
+ @logger.warn('[socket] -- check result must be valid JSON: ' + error)
205
227
  end
206
228
  close_connection
207
229
  end
data/lib/sensu/config.rb CHANGED
@@ -15,85 +15,45 @@ require 'cabin/outputs/em-stdlib-logger'
15
15
 
16
16
  module Sensu
17
17
  class Config
18
- attr_accessor :settings, :logger
18
+ attr_accessor :logger, :settings
19
19
 
20
20
  DEFAULT_OPTIONS = {
21
- :log_file => '/tmp/sensu.log',
22
21
  :config_file => '/etc/sensu/config.json',
23
- :config_dir => '/etc/sensu/conf.d',
24
- :validate => true,
25
- :daemonize => false,
26
- :pid_file => '/tmp/' + File.basename($0) + '.pid',
27
- :service => File.basename($0)
22
+ :config_dir => '/etc/sensu/conf.d'
28
23
  }
29
24
 
30
25
  def initialize(options={})
31
26
  @options = DEFAULT_OPTIONS.merge(options)
32
- if options[:log_file]
33
- open_log
34
- end
35
- read_config
36
- if @options[:validate]
37
- validate_config
38
- end
27
+ setup_logging
28
+ setup_settings
39
29
  end
40
30
 
41
31
  def invalid_config(message)
42
32
  raise 'configuration invalid, ' + message
43
33
  end
44
34
 
45
- def open_log
46
- @logger = Cabin::Channel.new
47
- if File.writable?(@options[:log_file]) || !File.exist?(@options[:log_file]) && File.writable?(File.dirname(@options[:log_file]))
48
- ruby_logger = case @options[:service]
49
- when 'rake'
50
- Logger.new(@options[:log_file])
51
- else
35
+ def setup_logging
36
+ if @options[:log_file]
37
+ if File.writable?(@options[:log_file]) || !File.exist?(@options[:log_file]) && File.writable?(File.dirname(@options[:log_file]))
52
38
  STDOUT.reopen(@options[:log_file], 'a')
53
39
  STDERR.reopen(STDOUT)
54
40
  STDOUT.sync = true
55
- Logger.new(STDOUT)
41
+ else
42
+ invalid_config('log file is not writable: ' + @options[:log_file])
56
43
  end
57
- else
58
- invalid_config('log file is not writable: ' + @options[:log_file])
59
44
  end
60
- @logger.subscribe(Cabin::Outputs::EmStdlibLogger.new(ruby_logger))
45
+ @logger = Cabin::Channel.new
46
+ log_output = File.basename($0) == 'rake' ? '/tmp/sensu_test.log' : STDOUT
47
+ @logger.subscribe(Cabin::Outputs::EmStdlibLogger.new(Logger.new(log_output)))
61
48
  @logger.level = @options[:verbose] ? :debug : :info
62
49
  if Signal.list.include?('USR1')
63
50
  Signal.trap('USR1') do
64
51
  @logger.level = @logger.level == :info ? :debug : :info
65
52
  end
66
53
  end
67
- @logger
68
- end
69
-
70
- def read_config
71
- if File.readable?(@options[:config_file])
72
- begin
73
- @settings = Hashie::Mash.new(JSON.parse(File.open(@options[:config_file], 'r').read))
74
- rescue JSON::ParserError => error
75
- invalid_config('configuration file (' + @options[:config_file] + ') must be valid JSON: ' + error.to_s)
76
- end
77
- else
78
- invalid_config('configuration file does not exist or is not readable: ' + @options[:config_file])
79
- end
80
- if File.exists?(@options[:config_dir])
81
- Dir[@options[:config_dir] + '/**/*.json'].each do |snippet_file|
82
- begin
83
- snippet_hash = JSON.parse(File.open(snippet_file, 'r').read)
84
- rescue JSON::ParserError => error
85
- invalid_config('configuration snippet file (' + snippet_file + ') must be valid JSON: ' + error.to_s)
86
- end
87
- merged_settings = @settings.to_hash.deep_merge(snippet_hash)
88
- if @logger
89
- @logger.warn('[settings] configuration snippet (' + snippet_file + ') applied changes: ' + @settings.deep_diff(merged_settings).to_json)
90
- end
91
- @settings = Hashie::Mash.new(merged_settings)
92
- end
93
- end
94
54
  end
95
55
 
96
- def validate_common_config
56
+ def validate_common_settings
97
57
  @settings.checks.each do |name, details|
98
58
  unless details.interval.is_a?(Integer) && details.interval > 0
99
59
  invalid_config('missing interval for check ' + name)
@@ -101,8 +61,10 @@ module Sensu
101
61
  unless details.command.is_a?(String)
102
62
  invalid_config('missing command for check ' + name)
103
63
  end
104
- unless details.subscribers.is_a?(Array) && details.subscribers.count > 0
105
- invalid_config('missing subscribers for check ' + name)
64
+ unless details.standalone
65
+ unless details.subscribers.is_a?(Array) && details.subscribers.count > 0
66
+ invalid_config('missing subscribers for check ' + name)
67
+ end
106
68
  end
107
69
  if details.key?('handler')
108
70
  unless details.handler.is_a?(String)
@@ -117,7 +79,7 @@ module Sensu
117
79
  end
118
80
  end
119
81
 
120
- def validate_server_config
82
+ def validate_server_settings
121
83
  unless @settings.handlers.include?('default')
122
84
  invalid_config('missing default handler')
123
85
  end
@@ -125,28 +87,32 @@ module Sensu
125
87
  unless details.is_a?(Hash)
126
88
  invalid_config('hander details must be a hash ' + name)
127
89
  end
128
- unless details.key?('type')
90
+ unless details['type'].is_a?(String)
129
91
  invalid_config('missing type for handler ' + name)
130
92
  end
131
93
  case details['type']
132
94
  when 'pipe'
133
- unless details.key?('command')
95
+ unless details.command.is_a?(String)
134
96
  invalid_config('missing command for pipe handler ' + name)
135
97
  end
136
98
  when 'amqp'
137
- unless details.key?('exchange')
99
+ unless details.exchange.is_a?(Hash)
138
100
  invalid_config('missing exchange details for amqp handler ' + name)
139
101
  end
140
- unless details.exchange.key?('name')
102
+ unless details.exchange.name.is_a?(String)
141
103
  invalid_config('missing exchange name for amqp handler ' + name)
142
104
  end
105
+ when 'set'
106
+ unless details.handlers.is_a?(Array) && details.handlers.count > 0
107
+ invalid_config('missing handler set for handler ' + name)
108
+ end
143
109
  else
144
110
  invalid_config('unknown type for handler ' + name)
145
111
  end
146
112
  end
147
113
  end
148
114
 
149
- def validate_client_config
115
+ def validate_client_settings
150
116
  unless @settings.client.name.is_a?(String)
151
117
  invalid_config('client must have a name')
152
118
  end
@@ -166,54 +132,80 @@ module Sensu
166
132
  end
167
133
  end
168
134
 
169
- def validate_config
170
- if @logger
171
- @logger.debug('[config] -- validating configuration')
172
- end
135
+ def validate_settings
136
+ @logger.debug('[validate] -- validating configuration')
173
137
  has_keys(%w[rabbitmq checks])
174
- validate_common_config
175
- case @options[:service]
138
+ validate_common_settings
139
+ case File.basename($0)
176
140
  when 'rake'
177
141
  has_keys(%w[redis api handlers client])
178
- validate_server_config
179
- validate_client_config
142
+ validate_server_settings
143
+ validate_client_settings
180
144
  when 'sensu-server'
181
145
  has_keys(%w[redis handlers])
182
- validate_server_config
146
+ validate_server_settings
183
147
  when 'sensu-api'
184
148
  has_keys(%w[redis api])
185
149
  when 'sensu-client'
186
150
  has_keys(%w[client])
187
- validate_client_config
151
+ validate_client_settings
152
+ end
153
+ @logger.info('[validate] -- configuration valid -- running')
154
+ end
155
+
156
+ def setup_settings
157
+ if File.readable?(@options[:config_file])
158
+ begin
159
+ config_hash = JSON.parse(File.open(@options[:config_file], 'r').read)
160
+ rescue JSON::ParserError => error
161
+ invalid_config('configuration file (' + @options[:config_file] + ') must be valid JSON: ' + error)
162
+ end
163
+ @settings = Hashie::Mash.new(config_hash)
164
+ else
165
+ invalid_config('configuration file does not exist or is not readable: ' + @options[:config_file])
188
166
  end
189
- if @logger
190
- @logger.debug('[config] -- configuration valid -- running ' + @options[:service])
167
+ if File.exists?(@options[:config_dir])
168
+ Dir[@options[:config_dir] + '/**/*.json'].each do |snippet_file|
169
+ if File.readable?(snippet_file)
170
+ begin
171
+ snippet_hash = JSON.parse(File.open(snippet_file, 'r').read)
172
+ rescue JSON::ParserError => error
173
+ invalid_config('configuration snippet file (' + snippet_file + ') must be valid JSON: ' + error)
174
+ end
175
+ merged_settings = @settings.to_hash.deep_merge(snippet_hash)
176
+ @logger.warn('[settings] configuration snippet (' + snippet_file + ') applied changes: ' + @settings.deep_diff(merged_settings).to_json)
177
+ @settings = Hashie::Mash.new(merged_settings)
178
+ else
179
+ invalid_config('configuration snippet file is not readable: ' + snippet_file)
180
+ end
181
+ end
191
182
  end
183
+ validate_settings
192
184
  end
193
185
 
194
186
  def self.read_arguments(arguments)
195
187
  options = Hash.new
196
188
  optparse = OptionParser.new do |opts|
197
- opts.on('-h', '--help', 'Display this screen') do
189
+ opts.on('-h', '--help', 'Display this message') do
198
190
  puts opts
199
191
  exit
200
192
  end
201
- opts.on('-c', '--config FILE', 'Sensu JSON config FILE (default: /etc/sensu/config.json)') do |file|
193
+ opts.on('-c', '--config FILE', 'Sensu JSON config FILE. Default is /etc/sensu/config.json') do |file|
202
194
  options[:config_file] = file
203
195
  end
204
- opts.on('-d', '--config_dir DIR', 'Directory for supplemental Sensu JSON config files (default: /etc/sensu/conf.d/)') do |dir|
196
+ opts.on('-d', '--config_dir DIR', 'DIR for supplemental Sensu JSON config files. Default is /etc/sensu/conf.d/') do |dir|
205
197
  options[:config_dir] = dir
206
198
  end
207
- opts.on('-l', '--log FILE', 'Sensu log FILE (default: /tmp/sensu.log)') do |file|
199
+ opts.on('-l', '--log FILE', 'Log to a given FILE. Default is to log to stdout') do |file|
208
200
  options[:log_file] = file
209
201
  end
210
- opts.on('-v', '--verbose', 'Enable verbose logging (default: false)') do
202
+ opts.on('-v', '--verbose', 'Enable verbose logging') do
211
203
  options[:verbose] = true
212
204
  end
213
- opts.on('-b', '--background', 'Fork into backgaround (daemon mode) (default: false)') do
205
+ opts.on('-b', '--background', 'Fork into the background') do
214
206
  options[:daemonize] = true
215
207
  end
216
- opts.on('-p', '--pid_file FILE', 'Sensu PID FILE (default: ' + DEFAULT_OPTIONS[:pid_file] + ')') do |file|
208
+ opts.on('-p', '--pid_file FILE', 'Write the PID to a given FILE') do |file|
217
209
  options[:pid_file] = file
218
210
  end
219
211
  end
@@ -33,7 +33,13 @@ class Hash
33
33
 
34
34
  def deep_merge(hash)
35
35
  merger = proc do |key, value1, value2|
36
- value1.is_a?(Hash) && value2.is_a?(Hash) ? value1.merge(value2, &merger) : 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
37
43
  end
38
44
  self.merge(hash, &merger)
39
45
  end
data/lib/sensu/server.rb CHANGED
@@ -35,9 +35,10 @@ module Sensu
35
35
 
36
36
  def initialize(options={})
37
37
  config = Sensu::Config.new(options)
38
+ @logger = config.logger
38
39
  @settings = config.settings
39
- @logger = config.logger || config.open_log
40
40
  @timers = Array.new
41
+ @handlers_in_progress = 0
41
42
  end
42
43
 
43
44
  def setup_redis
@@ -72,14 +73,21 @@ module Sensu
72
73
  else
73
74
  ['default']
74
75
  end
76
+ handlers.map! do |handler|
77
+ @settings.handlers[handler]['type'] == 'set' ? @settings.handlers[handler].handlers : handler
78
+ end
79
+ handlers.flatten!
80
+ handlers.uniq!
75
81
  report = proc do |output|
76
82
  output.split(/\n+/).each do |line|
77
83
  @logger.info('[handler] -- ' + line)
78
84
  end
85
+ @handlers_in_progress -= 1
79
86
  end
80
87
  handlers.each do |handler|
81
88
  if @settings.handlers.key?(handler)
82
89
  @logger.debug('[event] -- handling event -- ' + [handler, event.client.name, event.check.name].join(' -- '))
90
+ @handlers_in_progress += 1
83
91
  details = @settings.handlers[handler]
84
92
  case details['type']
85
93
  when 'pipe'
@@ -93,7 +101,7 @@ module Sensu
93
101
  output = io.read
94
102
  end
95
103
  rescue Errno::EPIPE => error
96
- output = handler + ' -- broken pipe: ' + error.to_s
104
+ output = handler + ' -- broken pipe: ' + error
97
105
  end
98
106
  end
99
107
  output
@@ -106,6 +114,10 @@ module Sensu
106
114
  @logger.debug('[event] -- publishing event to rabbitmq exchange -- ' + [exchange, event.client.name, event.check.name].join(' -- '))
107
115
  payload = details.send_only_check_output ? event.check.output : event.to_json
108
116
  @amq.method(exchange_type).call(exchange, exchange_options).publish(payload)
117
+ @handlers_in_progress -= 1
118
+ when 'set'
119
+ @logger.warn('[event] -- handler sets cannot be nested -- ' + handler)
120
+ @handlers_in_progress -= 1
109
121
  end
110
122
  else
111
123
  @logger.warn('[event] -- unknown handler -- ' + handler)
@@ -214,20 +226,13 @@ module Sensu
214
226
  stagger = options[:test] ? 0 : 7
215
227
  @settings.checks.each_with_index do |(name, details), index|
216
228
  check_request = Hashie::Mash.new({:name => name})
217
- unless details.publish == false
229
+ unless details.publish == false || details.standalone
218
230
  @timers << EM::Timer.new(stagger*index) do
219
- details.subscribers.each do |target|
220
- if target.is_a?(Hash)
221
- @logger.debug('[publisher] -- check requires matching -- ' + target.to_hash.to_s + ' -- ' + name)
222
- check_request.matching = target
223
- exchange = 'uchiwa'
224
- else
225
- exchange = target
226
- end
231
+ details.subscribers.each do |exchange|
227
232
  interval = options[:test] ? 0.5 : details.interval
228
233
  @timers << EM::PeriodicTimer.new(interval) do
229
- check_request.issued = Time.now.to_i
230
234
  @logger.info('[publisher] -- publishing check request -- ' + name + ' -- ' + exchange)
235
+ check_request.issued = Time.now.to_i
231
236
  @amq.fanout(exchange).publish(check_request.to_json)
232
237
  end
233
238
  end
@@ -333,9 +338,19 @@ module Sensu
333
338
  end
334
339
 
335
340
  def stop_reactor
336
- @logger.warn('[stop] -- stopping reactor')
337
- EM::Timer.new(3) do
338
- EM::stop_event_loop
341
+ EM::Timer.new(1) do
342
+ @logger.info('[stop] -- completing handlers in progress')
343
+ complete_in_progress = EM::tick_loop do
344
+ if @handlers_in_progress == 0
345
+ :stop
346
+ end
347
+ end
348
+ complete_in_progress.on_stop do
349
+ @logger.warn('[stop] -- stopping reactor')
350
+ EM::PeriodicTimer.new(0.25) do
351
+ EM::stop_event_loop
352
+ end
353
+ end
339
354
  end
340
355
  end
341
356
 
@@ -344,10 +359,10 @@ module Sensu
344
359
  @timers.each do |timer|
345
360
  timer.cancel
346
361
  end
362
+ @logger.warn('[stop] -- unsubscribing from keepalives')
347
363
  @keepalive_queue.unsubscribe do
348
- @logger.warn('[stop] -- unsubscribed from rabbitmq queue -- keepalives')
364
+ @logger.warn('[stop] -- unsubscribing from results')
349
365
  @result_queue.unsubscribe do
350
- @logger.warn('[stop] -- unsubscribed from rabbitmq queue -- results')
351
366
  if @is_master
352
367
  @redis.del('lock:master').callback do
353
368
  @logger.warn('[stop] -- resigned as master')
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: 57
5
- prerelease: false
4
+ hash: 31098113
5
+ prerelease: true
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 1
10
- version: 0.9.1
9
+ - 2
10
+ - beta
11
+ version: 0.9.2.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: 2011-12-27 00:00:00 -08:00
20
+ date: 2012-01-04 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: