sensu 0.9.9.beta.2 → 0.9.9.beta.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,16 +1,17 @@
1
1
  module Sensu
2
2
  unless defined?(Sensu::VERSION)
3
- VERSION = '0.9.9.beta.2'
4
- end
3
+ VERSION = '0.9.9.beta.3'
5
4
 
6
- unless defined?(Sensu::DEFAULT_OPTIONS)
7
5
  DEFAULT_OPTIONS = {
8
6
  :config_file => '/etc/sensu/config.json',
9
- :config_dir => '/etc/sensu/conf.d'
7
+ :config_dir => '/etc/sensu/conf.d',
8
+ :log_level => :info
10
9
  }
11
- end
12
10
 
13
- unless defined?(Sensu::SEVERITIES)
11
+ SETTINGS_CATEGORIES = [:checks, :filters, :mutators, :handlers]
12
+
13
+ EXTENSION_CATEGORIES = [:mutators, :handlers]
14
+
14
15
  SEVERITIES = %w[ok warning critical unknown]
15
16
  end
16
17
  end
@@ -0,0 +1,101 @@
1
+ module Sensu
2
+ class Extensions
3
+ def initialize
4
+ @logger = Logger.get
5
+ @extensions = Hash.new
6
+ EXTENSION_CATEGORIES.each do |category|
7
+ @extensions[category] = Hash.new
8
+ end
9
+ end
10
+
11
+ def [](key)
12
+ @extensions[key]
13
+ end
14
+
15
+ EXTENSION_CATEGORIES.each do |category|
16
+ define_method(category.to_s.chop + '_exists?') do |extension_name|
17
+ @extensions[category].has_key?(extension_name)
18
+ end
19
+ end
20
+
21
+ def require_directory(directory)
22
+ Dir.glob(File.join(directory, '**/*.rb')).each do |file|
23
+ begin
24
+ require file
25
+ rescue ScriptError => error
26
+ @logger.error('failed to require extension', {
27
+ :extension_file => file,
28
+ :error => error
29
+ })
30
+ @logger.warn('ignoring extension', {
31
+ :extension_file => file
32
+ })
33
+ end
34
+ end
35
+ end
36
+
37
+ def load_all
38
+ require_directory(File.join(File.dirname(__FILE__), 'extensions'))
39
+ EXTENSION_CATEGORIES.each do |category|
40
+ extension_type = category.to_s.chop
41
+ Extension.const_get(extension_type.capitalize).descendants.each do |klass|
42
+ extension = klass.new
43
+ @extensions[category][extension.name] = extension
44
+ loaded(extension_type, extension.name, extension.description)
45
+ end
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def loaded(type, name, description)
52
+ @logger.info('loaded extension', {
53
+ :type => type,
54
+ :name => name,
55
+ :description => description
56
+ })
57
+ end
58
+ end
59
+
60
+ module Extension
61
+ class Base
62
+ def name
63
+ 'base'
64
+ end
65
+
66
+ def description
67
+ 'extension description (change me)'
68
+ end
69
+
70
+ def definition
71
+ {
72
+ :type => 'extension',
73
+ :name => name
74
+ }
75
+ end
76
+
77
+ def [](key)
78
+ definition[key.to_sym]
79
+ end
80
+
81
+ def has_key?(key)
82
+ definition.has_key?(key.to_sym)
83
+ end
84
+
85
+ def run(event=nil, &block)
86
+ block.call('noop', 0)
87
+ end
88
+
89
+ def self.descendants
90
+ ObjectSpace.each_object(Class).select do |klass|
91
+ klass < self
92
+ end
93
+ end
94
+ end
95
+
96
+ EXTENSION_CATEGORIES.each do |category|
97
+ extension_type = category.to_s.chop
98
+ Object.const_set(extension_type.capitalize, Class.new(Base))
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,17 @@
1
+ module Sensu
2
+ module Extension
3
+ class Debug < Handler
4
+ def name
5
+ 'debug'
6
+ end
7
+
8
+ def description
9
+ 'outputs json event data'
10
+ end
11
+
12
+ def run(event, &block)
13
+ block.call(event.to_json, 0)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Sensu
2
+ module Extension
3
+ class OnlyCheckOutput < Mutator
4
+ def name
5
+ 'only_check_output'
6
+ end
7
+
8
+ def description
9
+ 'returns check output'
10
+ end
11
+
12
+ def run(event, &block)
13
+ block.call(event[:check][:output], 0)
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/sensu/io.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'timeout'
2
+
1
3
  module Sensu
2
4
  class IO
3
5
  class << self
@@ -3,7 +3,9 @@ gem 'cabin', '0.4.4'
3
3
  require 'cabin'
4
4
 
5
5
  module Sensu
6
- class Logger
6
+ class LogStream
7
+ attr_reader :logger
8
+
7
9
  def initialize
8
10
  @logger = Cabin::Channel.get
9
11
  STDOUT.sync = true
@@ -15,19 +17,16 @@ module Sensu
15
17
  @logger.level = log_level
16
18
  end
17
19
 
18
- def reopen(file=nil)
19
- file ||= @log_file
20
- unless file.nil?
21
- @log_file = file
22
- if File.writable?(file) || !File.exist?(file) && File.writable?(File.dirname(file))
23
- STDOUT.reopen(file, 'a')
24
- STDOUT.sync = true
25
- STDERR.reopen(STDOUT)
26
- else
27
- @logger.error('log file is not writable', {
28
- :log_file => file
29
- })
30
- end
20
+ def reopen(file)
21
+ @log_file = file
22
+ if File.writable?(file) || !File.exist?(file) && File.writable?(File.dirname(file))
23
+ STDOUT.reopen(file, 'a')
24
+ STDOUT.sync = true
25
+ STDERR.reopen(STDOUT)
26
+ else
27
+ @logger.error('log file is not writable', {
28
+ :log_file => file
29
+ })
31
30
  end
32
31
  end
33
32
 
@@ -39,11 +38,15 @@ module Sensu
39
38
  end
40
39
  if Signal.list.include?('USR2')
41
40
  Signal.trap('USR2') do
42
- reopen(@log_file)
41
+ if @log_file
42
+ reopen(@log_file)
43
+ end
43
44
  end
44
45
  end
45
46
  end
47
+ end
46
48
 
49
+ class Logger
47
50
  def self.get
48
51
  Cabin::Channel.get
49
52
  end
@@ -52,6 +55,7 @@ module Sensu
52
55
  class NullLogger
53
56
  [:debug, :info, :warn, :error, :fatal].each do |method|
54
57
  define_method(method) do |*arguments|
58
+ true
55
59
  end
56
60
  end
57
61
 
data/lib/sensu/process.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Sensu
2
2
  class Process
3
3
  def initialize
4
- @logger = Sensu::Logger.get
4
+ @logger = Logger.get
5
5
  end
6
6
 
7
7
  def write_pid(file)
@@ -0,0 +1,74 @@
1
+ gem 'amqp', '0.9.8'
2
+
3
+ require 'amqp'
4
+
5
+ module Sensu
6
+ class RabbitMQError < StandardError; end
7
+
8
+ class RabbitMQ
9
+ attr_reader :channel
10
+
11
+ def initialize
12
+ @on_error = Proc.new {}
13
+ @before_reconnect = Proc.new {}
14
+ @after_reconnect = Proc.new {}
15
+ end
16
+
17
+ def on_error(&block)
18
+ @on_error = block
19
+ end
20
+
21
+ def before_reconnect(&block)
22
+ @before_reconnect = block
23
+ end
24
+
25
+ def after_reconnect(&block)
26
+ @after_reconnect = block
27
+ end
28
+
29
+ def connect(options={})
30
+ options.reject! do |key, value|
31
+ key == :heartbeat
32
+ end
33
+ on_failure = Proc.new do
34
+ error = RabbitMQError.new('cannot connect to rabbitmq')
35
+ @on_error.call(error)
36
+ end
37
+ @connection = AMQP.connect(options, {
38
+ :on_tcp_connection_failure => on_failure,
39
+ :on_possible_authentication_failure => on_failure
40
+ })
41
+ @connection.logger = NullLogger.get
42
+ @connection.on_tcp_connection_loss do |connection, settings|
43
+ unless connection.reconnecting?
44
+ @before_reconnect.call
45
+ connection.periodically_reconnect(5)
46
+ end
47
+ end
48
+ @channel = AMQP::Channel.new(@connection)
49
+ @channel.auto_recovery = true
50
+ @channel.on_error do |channel, channel_close|
51
+ error = RabbitMQError.new('rabbitmq channel closed')
52
+ @on_error.call(error)
53
+ end
54
+ @channel.on_recovery do
55
+ @after_reconnect.call
56
+ end
57
+ end
58
+
59
+ def connected?
60
+ @connection.connected?
61
+ end
62
+
63
+ def close
64
+ @connection.close
65
+ end
66
+
67
+ def self.connect(options={})
68
+ options ||= Hash.new
69
+ rabbitmq = self.new
70
+ rabbitmq.connect(options)
71
+ rabbitmq
72
+ end
73
+ end
74
+ end
data/lib/sensu/redis.rb CHANGED
@@ -1,122 +1,18 @@
1
- gem 'ruby-redis', '0.0.2'
1
+ gem 'em-redis-unified', '0.4.1'
2
2
 
3
- require 'redis'
3
+ require 'em-redis'
4
4
 
5
5
  module Sensu
6
- class Redis < Redis::Client
7
- attr_accessor :settings, :on_tcp_connection_failure
8
-
9
- alias :em_reconnect :reconnect
10
-
11
- def initialize(*arguments)
12
- super
13
- @logger = Sensu::Logger.get
14
- @settings = Hash.new
15
- @connection_established = false
16
- @connected = false
17
- @reconnecting = false
18
- @closing_connection = false
19
- end
20
-
21
- def setup_heartbeat
22
- @heartbeat ||= EM::PeriodicTimer.new(10) do
23
- if connected?
24
- ping
25
- end
26
- end
27
- end
28
-
29
- def connection_completed
30
- @connection_established = true
31
- @connected = true
32
- @reconnecting = false
33
- if @settings[:password]
34
- auth(@settings[:password]).callback do |reply|
35
- unless reply == 'OK'
36
- @logger.fatal('redis authentication failed')
37
- close_connection
38
- end
39
- end
40
- end
41
- info.callback do |reply|
42
- redis_version = reply.split(/\n/).select { |v| v =~ /^redis_version/ }.first.split(/:/).last.chomp
43
- if redis_version < '1.3.14'
44
- @logger.fatal('redis version must be >= 2.0 RC 1')
45
- close_connection
46
- end
47
- end
48
- setup_heartbeat
49
- end
50
-
51
- def reconnect(immediate=false, wait=10)
52
- if @reconnecting && !immediate
53
- EM::Timer.new(wait) do
54
- em_reconnect(@settings[:host], @settings[:port])
55
- end
56
- else
57
- @reconnecting = true
58
- em_reconnect(@settings[:host], @settings[:port])
59
- end
60
- end
61
-
62
- def close
63
- @closing_connection = true
64
- close_connection
65
- end
66
-
67
- def on_tcp_connection_loss(&block)
68
- if block.respond_to?(:call)
69
- @on_tcp_connection_loss = block
70
- end
71
- end
72
-
73
- def unbind
74
- @connected = false
75
- super
76
- unless @closing_connection
77
- if @connection_established
78
- if @on_tcp_connection_loss
79
- @on_tcp_connection_loss.call(self, @settings)
80
- end
81
- else
82
- if @on_tcp_connection_failure
83
- @on_tcp_connection_failure.call(self, @settings)
84
- end
85
- end
86
- end
87
- end
88
-
89
- def connected?
90
- @connected
91
- end
92
-
93
- def self.connect(options, additional={})
6
+ class Redis
7
+ def self.connect(options={})
94
8
  options ||= Hash.new
95
- if options.is_a?(String)
96
- begin
97
- uri = URI.parse(options)
98
- host = uri.host
99
- port = uri.port || 6379
100
- password = uri.password
101
- rescue
102
- @logger.fatal('invalid redis url')
103
- @logger.fatal('SENSU NOT RUNNING!')
104
- exit 2
9
+ connection = EM::Protocols::Redis.connect(options)
10
+ connection.info do |info|
11
+ if info[:redis_version] < '1.3.14'
12
+ klass = EM::Protocols::Redis::RedisError
13
+ message = 'redis version must be >= 2.0 RC 1'
14
+ connection.error(klass, message)
105
15
  end
106
- else
107
- host = options[:host] || 'localhost'
108
- port = options[:port] || 6379
109
- password = options[:password]
110
- end
111
- connection = EM::connect(host, port, self) do |redis|
112
- redis.settings = {
113
- :host => host,
114
- :port => port,
115
- :password => password
116
- }
117
- end
118
- if additional[:on_tcp_connection_failure].respond_to?(:call)
119
- connection.on_tcp_connection_failure = additional[:on_tcp_connection_failure]
120
16
  end
121
17
  connection
122
18
  end