sensu 0.9.5 → 0.9.6.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/README.org +8 -42
- data/bin/sensu-api +5 -2
- data/bin/sensu-client +5 -2
- data/bin/sensu-server +5 -2
- data/lib/sensu/api.rb +125 -95
- data/lib/sensu/base.rb +57 -0
- data/lib/sensu/cli.rb +37 -0
- data/lib/sensu/client.rb +126 -129
- data/lib/sensu/constants.rb +8 -0
- data/lib/sensu/logger.rb +39 -0
- data/lib/sensu/patches/ruby.rb +4 -80
- data/lib/sensu/process.rb +57 -0
- data/lib/sensu/server.rb +229 -163
- data/lib/sensu/settings.rb +280 -0
- data/lib/sensu/socket.rb +52 -0
- data/sensu.gemspec +22 -23
- metadata +171 -185
- data/lib/sensu/config.rb +0 -266
- data/lib/sensu/version.rb +0 -3
data/lib/sensu/logger.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module Sensu
|
2
|
+
class Logger
|
3
|
+
def initialize(options={})
|
4
|
+
@logger = Cabin::Channel.get
|
5
|
+
@logger.subscribe(STDOUT)
|
6
|
+
@logger.level = options[:verbose] ? :debug : options[:log_level] || :info
|
7
|
+
reopen(options)
|
8
|
+
setup_traps(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def reopen(options={})
|
12
|
+
unless options[:log_file].nil?
|
13
|
+
if File.writable?(options[:log_file]) ||
|
14
|
+
!File.exist?(options[:log_file]) && File.writable?(File.dirname(options[:log_file]))
|
15
|
+
STDOUT.reopen(options[:log_file], 'a')
|
16
|
+
STDERR.reopen(STDOUT)
|
17
|
+
STDOUT.sync = true
|
18
|
+
else
|
19
|
+
@logger.error('log file is not writable', {
|
20
|
+
:log_file => options[:log_file]
|
21
|
+
})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def setup_traps(options={})
|
27
|
+
if Signal.list.include?('USR1')
|
28
|
+
Signal.trap('USR1') do
|
29
|
+
@logger.level = @logger.level == :info ? :debug : :info
|
30
|
+
end
|
31
|
+
end
|
32
|
+
if Signal.list.include?('USR2')
|
33
|
+
Signal.trap('USR2') do
|
34
|
+
reopen(options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/sensu/patches/ruby.rb
CHANGED
@@ -1,85 +1,9 @@
|
|
1
|
-
class Array
|
2
|
-
def deep_merge(other_array, &merger)
|
3
|
-
concat(other_array).uniq
|
4
|
-
end
|
5
|
-
end
|
6
|
-
|
7
1
|
class Hash
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
item.map do |i|
|
12
|
-
symbolize_keys(i)
|
13
|
-
end
|
14
|
-
when Hash
|
15
|
-
Hash[
|
16
|
-
item.map do |key, value|
|
17
|
-
new_key = key.is_a?(String) ? key.to_sym : key
|
18
|
-
new_value = symbolize_keys(value)
|
19
|
-
[new_key, new_value]
|
20
|
-
end
|
21
|
-
]
|
2
|
+
def method_missing(method, *arguments, &block)
|
3
|
+
if has_key?(method)
|
4
|
+
self[method]
|
22
5
|
else
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def deep_diff(hash)
|
28
|
-
(self.keys | hash.keys).inject(Hash.new) do |diff, key|
|
29
|
-
unless self[key] == hash[key]
|
30
|
-
if self[key].is_a?(Hash) && hash[key].is_a?(Hash)
|
31
|
-
diff[key] = self[key].deep_diff(hash[key])
|
32
|
-
else
|
33
|
-
diff[key] = [self[key], hash[key]]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
diff
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def deep_merge(other_hash, &merger)
|
41
|
-
merger ||= proc do |key, oldval, newval|
|
42
|
-
oldval.deep_merge(newval, &merger) rescue newval
|
43
|
-
end
|
44
|
-
merge(other_hash, &merger)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
module Process
|
49
|
-
def self.write_pid(pid_file)
|
50
|
-
if pid_file.nil?
|
51
|
-
raise('a pid file path must be provided')
|
52
|
-
end
|
53
|
-
begin
|
54
|
-
File.open(pid_file, 'w') do |file|
|
55
|
-
file.write(self.pid.to_s + "\n")
|
56
|
-
end
|
57
|
-
rescue
|
58
|
-
raise('could not write to pid file: ' + pid_file)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.daemonize
|
63
|
-
srand
|
64
|
-
fork and exit
|
65
|
-
unless session_id = self.setsid
|
66
|
-
raise('cannot detach from controlling terminal')
|
67
|
-
end
|
68
|
-
trap 'SIGHUP', 'IGNORE'
|
69
|
-
if pid = fork
|
70
|
-
exit
|
71
|
-
end
|
72
|
-
Dir.chdir('/')
|
73
|
-
ObjectSpace.each_object(IO) do |io|
|
74
|
-
unless [STDIN, STDOUT, STDERR].include?(io)
|
75
|
-
begin
|
76
|
-
unless io.closed?
|
77
|
-
io.close
|
78
|
-
end
|
79
|
-
rescue
|
80
|
-
end
|
81
|
-
end
|
6
|
+
super
|
82
7
|
end
|
83
|
-
return session_id
|
84
8
|
end
|
85
9
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Sensu
|
2
|
+
class Process
|
3
|
+
def initialize(options={})
|
4
|
+
@logger = Cabin::Channel.get
|
5
|
+
if options[:daemonize]
|
6
|
+
daemonize
|
7
|
+
end
|
8
|
+
if options[:pid_file]
|
9
|
+
write_pid(options[:pid_file])
|
10
|
+
end
|
11
|
+
setup_eventmachine
|
12
|
+
end
|
13
|
+
|
14
|
+
def write_pid(pid_file)
|
15
|
+
begin
|
16
|
+
File.open(pid_file, 'w') do |file|
|
17
|
+
file.puts(::Process.pid)
|
18
|
+
end
|
19
|
+
rescue
|
20
|
+
@logger.fatal('could not write to pid file', {
|
21
|
+
:pid_file => pid_file
|
22
|
+
})
|
23
|
+
exit 2
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def daemonize
|
28
|
+
srand
|
29
|
+
if fork
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
unless ::Process.setsid
|
33
|
+
@logger.fatal('cannot detach from controlling terminal')
|
34
|
+
exit 2
|
35
|
+
end
|
36
|
+
Signal.trap('SIGHUP', 'IGNORE')
|
37
|
+
if fork
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
Dir.chdir('/')
|
41
|
+
ObjectSpace.each_object(IO) do |io|
|
42
|
+
unless [STDIN, STDOUT, STDERR].include?(io)
|
43
|
+
begin
|
44
|
+
unless io.closed?
|
45
|
+
io.close
|
46
|
+
end
|
47
|
+
rescue
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def setup_eventmachine
|
54
|
+
EM::threadpool_size = 14
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/sensu/server.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '
|
1
|
+
require File.join(File.dirname(__FILE__), 'base')
|
2
2
|
|
3
3
|
require 'redis'
|
4
4
|
|
@@ -6,17 +6,10 @@ require File.join(File.dirname(__FILE__), 'patches', 'redis')
|
|
6
6
|
|
7
7
|
module Sensu
|
8
8
|
class Server
|
9
|
-
|
9
|
+
attr_reader :redis, :amq, :is_master
|
10
10
|
|
11
11
|
def self.run(options={})
|
12
12
|
server = self.new(options)
|
13
|
-
if options[:daemonize]
|
14
|
-
Process.daemonize
|
15
|
-
end
|
16
|
-
if options[:pid_file]
|
17
|
-
Process.write_pid(options[:pid_file])
|
18
|
-
end
|
19
|
-
EM::threadpool_size = 14
|
20
13
|
EM::run do
|
21
14
|
server.setup_redis
|
22
15
|
server.setup_rabbitmq
|
@@ -34,116 +27,165 @@ module Sensu
|
|
34
27
|
end
|
35
28
|
|
36
29
|
def initialize(options={})
|
37
|
-
|
38
|
-
@logger =
|
39
|
-
@settings =
|
30
|
+
base = Sensu::Base.new(options)
|
31
|
+
@logger = base.logger
|
32
|
+
@settings = base.settings
|
40
33
|
@timers = Array.new
|
41
34
|
@handlers_in_progress = 0
|
42
35
|
end
|
43
36
|
|
44
37
|
def setup_redis
|
45
|
-
@logger.debug('
|
46
|
-
|
38
|
+
@logger.debug('connecting to redis', {
|
39
|
+
:settings => @settings[:redis]
|
40
|
+
})
|
41
|
+
@redis = Redis.connect(@settings[:redis])
|
47
42
|
end
|
48
43
|
|
49
44
|
def setup_rabbitmq
|
50
|
-
@logger.debug('
|
51
|
-
|
45
|
+
@logger.debug('connecting to rabbitmq', {
|
46
|
+
:settings => @settings[:rabbitmq]
|
47
|
+
})
|
48
|
+
@rabbitmq = AMQP.connect(@settings[:rabbitmq])
|
52
49
|
@amq = AMQP::Channel.new(@rabbitmq)
|
53
50
|
end
|
54
51
|
|
55
52
|
def setup_keepalives
|
56
|
-
@logger.debug('
|
53
|
+
@logger.debug('subscribing to keepalives')
|
57
54
|
@keepalive_queue = @amq.queue('keepalives')
|
58
|
-
@keepalive_queue.subscribe do |
|
59
|
-
client =
|
60
|
-
@logger.debug('
|
61
|
-
|
62
|
-
|
55
|
+
@keepalive_queue.subscribe do |payload|
|
56
|
+
client = JSON.parse(payload, :symbolize_names => true)
|
57
|
+
@logger.debug('received keepalive', {
|
58
|
+
:client => client
|
59
|
+
})
|
60
|
+
@redis.set('client:' + client[:name], client.to_json).callback do
|
61
|
+
@redis.sadd('clients', client[:name])
|
63
62
|
end
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
67
|
-
def
|
68
|
-
|
69
|
-
when
|
70
|
-
[
|
71
|
-
when
|
72
|
-
|
66
|
+
def check_handlers(check)
|
67
|
+
handler_list = case
|
68
|
+
when check.has_key?(:handler)
|
69
|
+
[check[:handler]]
|
70
|
+
when check.has_key?(:handlers)
|
71
|
+
check[:handlers]
|
73
72
|
else
|
74
73
|
['default']
|
75
74
|
end
|
76
|
-
|
77
|
-
|
75
|
+
handler_list.reject! do |handler_name|
|
76
|
+
!@settings.handler_exists?(handler_name)
|
77
|
+
end
|
78
|
+
handler_list.map! do |handler_name|
|
79
|
+
if @settings[:handlers][handler_name][:type] == 'set'
|
80
|
+
@settings[:handlers][handler_name][:handlers]
|
81
|
+
else
|
82
|
+
handler_name
|
83
|
+
end
|
84
|
+
end
|
85
|
+
handler_list.flatten!
|
86
|
+
handler_list.uniq!
|
87
|
+
handler_list.reject! do |handler_name|
|
88
|
+
!@settings.handler_exists?(handler_name)
|
78
89
|
end
|
79
|
-
|
80
|
-
|
90
|
+
handler_list.map do |handler_name|
|
91
|
+
@settings[:handlers][handler_name].merge(:name => handler_name)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def handle_event(event)
|
81
96
|
report = proc do |output|
|
82
|
-
output.
|
83
|
-
|
97
|
+
if output.is_a?(String)
|
98
|
+
output.split(/\n+/).each do |line|
|
99
|
+
@logger.info('handler output', {
|
100
|
+
:output => line
|
101
|
+
})
|
102
|
+
end
|
84
103
|
end
|
85
104
|
@handlers_in_progress -= 1
|
86
105
|
end
|
106
|
+
handlers = check_handlers(event[:check])
|
87
107
|
handlers.each do |handler|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
rescue Errno::ENOENT => error
|
103
|
-
handler + ' -- does not exist: ' + error.to_s
|
104
|
-
rescue Errno::EPIPE => error
|
105
|
-
handler + ' -- broken pipe: ' + error.to_s
|
106
|
-
rescue => error
|
107
|
-
handler + ' -- unexpected error: ' + error.to_s
|
108
|
-
end
|
108
|
+
@logger.debug('handling event', {
|
109
|
+
:event => event,
|
110
|
+
:handler => handler
|
111
|
+
})
|
112
|
+
@handlers_in_progress += 1
|
113
|
+
case handler[:type]
|
114
|
+
when 'pipe'
|
115
|
+
execute = proc do
|
116
|
+
begin
|
117
|
+
IO.popen(handler[:command] + ' 2>&1', 'r+') do |io|
|
118
|
+
io.write(event.to_json)
|
119
|
+
io.close_write
|
120
|
+
io.read
|
109
121
|
end
|
122
|
+
rescue Errno::ENOENT => error
|
123
|
+
@logger.error('handler does not exist', {
|
124
|
+
:event => event,
|
125
|
+
:handler => handler,
|
126
|
+
:error => error.to_s
|
127
|
+
})
|
128
|
+
rescue Errno::EPIPE => error
|
129
|
+
@logger.error('broken pipe', {
|
130
|
+
:event => event,
|
131
|
+
:handler => handler,
|
132
|
+
:error => error.to_s
|
133
|
+
})
|
134
|
+
rescue => error
|
135
|
+
@logger.error('unexpected error', {
|
136
|
+
:event => event,
|
137
|
+
:handler => handler,
|
138
|
+
:error => error.to_s
|
139
|
+
})
|
110
140
|
end
|
111
|
-
EM::defer(execute, report)
|
112
|
-
when 'amqp'
|
113
|
-
exchange = details.exchange.name
|
114
|
-
exchange_type = details.exchange.key?('type') ? details.exchange['type'].to_sym : :direct
|
115
|
-
exchange_options = details.exchange.reject { |key, value| %w[name type].include?(key) }
|
116
|
-
@logger.debug('[event] -- publishing event to rabbitmq exchange -- ' + [exchange, event.client.name, event.check.name].join(' -- '))
|
117
|
-
payload = details.send_only_check_output ? event.check.output : event.to_json
|
118
|
-
unless payload.empty?
|
119
|
-
@amq.method(exchange_type).call(exchange, exchange_options).publish(payload)
|
120
|
-
end
|
121
|
-
@handlers_in_progress -= 1
|
122
|
-
when 'set'
|
123
|
-
@logger.warn('[event] -- handler sets cannot be nested -- ' + handler)
|
124
|
-
@handlers_in_progress -= 1
|
125
141
|
end
|
126
|
-
|
127
|
-
|
142
|
+
EM::defer(execute, report)
|
143
|
+
when 'amqp'
|
144
|
+
exchange_name = handler[:exchange][:name]
|
145
|
+
exchange_type = handler[:exchange].has_key?(:type) ? handler[:exchange][:type].to_sym : :direct
|
146
|
+
exchange_options = handler[:exchange].reject do |key, value|
|
147
|
+
[:name, :type].include?(key)
|
148
|
+
end
|
149
|
+
@logger.debug('publishing event to an amqp exchange', {
|
150
|
+
:event => event,
|
151
|
+
:exchange => handler[:exchange]
|
152
|
+
})
|
153
|
+
payload = handler[:send_only_check_output] ? event[:check][:output] : event.to_json
|
154
|
+
unless payload.empty?
|
155
|
+
@amq.method(exchange_type).call(exchange_name, exchange_options).publish(payload)
|
156
|
+
end
|
157
|
+
@handlers_in_progress -= 1
|
158
|
+
when 'set'
|
159
|
+
@logger.error('handler sets cannot be nested', {
|
160
|
+
:handler => handler
|
161
|
+
})
|
162
|
+
@handlers_in_progress -= 1
|
128
163
|
end
|
129
164
|
end
|
130
165
|
end
|
131
166
|
|
132
167
|
def process_result(result)
|
133
|
-
@logger.debug('
|
134
|
-
|
168
|
+
@logger.debug('processing result', {
|
169
|
+
:result => result
|
170
|
+
})
|
171
|
+
@redis.get('client:' + result[:client]).callback do |client_json|
|
135
172
|
unless client_json.nil?
|
136
|
-
client =
|
137
|
-
check =
|
138
|
-
|
173
|
+
client = JSON.parse(client_json, :symbolize_names => true)
|
174
|
+
check = case
|
175
|
+
when @settings.check_exists?(result[:check][:name])
|
176
|
+
@settings[:checks][result[:check][:name]].merge(result[:check])
|
177
|
+
else
|
178
|
+
result[:check]
|
179
|
+
end
|
180
|
+
event = {
|
139
181
|
:client => client,
|
140
182
|
:check => check,
|
141
183
|
:occurrences => 1
|
142
|
-
|
143
|
-
history_key = 'history:' + client
|
144
|
-
@redis.rpush(history_key, check
|
184
|
+
}
|
185
|
+
history_key = 'history:' + client[:name] + ':' + check[:name]
|
186
|
+
@redis.rpush(history_key, check[:status]).callback do
|
145
187
|
@redis.lrange(history_key, -21, -1).callback do |history|
|
146
|
-
event
|
188
|
+
event[:check][:history] = history
|
147
189
|
total_state_change = 0
|
148
190
|
unless history.count < 21
|
149
191
|
state_changes = 0
|
@@ -159,61 +201,67 @@ module Sensu
|
|
159
201
|
total_state_change = (state_changes.fdiv(20) * 100).to_i
|
160
202
|
@redis.lpop(history_key)
|
161
203
|
end
|
162
|
-
@redis.hget('events:' + client
|
163
|
-
previous_occurrence = event_json ?
|
204
|
+
@redis.hget('events:' + client[:name], check[:name]).callback do |event_json|
|
205
|
+
previous_occurrence = event_json ? JSON.parse(event_json, :symbolize_names => true) : false
|
164
206
|
is_flapping = false
|
165
|
-
if check.
|
166
|
-
was_flapping = previous_occurrence ? previous_occurrence
|
207
|
+
if check.has_key?(:low_flap_threshold) && check.has_key?(:high_flap_threshold)
|
208
|
+
was_flapping = previous_occurrence ? previous_occurrence[:flapping] : false
|
167
209
|
is_flapping = case
|
168
|
-
when total_state_change >= check
|
210
|
+
when total_state_change >= check[:high_flap_threshold]
|
169
211
|
true
|
170
|
-
when was_flapping && total_state_change <= check
|
212
|
+
when was_flapping && total_state_change <= check[:low_flap_threshold]
|
171
213
|
false
|
172
214
|
else
|
173
215
|
was_flapping
|
174
216
|
end
|
175
217
|
end
|
176
|
-
if check
|
177
|
-
if previous_occurrence && check
|
178
|
-
event
|
218
|
+
if check[:status] != 0
|
219
|
+
if previous_occurrence && check[:status] == previous_occurrence[:status]
|
220
|
+
event[:occurrences] = previous_occurrence[:occurrences] += 1
|
179
221
|
end
|
180
|
-
@redis.hset('events:' + client
|
181
|
-
:output => check
|
182
|
-
:status => check
|
183
|
-
:issued =>
|
222
|
+
@redis.hset('events:' + client[:name], check[:name], {
|
223
|
+
:output => check[:output],
|
224
|
+
:status => check[:status],
|
225
|
+
:issued => check[:issued],
|
184
226
|
:flapping => is_flapping,
|
185
|
-
:occurrences => event
|
227
|
+
:occurrences => event[:occurrences]
|
186
228
|
}.to_json).callback do
|
187
|
-
unless check
|
188
|
-
event
|
189
|
-
event
|
229
|
+
unless check[:handle] == false
|
230
|
+
event[:check][:flapping] = is_flapping
|
231
|
+
event[:action] = 'create'
|
190
232
|
handle_event(event)
|
191
233
|
else
|
192
|
-
@logger.debug('
|
234
|
+
@logger.debug('handling disabled', {
|
235
|
+
:event => event
|
236
|
+
})
|
193
237
|
end
|
194
238
|
end
|
195
239
|
elsif previous_occurrence
|
196
240
|
unless is_flapping
|
197
|
-
unless check
|
198
|
-
@redis.hdel('events:' + client
|
199
|
-
unless check
|
200
|
-
event
|
241
|
+
unless check[:auto_resolve] == false && !check[:force_resolve]
|
242
|
+
@redis.hdel('events:' + client[:name], check[:name]).callback do
|
243
|
+
unless check[:handle] == false
|
244
|
+
event[:action] = 'resolve'
|
201
245
|
handle_event(event)
|
202
246
|
else
|
203
|
-
@logger.debug('
|
247
|
+
@logger.debug('handling disabled', {
|
248
|
+
:event => event
|
249
|
+
})
|
204
250
|
end
|
205
251
|
end
|
206
252
|
end
|
207
253
|
else
|
208
|
-
@logger.debug('
|
209
|
-
|
210
|
-
|
211
|
-
|
254
|
+
@logger.debug('check is flapping', {
|
255
|
+
:event => event
|
256
|
+
})
|
257
|
+
@redis.hset('events:' + client[:name], check[:name], previous_occurrence.merge(:flapping => true).to_json).callback do
|
258
|
+
if check[:type] == 'metric'
|
259
|
+
event[:check][:flapping] = is_flapping
|
212
260
|
handle_event(event)
|
213
261
|
end
|
214
262
|
end
|
215
263
|
end
|
216
|
-
elsif check[
|
264
|
+
elsif check[:type] == 'metric'
|
217
265
|
handle_event(event)
|
218
266
|
end
|
219
267
|
end
|
@@ -224,29 +272,38 @@ module Sensu
|
|
224
272
|
end
|
225
273
|
|
226
274
|
def setup_results
|
227
|
-
@logger.debug('
|
275
|
+
@logger.debug('subscribing to results')
|
228
276
|
@result_queue = @amq.queue('results')
|
229
|
-
@result_queue.subscribe do |
|
230
|
-
result =
|
231
|
-
@logger.
|
277
|
+
@result_queue.subscribe do |payload|
|
278
|
+
result = JSON.parse(payload, :symbolize_names => true)
|
279
|
+
@logger.debug('received result', {
|
280
|
+
:result => result
|
281
|
+
})
|
232
282
|
process_result(result)
|
233
283
|
end
|
234
284
|
end
|
235
285
|
|
236
286
|
def setup_publisher(options={})
|
237
|
-
@logger.debug('
|
287
|
+
@logger.debug('scheduling check requests')
|
288
|
+
check_count = 0
|
238
289
|
stagger = options[:test] ? 0 : 7
|
239
|
-
@settings.checks.
|
240
|
-
|
241
|
-
|
242
|
-
@timers << EM::Timer.new(stagger *
|
243
|
-
|
244
|
-
|
245
|
-
@
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
290
|
+
@settings.checks.each do |check|
|
291
|
+
unless check[:publish] == false || check[:standalone]
|
292
|
+
check_count += 1
|
293
|
+
@timers << EM::Timer.new(stagger * check_count) do
|
294
|
+
interval = options[:test] ? 0.5 : check[:interval]
|
295
|
+
@timers << EM::PeriodicTimer.new(interval) do
|
296
|
+
unless @rabbitmq.reconnecting?
|
297
|
+
payload = {
|
298
|
+
:name => check[:name],
|
299
|
+
:issued => Time.now.to_i
|
300
|
+
}
|
301
|
+
@logger.info('publishing check request', {
|
302
|
+
:payload => payload,
|
303
|
+
:subscribers => check[:subscribers]
|
304
|
+
})
|
305
|
+
check[:subscribers].uniq.each do |exchange_name|
|
306
|
+
@amq.fanout(exchange_name).publish(payload.to_json)
|
250
307
|
end
|
251
308
|
end
|
252
309
|
end
|
@@ -256,39 +313,44 @@ module Sensu
|
|
256
313
|
end
|
257
314
|
|
258
315
|
def setup_keepalive_monitor
|
259
|
-
@logger.debug('
|
316
|
+
@logger.debug('monitoring client keepalives')
|
260
317
|
@timers << EM::PeriodicTimer.new(30) do
|
261
|
-
@logger.debug('
|
318
|
+
@logger.debug('checking for stale client info')
|
262
319
|
@redis.smembers('clients').callback do |clients|
|
263
|
-
clients.each do |
|
264
|
-
@redis.get('client:' +
|
265
|
-
client =
|
266
|
-
time_since_last_keepalive = Time.now.to_i - client
|
267
|
-
|
268
|
-
:client => client.name,
|
269
|
-
:check => {
|
270
|
-
:name => 'keepalive',
|
271
|
-
:issued => Time.now.to_i
|
272
|
-
}
|
273
|
-
)
|
320
|
+
clients.each do |client_name|
|
321
|
+
@redis.get('client:' + client_name).callback do |client_json|
|
322
|
+
client = JSON.parse(client_json, :symbolize_names => true)
|
323
|
+
time_since_last_keepalive = Time.now.to_i - client[:timestamp]
|
324
|
+
check = Hash.new
|
274
325
|
case
|
275
326
|
when time_since_last_keepalive >= 180
|
276
|
-
|
277
|
-
|
278
|
-
@amq.queue('results').publish(result.to_json)
|
327
|
+
check[:output] = 'No keep-alive sent from host in over 180 seconds'
|
328
|
+
check[:status] = 2
|
279
329
|
when time_since_last_keepalive >= 120
|
280
|
-
|
281
|
-
|
282
|
-
@amq.queue('results').publish(result.to_json)
|
330
|
+
check[:output] = 'No keep-alive sent from host in over 120 seconds'
|
331
|
+
check[:status] = 1
|
283
332
|
else
|
284
|
-
@redis.hexists('events:' +
|
333
|
+
@redis.hexists('events:' + client[:name], 'keepalive').callback do |exists|
|
285
334
|
if exists
|
286
|
-
|
287
|
-
|
288
|
-
@amq.queue('results').publish(result.to_json)
|
335
|
+
check[:output] = 'Keep-alive sent from host'
|
336
|
+
check[:status] = 0
|
289
337
|
end
|
290
338
|
end
|
291
339
|
end
|
340
|
+
unless check.empty?
|
341
|
+
check.merge(
|
342
|
+
:name => 'keepalive',
|
343
|
+
:issued => Time.now.to_i
|
344
|
+
)
|
345
|
+
payload = {
|
346
|
+
:client => client[:name],
|
347
|
+
:check => check
|
348
|
+
}
|
349
|
+
@logger.info('publishing check result', {
|
350
|
+
:payload => payload
|
351
|
+
})
|
352
|
+
@amq.queue('results').publish(payload.to_json)
|
353
|
+
end
|
292
354
|
end
|
293
355
|
end
|
294
356
|
end
|
@@ -304,16 +366,16 @@ module Sensu
|
|
304
366
|
@is_master ||= false
|
305
367
|
@redis.setnx('lock:master', Time.now.to_i).callback do |created|
|
306
368
|
if created
|
307
|
-
@logger.info('[master] -- i am the master')
|
308
369
|
@is_master = true
|
370
|
+
@logger.info('i am the master')
|
309
371
|
master_duties
|
310
372
|
else
|
311
373
|
@redis.get('lock:master') do |timestamp|
|
312
374
|
if Time.now.to_i - timestamp.to_i >= 60
|
313
375
|
@redis.getset('lock:master', Time.now.to_i).callback do |previous|
|
314
376
|
if previous == timestamp
|
315
|
-
@logger.info('[master] -- i am now the master')
|
316
377
|
@is_master = true
|
378
|
+
@logger.info('i am now the master')
|
317
379
|
master_duties
|
318
380
|
end
|
319
381
|
end
|
@@ -326,13 +388,13 @@ module Sensu
|
|
326
388
|
def resign_as_master(&block)
|
327
389
|
if @is_master
|
328
390
|
@redis.del('lock:master').callback do
|
329
|
-
@logger.warn('
|
391
|
+
@logger.warn('resigned as master')
|
330
392
|
if block
|
331
393
|
block.call
|
332
394
|
end
|
333
395
|
end
|
334
396
|
else
|
335
|
-
@logger.warn('
|
397
|
+
@logger.warn('not currently master')
|
336
398
|
if block
|
337
399
|
block.call
|
338
400
|
end
|
@@ -343,9 +405,8 @@ module Sensu
|
|
343
405
|
request_master_election
|
344
406
|
@timers << EM::PeriodicTimer.new(20) do
|
345
407
|
if @is_master
|
346
|
-
|
347
|
-
|
348
|
-
@logger.debug('[master] -- updated master lock timestamp -- ' + timestamp.to_s)
|
408
|
+
@redis.set('lock:master', Time.now.to_i).callback do
|
409
|
+
@logger.debug('updated master lock timestamp')
|
349
410
|
end
|
350
411
|
else
|
351
412
|
request_master_election
|
@@ -354,17 +415,17 @@ module Sensu
|
|
354
415
|
end
|
355
416
|
|
356
417
|
def setup_rabbitmq_monitor
|
357
|
-
@logger.debug('
|
418
|
+
@logger.debug('monitoring rabbitmq connection')
|
358
419
|
@timers << EM::PeriodicTimer.new(5) do
|
359
420
|
if @rabbitmq.reconnecting?
|
360
|
-
@logger.warn('
|
421
|
+
@logger.warn('reconnecting to rabbitmq')
|
361
422
|
else
|
362
423
|
unless @keepalive_queue.subscribed?
|
363
|
-
@logger.warn('
|
424
|
+
@logger.warn('re-subscribing to keepalives')
|
364
425
|
setup_keepalives
|
365
426
|
end
|
366
427
|
unless @result_queue.subscribed?
|
367
|
-
@logger.warn('
|
428
|
+
@logger.warn('re-subscribing to results')
|
368
429
|
setup_results
|
369
430
|
end
|
370
431
|
end
|
@@ -372,14 +433,16 @@ module Sensu
|
|
372
433
|
end
|
373
434
|
|
374
435
|
def stop_reactor
|
375
|
-
@logger.info('
|
436
|
+
@logger.info('completing handlers in progress', {
|
437
|
+
:handlers_in_progress => @handlers_in_progress
|
438
|
+
})
|
376
439
|
complete_in_progress = EM::tick_loop do
|
377
440
|
if @handlers_in_progress == 0
|
378
441
|
:stop
|
379
442
|
end
|
380
443
|
end
|
381
444
|
complete_in_progress.on_stop do
|
382
|
-
@logger.warn('
|
445
|
+
@logger.warn('stopping reactor')
|
383
446
|
EM::PeriodicTimer.new(0.25) do
|
384
447
|
EM::stop_event_loop
|
385
448
|
end
|
@@ -387,14 +450,17 @@ module Sensu
|
|
387
450
|
end
|
388
451
|
|
389
452
|
def stop(signal)
|
390
|
-
@logger.warn('
|
453
|
+
@logger.warn('received signal', {
|
454
|
+
:signal => signal
|
455
|
+
})
|
456
|
+
@logger.warn('stopping')
|
391
457
|
@timers.each do |timer|
|
392
458
|
timer.cancel
|
393
459
|
end
|
394
460
|
unless @rabbitmq.reconnecting?
|
395
|
-
@logger.warn('
|
461
|
+
@logger.warn('unsubscribing from keepalives')
|
396
462
|
@keepalive_queue.unsubscribe do
|
397
|
-
@logger.warn('
|
463
|
+
@logger.warn('unsubscribing from results')
|
398
464
|
@result_queue.unsubscribe do
|
399
465
|
resign_as_master do
|
400
466
|
stop_reactor
|