sensu 0.9.6.beta.3 → 0.9.6.beta.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sensu/api.rb CHANGED
@@ -77,7 +77,7 @@ module Sensu
77
77
  aget '/info' do
78
78
  response = {
79
79
  :sensu => {
80
- :version => VERSION
80
+ :version => Sensu::VERSION
81
81
  },
82
82
  :health => {
83
83
  :redis => 'ok',
data/lib/sensu/base.rb CHANGED
@@ -4,6 +4,8 @@ gem 'eventmachine', '~> 1.0.0.beta.4'
4
4
 
5
5
  require 'optparse'
6
6
  require 'json'
7
+ require 'time'
8
+ require 'uri'
7
9
  require 'cabin'
8
10
  require 'amqp'
9
11
 
@@ -21,7 +23,7 @@ module Sensu
21
23
  attr_reader :options, :logger, :settings
22
24
 
23
25
  def initialize(options={})
24
- @options = DEFAULT_OPTIONS.merge(options)
26
+ @options = Sensu::DEFAULT_OPTIONS.merge(options)
25
27
  @logger = Cabin::Channel.get
26
28
  setup_logging
27
29
  setup_settings
@@ -29,7 +31,9 @@ module Sensu
29
31
  end
30
32
 
31
33
  def setup_logging
32
- Sensu::Logger.new(@options)
34
+ logger = Sensu::Logger.new(@options)
35
+ logger.reopen
36
+ logger.setup_traps
33
37
  end
34
38
 
35
39
  def setup_settings
@@ -42,7 +46,7 @@ module Sensu
42
46
  begin
43
47
  @settings.validate
44
48
  rescue => error
45
- @logger.fatal('CONFIG INVALID', {
49
+ @logger.fatal('config invalid', {
46
50
  :error => error.to_s
47
51
  })
48
52
  @logger.fatal('SENSU NOT RUNNING!')
@@ -52,7 +56,14 @@ module Sensu
52
56
  end
53
57
 
54
58
  def setup_process
55
- Sensu::Process.new(@options)
59
+ process = Sensu::Process.new
60
+ if @options[:daemonize]
61
+ process.daemonize
62
+ end
63
+ if @options[:pid_file]
64
+ process.write_pid(@options[:pid_file])
65
+ end
66
+ process.setup_eventmachine
56
67
  end
57
68
  end
58
69
  end
data/lib/sensu/cli.rb CHANGED
@@ -8,7 +8,7 @@ module Sensu
8
8
  exit
9
9
  end
10
10
  opts.on('-V', '--version', 'Display version') do
11
- puts VERSION
11
+ puts Sensu::VERSION
12
12
  exit
13
13
  end
14
14
  opts.on('-c', '--config FILE', 'Sensu JSON config FILE. Default is /etc/sensu/config.json') do |file|
@@ -31,7 +31,7 @@ module Sensu
31
31
  end
32
32
  end
33
33
  optparse.parse!(arguments)
34
- DEFAULT_OPTIONS.merge(options)
34
+ Sensu::DEFAULT_OPTIONS.merge(options)
35
35
  end
36
36
  end
37
37
  end
@@ -1,8 +1,12 @@
1
1
  module Sensu
2
- VERSION = '0.9.6.beta.3'
2
+ unless defined?(Sensu::VERSION)
3
+ VERSION = '0.9.6.beta.4'
4
+ end
3
5
 
4
- DEFAULT_OPTIONS = {
5
- :config_file => '/etc/sensu/config.json',
6
- :config_dir => '/etc/sensu/conf.d'
7
- }
6
+ unless defined?(Sensu::DEFAULT_OPTIONS)
7
+ DEFAULT_OPTIONS = {
8
+ :config_file => '/etc/sensu/config.json',
9
+ :config_dir => '/etc/sensu/conf.d'
10
+ }
11
+ end
8
12
  end
data/lib/sensu/logger.rb CHANGED
@@ -4,26 +4,26 @@ module Sensu
4
4
  @logger = Cabin::Channel.get
5
5
  @logger.subscribe(STDOUT)
6
6
  @logger.level = options[:verbose] ? :debug : options[:log_level] || :info
7
- reopen(options)
8
- setup_traps(options)
7
+ @log_file = options[:log_file]
9
8
  end
10
9
 
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')
10
+ def reopen(file=nil)
11
+ file ||= @log_file
12
+ unless file.nil?
13
+ @log_file = file
14
+ if File.writable?(file) || !File.exist?(file) && File.writable?(File.dirname(file))
15
+ STDOUT.reopen(file, 'a')
16
16
  STDERR.reopen(STDOUT)
17
17
  STDOUT.sync = true
18
18
  else
19
19
  @logger.error('log file is not writable', {
20
- :log_file => options[:log_file]
20
+ :log_file => file
21
21
  })
22
22
  end
23
23
  end
24
24
  end
25
25
 
26
- def setup_traps(options={})
26
+ def setup_traps
27
27
  if Signal.list.include?('USR1')
28
28
  Signal.trap('USR1') do
29
29
  @logger.level = @logger.level == :info ? :debug : :info
@@ -31,7 +31,7 @@ module Sensu
31
31
  end
32
32
  if Signal.list.include?('USR2')
33
33
  Signal.trap('USR2') do
34
- reopen(options)
34
+ reopen(@log_file)
35
35
  end
36
36
  end
37
37
  end
@@ -46,13 +46,26 @@ module Redis
46
46
  end
47
47
  end
48
48
 
49
- def self.connect(options={})
50
- host = options[:host] || 'localhost'
51
- port = options[:port] || 6379
49
+ def self.connect(options)
50
+ options ||= Hash.new
51
+ if options.is_a?(String)
52
+ begin
53
+ uri = URI.parse(options)
54
+ host = uri.host
55
+ port = uri.port || 6379
56
+ password = uri.password
57
+ rescue
58
+ raise('invalid redis url')
59
+ end
60
+ else
61
+ host = options[:host] || 'localhost'
62
+ port = options[:port] || 6379
63
+ password = options[:password]
64
+ end
52
65
  EM::connect(host, port, Redis::Client) do |client|
53
66
  client.redis_host = host
54
67
  client.redis_port = port
55
- client.redis_password = options[:password]
68
+ client.redis_password = password
56
69
  end
57
70
  end
58
71
  end
data/lib/sensu/process.rb CHANGED
@@ -1,25 +1,19 @@
1
1
  module Sensu
2
2
  class Process
3
- def initialize(options={})
3
+ def initialize
4
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
5
  end
13
6
 
14
- def write_pid(pid_file)
7
+ def write_pid(file)
15
8
  begin
16
- File.open(pid_file, 'w') do |file|
17
- file.puts(::Process.pid)
9
+ File.open(file, 'w') do |pid_file|
10
+ pid_file.puts(::Process.pid)
18
11
  end
19
12
  rescue
20
13
  @logger.fatal('could not write to pid file', {
21
- :pid_file => pid_file
14
+ :pid_file => file
22
15
  })
16
+ @logger.fatal('SENSU NOT RUNNING!')
23
17
  exit 2
24
18
  end
25
19
  end
@@ -31,6 +25,7 @@ module Sensu
31
25
  end
32
26
  unless ::Process.setsid
33
27
  @logger.fatal('cannot detach from controlling terminal')
28
+ @logger.fatal('SENSU NOT RUNNING!')
34
29
  exit 2
35
30
  end
36
31
  Signal.trap('SIGHUP', 'IGNORE')
data/lib/sensu/server.rb CHANGED
@@ -63,6 +63,43 @@ module Sensu
63
63
  end
64
64
  end
65
65
 
66
+ def check_subdued?(check, subdue_type)
67
+ subdue = false
68
+ if check[:subdue].is_a?(Hash)
69
+ if check[:subdue].has_key?(:start) && check[:subdue].has_key?(:end)
70
+ start = Time.parse(check[:subdue][:start])
71
+ stop = Time.parse(check[:subdue][:end])
72
+ if stop < start
73
+ if Time.now < stop
74
+ start = Time.parse('12:00:00 AM')
75
+ else
76
+ stop = Time.parse('11:59:59 PM')
77
+ end
78
+ end
79
+ if Time.now >= start && Time.now <= stop
80
+ subdue = true
81
+ end
82
+ end
83
+ if check[:subdue].has_key?(:days)
84
+ days = check[:subdue][:days].map(&:downcase)
85
+ if days.include?(Time.now.strftime('%A').downcase)
86
+ subdue = true
87
+ end
88
+ end
89
+ if subdue && check[:subdue].has_key?(:exceptions)
90
+ subdue = check[:subdue][:exceptions].none? do |exception|
91
+ Time.now >= Time.parse(exception[:start]) && Time.now <= Time.parse(exception[:end])
92
+ end
93
+ end
94
+ end
95
+ if subdue
96
+ (!check[:subdue].has_key?(:at) && subdue_type == :handler) ||
97
+ (check[:subdue].has_key?(:at) && check[:subdue][:at].to_sym == subdue_type)
98
+ else
99
+ false
100
+ end
101
+ end
102
+
66
103
  def check_handlers(check)
67
104
  handler_list = case
68
105
  when check.has_key?(:handler)
@@ -93,73 +130,75 @@ module Sensu
93
130
  end
94
131
 
95
132
  def handle_event(event)
96
- report = proc do |output|
97
- if output.is_a?(String)
98
- output.split(/\n+/).each do |line|
99
- @logger.info('handler output', {
100
- :output => line
101
- })
102
- end
103
- end
104
- @handlers_in_progress -= 1
105
- end
106
- handlers = check_handlers(event[:check])
107
- handlers.each do |handler|
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
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
133
+ unless check_subdued?(event[:check], :handler)
134
+ report = proc do |output|
135
+ if output.is_a?(String)
136
+ output.split(/\n+/).each do |line|
137
+ @logger.info('handler output', {
138
+ :output => line
139
139
  })
140
140
  end
141
141
  end
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
142
  @handlers_in_progress -= 1
158
- when 'set'
159
- @logger.error('handler sets cannot be nested', {
143
+ end
144
+ handlers = check_handlers(event[:check])
145
+ handlers.each do |handler|
146
+ @logger.debug('handling event', {
147
+ :event => event,
160
148
  :handler => handler
161
149
  })
162
- @handlers_in_progress -= 1
150
+ @handlers_in_progress += 1
151
+ case handler[:type]
152
+ when 'pipe'
153
+ execute = proc do
154
+ begin
155
+ IO.popen(handler[:command] + ' 2>&1', 'r+') do |io|
156
+ io.write(event.to_json)
157
+ io.close_write
158
+ io.read
159
+ end
160
+ rescue Errno::ENOENT => error
161
+ @logger.error('handler does not exist', {
162
+ :event => event,
163
+ :handler => handler,
164
+ :error => error.to_s
165
+ })
166
+ rescue Errno::EPIPE => error
167
+ @logger.error('broken pipe', {
168
+ :event => event,
169
+ :handler => handler,
170
+ :error => error.to_s
171
+ })
172
+ rescue => error
173
+ @logger.error('unexpected error', {
174
+ :event => event,
175
+ :handler => handler,
176
+ :error => error.to_s
177
+ })
178
+ end
179
+ end
180
+ EM::defer(execute, report)
181
+ when 'amqp'
182
+ exchange_name = handler[:exchange][:name]
183
+ exchange_type = handler[:exchange].has_key?(:type) ? handler[:exchange][:type].to_sym : :direct
184
+ exchange_options = handler[:exchange].reject do |key, value|
185
+ [:name, :type].include?(key)
186
+ end
187
+ @logger.debug('publishing event to an amqp exchange', {
188
+ :event => event,
189
+ :exchange => handler[:exchange]
190
+ })
191
+ payload = handler[:send_only_check_output] ? event[:check][:output] : event.to_json
192
+ unless payload.empty?
193
+ @amq.method(exchange_type).call(exchange_name, exchange_options).publish(payload)
194
+ end
195
+ @handlers_in_progress -= 1
196
+ when 'set'
197
+ @logger.error('handler sets cannot be nested', {
198
+ :handler => handler
199
+ })
200
+ @handlers_in_progress -= 1
201
+ end
163
202
  end
164
203
  end
165
204
  end
@@ -242,6 +281,7 @@ module Sensu
242
281
  unless check[:auto_resolve] == false && !check[:force_resolve]
243
282
  @redis.hdel('events:' + client[:name], check[:name]).callback do
244
283
  unless check[:handle] == false
284
+ event[:occurrences] = previous_occurrence[:occurrences]
245
285
  event[:action] = 'resolve'
246
286
  handle_event(event)
247
287
  else
@@ -294,17 +334,19 @@ module Sensu
294
334
  @timers << EM::Timer.new(stagger * check_count) do
295
335
  interval = options[:test] ? 0.5 : check[:interval]
296
336
  @timers << EM::PeriodicTimer.new(interval) do
297
- unless @rabbitmq.reconnecting?
298
- payload = {
299
- :name => check[:name],
300
- :issued => Time.now.to_i
301
- }
302
- @logger.info('publishing check request', {
303
- :payload => payload,
304
- :subscribers => check[:subscribers]
305
- })
306
- check[:subscribers].uniq.each do |exchange_name|
307
- @amq.fanout(exchange_name).publish(payload.to_json)
337
+ unless check_subdued?(check, :publisher)
338
+ unless @rabbitmq.reconnecting?
339
+ payload = {
340
+ :name => check[:name],
341
+ :issued => Time.now.to_i
342
+ }
343
+ @logger.info('publishing check request', {
344
+ :payload => payload,
345
+ :subscribers => check[:subscribers]
346
+ })
347
+ check[:subscribers].uniq.each do |exchange_name|
348
+ @amq.fanout(exchange_name).publish(payload.to_json)
349
+ end
308
350
  end
309
351
  end
310
352
  end
@@ -203,6 +203,48 @@ module Sensu
203
203
  raise('handlers must be an array for check: ' + check[:name])
204
204
  end
205
205
  end
206
+ if check.has_key?(:subdue)
207
+ unless check[:subdue].is_a?(Hash)
208
+ raise('subdue must be a hash for check: ' + check[:name])
209
+ end
210
+ if check[:subdue].has_key?(:start) || check[:subdue].has_key?(:end)
211
+ begin
212
+ Time.parse(check[:subdue][:start])
213
+ Time.parse(check[:subdue][:end])
214
+ rescue
215
+ raise('subdue start & end times must be valid for check: ' + check[:name])
216
+ end
217
+ end
218
+ if check[:subdue].has_key?(:days)
219
+ unless check[:subdue][:days].is_a?(Array)
220
+ raise('subdue days must be an array for check: ' + check[:name])
221
+ end
222
+ check[:subdue][:days].each do |day|
223
+ days = %w[sunday monday tuesday wednesday thursday friday saturday]
224
+ unless day.is_a?(String) && days.include?(day.downcase)
225
+ raise('subdue days must be valid days of the week for check: ' + check[:name])
226
+ end
227
+ end
228
+ end
229
+ if check[:subdue].has_key?(:exceptions)
230
+ unless check[:subdue][:exceptions].is_a?(Array)
231
+ raise('subdue exceptions must be an array for check: ' + check[:name])
232
+ end
233
+ check[:subdue][:exceptions].each do |exception|
234
+ unless exception.is_a?(Hash)
235
+ raise('subdue exception items must be a hash for check: ' + check[:name])
236
+ end
237
+ if exception.has_key?(:start) || exception.has_key?(:end)
238
+ begin
239
+ Time.parse(exception[:start])
240
+ Time.parse(exception[:end])
241
+ rescue
242
+ raise('subdue exception start & end times must be valid for check: ' + check[:name])
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
206
248
  end
207
249
  end
208
250
 
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: 62196229
4
+ hash: 62196235
5
5
  prerelease: true
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
9
  - 6
10
10
  - beta
11
- - 3
12
- version: 0.9.6.beta.3
11
+ - 4
12
+ version: 0.9.6.beta.4
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-05-04 00:00:00 -07:00
21
+ date: 2012-05-19 00:00:00 -07:00
22
22
  default_executable:
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency