averell23-watchdogger 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/dog_log.rb +7 -5
- data/lib/watchdogger.rb +3 -3
- data/lib/watcher/base.rb +22 -14
- data/lib/watcher/http_watcher.rb +6 -5
- data/lib/watcher/log_watcher.rb +5 -7
- data/lib/watcher_action.rb +5 -0
- data/lib/watcher_action/htpost.rb +4 -4
- data/lib/watcher_action/kill_process.rb +4 -3
- data/lib/watcher_action/log_action.rb +5 -4
- data/lib/watcher_action/meta_action.rb +27 -0
- data/lib/watcher_action/send_mail.rb +15 -15
- data/test/meta_action_test.rb +20 -0
- data/test/test_helper.rb +41 -1
- data/test/watchdogger_test.rb +1 -32
- metadata +3 -1
data/lib/dog_log.rb
CHANGED
@@ -8,8 +8,12 @@ class DogLog # :nodoc:
|
|
8
8
|
# Set the log file and severity. This will reset the current logger,
|
9
9
|
# but should not usually be called on an active log.
|
10
10
|
def setup(logfile, severity)
|
11
|
-
@logfile = logfile
|
12
|
-
@severity =
|
11
|
+
@logfile = logfile || STDERR
|
12
|
+
@severity = if(severity)
|
13
|
+
severity.is_a?(Fixnum) ? severity : Logger.const_get(severity.upcase)
|
14
|
+
else
|
15
|
+
Logger::DEBUG
|
16
|
+
end
|
13
17
|
if(@logger)
|
14
18
|
assit_fail('Resetting logfile')
|
15
19
|
@logger.close if(@logger.respond_to?(:close))
|
@@ -22,10 +26,8 @@ class DogLog # :nodoc:
|
|
22
26
|
# If nothing is configured, we log to STDERR by default
|
23
27
|
def logger
|
24
28
|
@logger ||= begin
|
25
|
-
@logfile ||= STDERR
|
26
|
-
severity = @severity || Logger::DEBUG
|
27
29
|
logger = Logger.new(get_log_io, 3)
|
28
|
-
logger.level = severity
|
30
|
+
logger.level = @severity
|
29
31
|
logger
|
30
32
|
end
|
31
33
|
end
|
data/lib/watchdogger.rb
CHANGED
@@ -24,9 +24,9 @@ module WatchDogger # :nodoc:
|
|
24
24
|
# Initializes the watchdog system, sets up the log. In addition to the configured
|
25
25
|
# Watchers and WatcherActions, the system can take the following arguments:
|
26
26
|
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
27
|
+
# [*log_level*] The log level for the system log. This will apply to all log messages
|
28
|
+
# [*logfile*] The log file for the system. Defaults to STDOUT
|
29
|
+
# [*interval*] The watch interval in seconds. Defaults to 60
|
30
30
|
def init_system(options)
|
31
31
|
# First setup the logging options
|
32
32
|
@log_level = options.get_value(:log_level)
|
data/lib/watcher/base.rb
CHANGED
@@ -6,20 +6,22 @@ module Watcher
|
|
6
6
|
# trouble). Each watcher will have one or more actions attached that will be called if the
|
7
7
|
# watched condition is triggered.
|
8
8
|
#
|
9
|
+
# =Options
|
10
|
+
#
|
9
11
|
# Each watcher will accept the following options, which are handled by the superclass:
|
10
12
|
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
13
|
+
# [*severity*] Severity of the event. Each time the event is triggered, the watcher will
|
14
|
+
# add this value to the internal "severity". If the internal severity reaches
|
15
|
+
# 100, the action is triggered. This means that with a severity of 100 the
|
16
|
+
# action is run each time the watcher triggers. With a severity of 1, it is
|
17
|
+
# only executed every 100th time. The global mechanism will reset the
|
18
|
+
# severity once the action is triggered. The watcher class may decide
|
19
|
+
# to reset the severity also on other occasions. Default: 100
|
18
20
|
#
|
19
|
-
#
|
20
|
-
#
|
21
|
+
# [*actions*] The actions that should be executed when the watcher triggers. These
|
22
|
+
# are names of actions that have been set up previously. (Required)
|
21
23
|
#
|
22
|
-
#
|
24
|
+
# [*warn_actions*] Additional actions that are executed if the watcher triggers, but the
|
23
25
|
# severity for a real action is not yet reached.
|
24
26
|
#
|
25
27
|
# Each watcher object must respond to the #watch_it! method. It must check the watched condition
|
@@ -37,22 +39,28 @@ module Watcher
|
|
37
39
|
action_config = configuration.get_value(:actions)
|
38
40
|
raise(ArgumentError, "No actions passed to watcher.") unless(action_config)
|
39
41
|
if(action_config.is_a?(Array))
|
40
|
-
action_config.each { |ac| actions
|
42
|
+
action_config.each { |ac| add_action_to(actions, ac) }
|
41
43
|
else
|
42
44
|
assit(action_config.is_a?(String) || action_config.is_a?(Symbol))
|
43
|
-
actions
|
45
|
+
add_action_to(actions, action_config)
|
44
46
|
end
|
45
47
|
warn_config = configuration.get_value(:warn_actions)
|
46
48
|
if(warn_config.is_a?(Array))
|
47
|
-
warn_config.each { |ac| warn_actions
|
49
|
+
warn_config.each { |ac| add_action_to(warn_actions, ac) }
|
48
50
|
elsif(warn_config)
|
49
51
|
assit_kind_of(String, warn_config)
|
50
|
-
warn_actions
|
52
|
+
add_action_to(warn_actions, warn_config)
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
56
|
private
|
55
57
|
|
58
|
+
# Adds the given action to the array, if it exists
|
59
|
+
def add_action_to(ary, action)
|
60
|
+
raise(NameError, "Action does not exist: #{action}") unless(WatcherAction.has_action?(action))
|
61
|
+
ary << action
|
62
|
+
end
|
63
|
+
|
56
64
|
# Checks the trigger and does everything to call the actions connected to this watcher
|
57
65
|
def do_watch!
|
58
66
|
@current_severity ||= 0
|
data/lib/watcher/http_watcher.rb
CHANGED
@@ -3,13 +3,14 @@ require 'net/http'
|
|
3
3
|
module Watcher
|
4
4
|
|
5
5
|
# Checks an http connection if it is active and returns the expected results.
|
6
|
-
#
|
6
|
+
#
|
7
|
+
# =Options
|
7
8
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
9
|
+
# [*url*] The URL to query (required)
|
10
|
+
# [*response*] The response code that is expected from the operation
|
11
|
+
# [*content_match*] A regular expression that is matched against the result.
|
11
12
|
# The watcher fails if the expression doesn't match
|
12
|
-
#
|
13
|
+
# [*timeout*] The timeout for the connection attempt. Defaults to 10 sec
|
13
14
|
#
|
14
15
|
# If neither response nor content_match are given, the watcher will expect a
|
15
16
|
# 200 OK response from the server.
|
data/lib/watcher/log_watcher.rb
CHANGED
@@ -9,13 +9,11 @@ module Watcher
|
|
9
9
|
#
|
10
10
|
# = Options
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# log file. They default to 60 (1 minute) and 300 (5 minutes). The log file will
|
18
|
-
# be considered stale and reopened after max_value * 3.
|
12
|
+
# [*logfile*] The log file to watch (required)
|
13
|
+
# [*match*] A regular expression against which the log file will be matched (required)
|
14
|
+
# [*interval_first, interval_max*] The start and the max value for waiting on an unchanged
|
15
|
+
# log file. They default to 60 (1 minute) and 300 (5 minutes).
|
16
|
+
# The log file will be considered stale and reopened after max_value * 3.
|
19
17
|
#
|
20
18
|
# = Warning
|
21
19
|
#
|
data/lib/watcher_action.rb
CHANGED
@@ -29,6 +29,11 @@ module WatcherAction
|
|
29
29
|
dog_log.error('Action Handler') { "Could not execute #{name}: #{e.message} (Registered actions: #{registered_actions.keys.join(', ')})" }
|
30
30
|
false
|
31
31
|
end
|
32
|
+
|
33
|
+
# Checks if the given action exists
|
34
|
+
def has_action?(name)
|
35
|
+
registered_actions[name.to_sym] != nil
|
36
|
+
end
|
32
37
|
|
33
38
|
private
|
34
39
|
|
@@ -2,11 +2,11 @@ module WatcherAction
|
|
2
2
|
|
3
3
|
# This action posts the event to a given URL. It may use plain HTTP Authentication
|
4
4
|
#
|
5
|
-
# Options
|
5
|
+
# = Options
|
6
6
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
7
|
+
# [*url*] The URL to post the information to (required)
|
8
|
+
# [*user*] The user for HTTP Authentication (optional)
|
9
|
+
# [*pass*] The password for HTTP Authentication.
|
10
10
|
class Htpost
|
11
11
|
|
12
12
|
def initialize(options)
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module WatcherAction
|
2
2
|
|
3
3
|
# Kills the process with the given PID.
|
4
|
-
# Options:
|
5
4
|
#
|
6
|
-
#
|
7
|
-
#
|
5
|
+
# =Options
|
6
|
+
#
|
7
|
+
# [*pidfile*] The file containing the process id
|
8
|
+
# [*signal*] The signal to send to the process. Defaults to KILL
|
8
9
|
class KillProcess
|
9
10
|
|
10
11
|
def initialize(config)
|
@@ -3,11 +3,12 @@ require 'logger'
|
|
3
3
|
module WatcherAction
|
4
4
|
|
5
5
|
# Logs the event information to the standard log file
|
6
|
-
# Options:
|
7
6
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
7
|
+
# =Options
|
8
|
+
#
|
9
|
+
# [*format*] A format string that will receive the timestamp, watcher name and
|
10
|
+
# event message (in that order) as parameters (default message if not given)
|
11
|
+
# [*severity*] The severity of the log message (default: warn)
|
11
12
|
class LogAction
|
12
13
|
|
13
14
|
def initialize(options)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module WatcherAction
|
2
|
+
|
3
|
+
# An action to call other actions. This can be used to "aggregate" combinations of
|
4
|
+
# actions that should always go together, so that the same combinations do
|
5
|
+
# not have to repeated multiple times
|
6
|
+
#
|
7
|
+
# = Options
|
8
|
+
#
|
9
|
+
# [*actions*] A list of the actions that should be executed. (required)
|
10
|
+
class MetaAction
|
11
|
+
|
12
|
+
def initialize(config)
|
13
|
+
actions = config.get_value(:actions, false)
|
14
|
+
if(actions.is_a?(Array))
|
15
|
+
@actions = actions
|
16
|
+
else
|
17
|
+
@actions = [ actions ]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute(event)
|
22
|
+
@actions.each { |ac| WatcherAction.run_action(ac, event) }
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -7,20 +7,20 @@ module WatcherAction
|
|
7
7
|
# fancy features (you may want to do that handling externally) and will only
|
8
8
|
# use unencrypted smtp network connections.
|
9
9
|
#
|
10
|
-
# Options
|
10
|
+
# =Options
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
12
|
+
# [*to*] Email address to which to send the message. May be a list. (required)
|
13
|
+
# [*sender*] Email address of the person sending the mail (required)
|
14
|
+
# [*subject*] Subject of the message. You can put %s for the event message. (defaults if not set)
|
15
|
+
# [*body*] Body of the email message. If set to 'xml', it will include an
|
16
|
+
# XML representation of the event. If not set, it will default
|
17
|
+
# to a sensible description of the event. You can include the
|
18
|
+
# event's message as for the subject
|
19
|
+
# [*server*] Address or name of the mail server to use (defaults to localhost)
|
20
|
+
# [*port*] Port to connect to (default: 25)
|
21
|
+
# [*user*] Mail server user name
|
22
|
+
# [*pass*] Mail server password
|
23
|
+
# [*authentication*] Authentication method (default: plain)
|
24
24
|
class SendMail
|
25
25
|
|
26
26
|
def initialize(config)
|
@@ -28,7 +28,7 @@ module WatcherAction
|
|
28
28
|
@sender = config.get_value(:sender, false)
|
29
29
|
@subject = config.get_value(:subject, "Watchdogger triggered: %s")
|
30
30
|
@body = config.get_value(:body)
|
31
|
-
@server = config.get_value(:server,
|
31
|
+
@server = config.get_value(:server, 'localhost')
|
32
32
|
@port = config.get_value(:port, '25')
|
33
33
|
@user = config.get_value(:user)
|
34
34
|
@pass = config.get_value(:pass)
|
@@ -38,7 +38,7 @@ module WatcherAction
|
|
38
38
|
def execute(event)
|
39
39
|
msg = RMail::Message.new
|
40
40
|
msg.header.to = @mail_to
|
41
|
-
receipient = msg.header.to.split(',').first
|
41
|
+
receipient = msg.header.to.to_s.split(',').first
|
42
42
|
msg.header.from = @sender
|
43
43
|
msg.header.subject = @subject % [event.message]
|
44
44
|
if(@body.to_s == 'xml')
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class MetaActionTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
clear_registered
|
7
|
+
WatcherAction.register('child1', { :type => 'dummy_action' })
|
8
|
+
WatcherAction.register('child2', { :type => 'dummy_action' })
|
9
|
+
@meta = WatcherAction::MetaAction.new(:actions => ['child1', 'child2'])
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_simple
|
13
|
+
assert_equal(nil, action_status('child1'))
|
14
|
+
assert_equal(nil, action_status('child2'))
|
15
|
+
@meta.execute(WatcherEvent.new)
|
16
|
+
assert_equal(true, action_status('child1'))
|
17
|
+
assert_equal(true, action_status('child2'))
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -3,4 +3,44 @@ require 'test/unit'
|
|
3
3
|
|
4
4
|
require File.join(File.dirname(__FILE__), '..', 'lib', 'watchdogger')
|
5
5
|
|
6
|
-
DogLog.setup('tmp.log', Logger::DEBUG)
|
6
|
+
DogLog.setup('tmp.log', Logger::DEBUG)
|
7
|
+
|
8
|
+
module Watcher
|
9
|
+
class DummyWatcher < Watcher::Base
|
10
|
+
def initialize(config)
|
11
|
+
@watchit = config[:watchit]
|
12
|
+
end
|
13
|
+
def watch_it!
|
14
|
+
@watchit
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module WatcherAction
|
21
|
+
class DummyAction
|
22
|
+
def initialize(config)
|
23
|
+
end
|
24
|
+
def execute(event)
|
25
|
+
@executed = true
|
26
|
+
raise(Exception) unless(event.is_a?(WatcherEvent))
|
27
|
+
raise(ArgumentError, "Boom!")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Add some methods to the test case class
|
33
|
+
class Test::Unit::TestCase # :nodoc:
|
34
|
+
private
|
35
|
+
|
36
|
+
def action_status(name)
|
37
|
+
action = WatcherAction.instance_variable_get(:@registered_actions).get_value(name)
|
38
|
+
action.instance_variable_get(:@executed)
|
39
|
+
end
|
40
|
+
|
41
|
+
def clear_registered
|
42
|
+
Watcher.instance_variable_set(:@registered_watchers, nil)
|
43
|
+
WatcherAction.instance_variable_set(:@registered_actions, nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
data/test/watchdogger_test.rb
CHANGED
@@ -1,34 +1,9 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
2
|
|
3
|
-
module Watcher
|
4
|
-
class DummyWatcher < Watcher::Base
|
5
|
-
def initialize(config)
|
6
|
-
@watchit = config[:watchit]
|
7
|
-
end
|
8
|
-
def watch_it!
|
9
|
-
@watchit
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
module WatcherAction
|
16
|
-
class DummyAction
|
17
|
-
def initialize(config)
|
18
|
-
end
|
19
|
-
def execute(event)
|
20
|
-
@executed = true
|
21
|
-
raise(Exception) unless(event.is_a?(WatcherEvent))
|
22
|
-
raise(ArgumentError, "Boom!")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
3
|
class WatchdoggerTest < Test::Unit::TestCase
|
28
4
|
|
29
5
|
def setup
|
30
|
-
|
31
|
-
WatcherAction.instance_variable_set(:@registered_actions, nil)
|
6
|
+
clear_registered
|
32
7
|
WatcherAction.register('default', { :type => 'dummy_action' })
|
33
8
|
WatcherAction.register('log_action', { 'type' => :log_action })
|
34
9
|
Watcher.register('dummy', { :type => 'dummy_watcher', 'actions' => [ :default, :log_action ] })
|
@@ -85,10 +60,4 @@ class WatchdoggerTest < Test::Unit::TestCase
|
|
85
60
|
assert_equal(true, action_status('default'))
|
86
61
|
end
|
87
62
|
|
88
|
-
private
|
89
|
-
|
90
|
-
def action_status(name)
|
91
|
-
action = WatcherAction.instance_variable_get(:@registered_actions).get_value(name)
|
92
|
-
action.instance_variable_get(:@executed)
|
93
|
-
end
|
94
63
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: averell23-watchdogger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Hahn
|
@@ -85,12 +85,14 @@ files:
|
|
85
85
|
- lib/watcher_action/htpost.rb
|
86
86
|
- lib/watcher_action/kill_process.rb
|
87
87
|
- lib/watcher_action/log_action.rb
|
88
|
+
- lib/watcher_action/meta_action.rb
|
88
89
|
- lib/watcher_action/send_mail.rb
|
89
90
|
- lib/watcher_action.rb
|
90
91
|
- lib/watcher_event.rb
|
91
92
|
- test/http_watcher_test.rb
|
92
93
|
- test/kill_process_test.rb
|
93
94
|
- test/log_watcher_test.rb
|
95
|
+
- test/meta_action_test.rb
|
94
96
|
- test/test_helper.rb
|
95
97
|
- test/watchdogger_test.rb
|
96
98
|
- bin/watchdogger
|