averell23-watchdogger 0.1.5 → 0.2.0
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/watchdogger.rb +21 -3
- data/lib/watcher/base.rb +4 -15
- data/lib/watcher/http_watcher.rb +9 -3
- data/lib/watcher/log_watcher.rb +1 -0
- data/lib/watcher_action.rb +5 -0
- data/lib/watcher_action/kill_process.rb +21 -4
- data/lib/watcher_action/meta_action.rb +8 -6
- data/lib/watcher_action/send_mail.rb +21 -10
- data/sample_config.yml +10 -0
- metadata +11 -1
data/lib/watchdogger.rb
CHANGED
@@ -105,17 +105,23 @@ module WatchDogger # :nodoc:
|
|
105
105
|
# daemon is still running.
|
106
106
|
def check_daemon
|
107
107
|
return false unless(File.exists?(@pidfile))
|
108
|
-
|
108
|
+
check_process(get_pid)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Returns true if the system thinks that the given process is still alive
|
112
|
+
def check_process(pid)
|
109
113
|
begin
|
110
114
|
Process.kill(0, pid)
|
115
|
+
dog_log.debug('Watchdogger') { "Process #{pid} is alive" }
|
111
116
|
true
|
112
117
|
rescue Errno::EPERM
|
118
|
+
dog_log.debug('Watchdogger') { "No permissions for process #{pid} - seems to be running."}
|
113
119
|
true
|
114
120
|
rescue Errno::ESRCH
|
115
|
-
dog_log.
|
121
|
+
dog_log.debug('Watchdogger') { "Found stale process for #{pid}." }
|
116
122
|
false
|
117
123
|
rescue Exception => e
|
118
|
-
dog_log.
|
124
|
+
dog_log.info('Watchdogger') { "Could not find out if process #{pid} still runs (#{e.message}). Hoping for the best..." }
|
119
125
|
false
|
120
126
|
end
|
121
127
|
end
|
@@ -174,4 +180,16 @@ class Hash # :nodoc:
|
|
174
180
|
value
|
175
181
|
end
|
176
182
|
|
183
|
+
# Gets the given key as an array. If it's already an array, it will be returned,
|
184
|
+
# otherwise we'll check if it's a comma-separated list. The
|
185
|
+
# default will be processed in the same way as if was read from the Hash.
|
186
|
+
def get_list(sym_or_string, default = nil)
|
187
|
+
value = get_value(sym_or_string, default)
|
188
|
+
return value if(value.is_a?(Array))
|
189
|
+
assit(value.is_a?(String) || value.is_a?(Symbol))
|
190
|
+
value = value.to_s.split(',').collect do |val|
|
191
|
+
val.strip
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
177
195
|
end
|
data/lib/watcher/base.rb
CHANGED
@@ -36,21 +36,10 @@ module Watcher
|
|
36
36
|
|
37
37
|
# Sets up all actions for this watcher
|
38
38
|
def setup_actions(configuration)
|
39
|
-
action_config = configuration.
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
else
|
44
|
-
assit(action_config.is_a?(String) || action_config.is_a?(Symbol))
|
45
|
-
add_action_to(actions, action_config)
|
46
|
-
end
|
47
|
-
warn_config = configuration.get_value(:warn_actions)
|
48
|
-
if(warn_config.is_a?(Array))
|
49
|
-
warn_config.each { |ac| add_action_to(warn_actions, ac) }
|
50
|
-
elsif(warn_config)
|
51
|
-
assit_kind_of(String, warn_config)
|
52
|
-
add_action_to(warn_actions, warn_config)
|
53
|
-
end
|
39
|
+
action_config = configuration.get_list(:actions, false)
|
40
|
+
action_config.each { |ac| add_action_to(actions, ac) }
|
41
|
+
warn_config = configuration.get_list(:warn_actions, [])
|
42
|
+
warn_config.each { |ac| add_action_to(warn_actions, ac) }
|
54
43
|
end
|
55
44
|
|
56
45
|
private
|
data/lib/watcher/http_watcher.rb
CHANGED
@@ -11,12 +11,16 @@ module Watcher
|
|
11
11
|
# [*content_match*] A regular expression that is matched against the result.
|
12
12
|
# The watcher fails if the expression doesn't match
|
13
13
|
# [*timeout*] The timeout for the connection attempt. Defaults to 10 sec
|
14
|
-
#
|
14
|
+
# [*falloff*] If a successful connection is made, this is subtracted from
|
15
|
+
# the internal severity. (Default: 100, completely reset previous
|
16
|
+
# failures)
|
17
|
+
#
|
15
18
|
# If neither response nor content_match are given, the watcher will expect a
|
16
19
|
# 200 OK response from the server.
|
17
20
|
#
|
18
21
|
# This watcher resets the current severity on each successful connect, so that
|
19
|
-
# only continuous failures count against the trigger condition
|
22
|
+
# only continuous failures count against the trigger condition - see the falloff
|
23
|
+
# option.
|
20
24
|
class HttpWatcher < Watcher::Base
|
21
25
|
|
22
26
|
def initialize(config)
|
@@ -26,6 +30,8 @@ module Watcher
|
|
26
30
|
response = config.get_value(:response)
|
27
31
|
@response = ((!response && !match) ? "200" : response)
|
28
32
|
@timeout = config.get_value(:timeout, 10).to_i
|
33
|
+
@falloff = config.get_value(:falloff, 100).to_i
|
34
|
+
@current_severity = 0
|
29
35
|
end
|
30
36
|
|
31
37
|
def watch_it!
|
@@ -40,7 +46,7 @@ module Watcher
|
|
40
46
|
elsif(@content_match && !@content_match.match(res.body))
|
41
47
|
test_failed = "Did not find #{@content_match.to_s} at #{@url}"
|
42
48
|
end
|
43
|
-
@current_severity = 0 unless(test_failed)
|
49
|
+
@current_severity = [0, @current_severity - @falloff].min unless(test_failed)
|
44
50
|
dog_log.debug('HttpWatcher') { "Watch of #{@url} resulted in #{test_failed}" }
|
45
51
|
test_failed
|
46
52
|
rescue Exception => e
|
data/lib/watcher/log_watcher.rb
CHANGED
data/lib/watcher_action.rb
CHANGED
@@ -34,6 +34,11 @@ module WatcherAction
|
|
34
34
|
def has_action?(name)
|
35
35
|
registered_actions[name.to_sym] != nil
|
36
36
|
end
|
37
|
+
|
38
|
+
# Checks if the given action is registered with that name
|
39
|
+
def is_action?(name, action)
|
40
|
+
registered_actions[name.to_sym] == action
|
41
|
+
end
|
37
42
|
|
38
43
|
private
|
39
44
|
|
@@ -5,17 +5,34 @@ module WatcherAction
|
|
5
5
|
# =Options
|
6
6
|
#
|
7
7
|
# [*pidfile*] The file containing the process id
|
8
|
-
# [*signal*] The signal to send to the process.
|
8
|
+
# [*signal*] The signal to send to the process.
|
9
|
+
# This may be an array or a comma-separated
|
10
|
+
# list of signals. If there is more than one signal, this
|
11
|
+
# will wait for _wait_ seconds before trying the next
|
12
|
+
# signal, if the process didn't die.
|
13
|
+
# Defaults to KILL
|
14
|
+
# [*wait*] Time to wait between signals (Default: 5)
|
9
15
|
class KillProcess
|
10
16
|
|
11
17
|
def initialize(config)
|
12
18
|
@pidfile = config.get_value(:pidfile, false)
|
13
|
-
@
|
19
|
+
@signals = config.get_list(:signal, 'KILL')
|
20
|
+
@wait = config.get_value(:wait, 5).to_i
|
14
21
|
end
|
15
22
|
|
16
23
|
def execute(event)
|
17
|
-
|
18
|
-
|
24
|
+
Thread.new(@signals, @wait, @pidfile) do |signals, wait, pidfile|
|
25
|
+
pid = File.open(pidfile) { |io| io.read }.to_i
|
26
|
+
signals.each_with_index do |signal, index|
|
27
|
+
sleep(wait) if(index > 0)
|
28
|
+
if(WatchDogger.check_process(pid))
|
29
|
+
dog_log.debug('KillerThread') { "Sending signal #{signal} to process #{pid}" }
|
30
|
+
Process.kill(signal, pid)
|
31
|
+
else
|
32
|
+
dog_log.debug('KillerThread') { "Process #{pid} is dead." }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
19
36
|
rescue Exception => e
|
20
37
|
dog_log.warn { "Unable to kill process: #{e}" }
|
21
38
|
end
|
@@ -10,18 +10,20 @@ module WatcherAction
|
|
10
10
|
class MetaAction
|
11
11
|
|
12
12
|
def initialize(config)
|
13
|
-
actions = config.
|
14
|
-
|
15
|
-
@actions = actions
|
16
|
-
else
|
17
|
-
@actions = [ actions ]
|
18
|
-
end
|
13
|
+
actions = config.get_list(:actions, false)
|
14
|
+
actions.each { |ac| add_action(ac) }
|
19
15
|
end
|
20
16
|
|
21
17
|
def execute(event)
|
22
18
|
@actions.each { |ac| WatcherAction.run_action(ac, event) }
|
23
19
|
end
|
24
20
|
|
21
|
+
def add_action(action)
|
22
|
+
@actions ||= []
|
23
|
+
raise(ArgumentError, "Trying to add myself, creating a loop.") if(WatcherAction.is_action?(action, self))
|
24
|
+
@actions << action
|
25
|
+
end
|
26
|
+
|
25
27
|
end
|
26
28
|
|
27
29
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'rmail'
|
2
|
+
require 'tlsmail' if(/^1.8/ =~ RUBY_VERSION) # Include the hack for ruby 1.8
|
2
3
|
require 'net/smtp'
|
4
|
+
require 'time'
|
3
5
|
|
4
6
|
module WatcherAction
|
5
7
|
|
6
8
|
# This action will send an email to a given receipient. It doesn't support any
|
7
|
-
# fancy features (you may want to do that handling externally)
|
8
|
-
# use unencrypted smtp network connections.
|
9
|
+
# fancy features (you may want to do that handling externally).
|
9
10
|
#
|
10
11
|
# =Options
|
11
12
|
#
|
@@ -21,18 +22,20 @@ module WatcherAction
|
|
21
22
|
# [*user*] Mail server user name
|
22
23
|
# [*pass*] Mail server password
|
23
24
|
# [*authentication*] Authentication method (default: plain)
|
25
|
+
# [*enable_tls*] Use the TLS encryption (default: false)
|
24
26
|
class SendMail
|
25
27
|
|
26
28
|
def initialize(config)
|
27
29
|
@mail_to = config.get_value(:to, false)
|
28
30
|
@sender = config.get_value(:sender, false)
|
29
|
-
@subject = config.get_value(:subject, "Watchdogger
|
31
|
+
@subject = config.get_value(:subject, "Watchdogger needs your attention.")
|
30
32
|
@body = config.get_value(:body)
|
31
33
|
@server = config.get_value(:server, 'localhost')
|
32
34
|
@port = config.get_value(:port, '25')
|
33
35
|
@user = config.get_value(:user)
|
34
36
|
@pass = config.get_value(:pass)
|
35
37
|
@authentication = config.get_value(:authentication, :plain).to_sym
|
38
|
+
@enable_tls = config.get_value(:enable_tls) || false
|
36
39
|
end
|
37
40
|
|
38
41
|
def execute(event)
|
@@ -40,7 +43,8 @@ module WatcherAction
|
|
40
43
|
msg.header.to = @mail_to
|
41
44
|
receipient = msg.header.to.to_s.split(',').first
|
42
45
|
msg.header.from = @sender
|
43
|
-
msg.header.subject =
|
46
|
+
msg.header.subject = @subject % [event.message]
|
47
|
+
msg.header.date = Time.now
|
44
48
|
if(@body.to_s == 'xml')
|
45
49
|
msg.body = event.to_xml
|
46
50
|
elsif(@body)
|
@@ -48,18 +52,25 @@ module WatcherAction
|
|
48
52
|
else
|
49
53
|
msg.body = "The #{event.watcher.class.name} watcher of your watchdog triggered\nan event at #{event.timestamp}:\n#{event.message}"
|
50
54
|
end
|
51
|
-
|
55
|
+
|
52
56
|
smtp_params = [@server, @port]
|
53
57
|
if(@user && @pass)
|
54
|
-
smtp_params
|
58
|
+
smtp_params.concat([nil, @user, @pass, @authentication])
|
55
59
|
end
|
56
60
|
|
57
|
-
Net::SMTP.
|
58
|
-
|
61
|
+
Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE) if(@enable_tls)
|
62
|
+
Thread.new(smtp_params, msg, @sender, @mail_to) do |params, msg, sender, mail_to|
|
63
|
+
begin
|
64
|
+
Net::SMTP.start(*params) do |smtp|
|
65
|
+
smtp.send_message(msg.to_s, sender, mail_to)
|
66
|
+
end
|
67
|
+
dog_log.debug('SMTP Thread') { "Sent mail to #{mail_to} through #{params.first}" }
|
68
|
+
rescue Exception => e
|
69
|
+
dog_log.error('SMTP Thread') { "Could not send mail to #{mail_to} on #{params.first}: #{e.message}" }
|
70
|
+
end
|
59
71
|
end
|
60
|
-
dog_log.debug('SMTP Action') { "Sent mail to #{@mail_to} through #{@server}" }
|
61
72
|
rescue Exception => e
|
62
|
-
dog_log.
|
73
|
+
dog_log.error('SMTP Action') { "Could not send mail to #{@mail_to} on #{@server}: #{e.message}" }
|
63
74
|
end
|
64
75
|
|
65
76
|
end
|
data/sample_config.yml
CHANGED
@@ -3,6 +3,16 @@
|
|
3
3
|
actions:
|
4
4
|
log_it:
|
5
5
|
type: log_action
|
6
|
+
mail_message:
|
7
|
+
type: send_mail
|
8
|
+
to: one@gmail.com
|
9
|
+
sender: myself@gmail.com
|
10
|
+
server: smtp.gmail.com
|
11
|
+
user: test@gmail.com
|
12
|
+
pass: secret
|
13
|
+
port: 587
|
14
|
+
authentication: login
|
15
|
+
enable_tls: true
|
6
16
|
|
7
17
|
watchers:
|
8
18
|
test_hn:
|
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.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Hahn
|
@@ -62,6 +62,16 @@ dependencies:
|
|
62
62
|
- !ruby/object:Gem::Version
|
63
63
|
version: 0.6.5
|
64
64
|
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: tlsmail
|
67
|
+
type: :runtime
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.0.1
|
74
|
+
version:
|
65
75
|
description: A small flexible watchdog system to monitor servers.
|
66
76
|
email: ghub@limitedcreativity.org
|
67
77
|
executables:
|