averell23-watchdogger 0.1.4 → 0.1.5
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/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
|