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

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.
@@ -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