servicemonitor 0.0.12 → 0.0.13
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/README.md +12 -1
- data/bin/servicemonitor +14 -11
- data/lib/Alert.rb +1 -1
- data/lib/Alert/Email.rb +4 -2
- data/lib/MonitorManager.rb +3 -2
- data/lib/MonitorType.rb +40 -4
- data/lib/MonitorType/Beanstalk.rb +7 -1
- data/lib/MonitorType/Dir.rb +4 -0
- data/lib/MonitorType/FluidDb.rb +13 -1
- data/lib/MonitorType/Threshold.rb +3 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -1,7 +1,18 @@
|
|
1
1
|
#ServiceMonitor
|
2
2
|
|
3
|
-
Monitor various parts of
|
3
|
+
Monitor various parts of a system
|
4
4
|
|
5
5
|
##Principles
|
6
6
|
#This is aimed at people with computer knowledge
|
7
7
|
#The DSL should be clean to read, at the expense of a steeper learning curve
|
8
|
+
#Tell users what is wrong as precisley as possible, with possible remedy's
|
9
|
+
|
10
|
+
##Get it
|
11
|
+
#gem install servicemonitor
|
12
|
+
|
13
|
+
##Run it
|
14
|
+
#Have a look at the dsl's in the Example directory
|
15
|
+
#servicemonitor <path to dsl>
|
16
|
+
|
17
|
+
##Notes
|
18
|
+
#Plays well with upstart and foreman
|
data/bin/servicemonitor
CHANGED
@@ -24,27 +24,30 @@ def log( string, verbose=false )
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
|
27
28
|
if ARGV.length == 1 then
|
28
29
|
dslName = ARGV[0]
|
29
30
|
else
|
30
31
|
abort( "Usage: monitor <path to dsl>" )
|
31
32
|
end
|
32
33
|
|
34
|
+
#Need to remove file name extension
|
35
|
+
ENV["APP_NAME"] = File.basename( dslName ) if ENV["APP_NAME"].nil?
|
33
36
|
|
34
37
|
$a = MonitorManager.new
|
35
38
|
|
36
39
|
log "Loading dsl, #{dslName}"
|
37
40
|
begin
|
38
|
-
load dslName
|
39
|
-
$a.run
|
40
|
-
rescue ArgumentError=>e
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
rescue SystemExit=>e
|
45
|
-
rescue SIGTERM=>e
|
46
|
-
rescue Exception=>e
|
47
|
-
|
48
|
-
|
41
|
+
load dslName
|
42
|
+
$a.run
|
43
|
+
rescue ArgumentError=>e
|
44
|
+
puts "*** Your dsl is not formatted correctly"
|
45
|
+
puts "*** Ensure each line has the format,"
|
46
|
+
puts "*** <command>, [:arg=>value]"
|
47
|
+
rescue SystemExit=>e
|
48
|
+
# rescue SIGTERM=>e
|
49
|
+
rescue Exception=>e
|
50
|
+
puts e.class.name
|
51
|
+
puts e.message
|
49
52
|
end
|
50
53
|
|
data/lib/Alert.rb
CHANGED
data/lib/Alert/Email.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "net/smtp"
|
2
2
|
require "Alert"
|
3
3
|
|
4
|
+
#Email alert class
|
5
|
+
#Uses localhost for sending email - Probably need to change this in the future.
|
4
6
|
class Alert_Email
|
5
7
|
def initialize( destination, body )
|
6
8
|
@destination = destination
|
@@ -10,9 +12,9 @@ class Alert_Email
|
|
10
12
|
def Send
|
11
13
|
|
12
14
|
message = <<MESSAGE_END
|
13
|
-
From:
|
15
|
+
From: #{ENV['APP_NAME']} <girvine@lic.co.nz>
|
14
16
|
To: #{@destination}
|
15
|
-
Subject:
|
17
|
+
Subject: #{ENV['APP_NAME']} Alert
|
16
18
|
|
17
19
|
#{@body}
|
18
20
|
.
|
data/lib/MonitorManager.rb
CHANGED
@@ -8,6 +8,7 @@ class MonitorManager
|
|
8
8
|
@list.push monitor
|
9
9
|
end
|
10
10
|
|
11
|
+
#The main run loop
|
11
12
|
def run
|
12
13
|
while true do
|
13
14
|
@list.each do |m|
|
@@ -18,12 +19,12 @@ class MonitorManager
|
|
18
19
|
m.alert( e.message )
|
19
20
|
end
|
20
21
|
end
|
21
|
-
sleep 0.
|
22
|
+
sleep 0.2
|
22
23
|
end
|
23
24
|
|
24
25
|
rescue Interrupt => e
|
25
26
|
puts "Exiting on request ..."
|
26
|
-
|
27
|
+
|
27
28
|
rescue Exception => e
|
28
29
|
puts e.class.name
|
29
30
|
puts "*** This is really unexpected."
|
data/lib/MonitorType.rb
CHANGED
@@ -1,10 +1,23 @@
|
|
1
1
|
require 'parse-cron'
|
2
2
|
|
3
|
+
#This is provided for reporting purposes.
|
4
|
+
# If this is raised on startup, the process will fail, and stop running.
|
5
|
+
# If this is raised after startup, the process will report, but keep running.
|
6
|
+
#
|
7
|
+
#The idea is to provide clear direction to the user to fix the error, but
|
8
|
+
# not stop all monitors in case of a production issue.
|
3
9
|
class MonitorTypeExceptionHandled<StandardError
|
4
10
|
end
|
5
11
|
|
12
|
+
#Base class for Monitors
|
13
|
+
#
|
14
|
+
#Given that this is a DSL, it extracts named parameters from a hash in order to provide
|
15
|
+
#more precise reporting of errors, without spewing syntax errors at a user
|
6
16
|
class MonitorType
|
7
17
|
|
18
|
+
#Check that all required parameters have been passed in
|
19
|
+
#Make sure that any errors encountered are reported in a way that
|
20
|
+
# fixing the error is made easier
|
8
21
|
def initialize( params )
|
9
22
|
if params[:name].nil? then
|
10
23
|
puts "*** Monitor parameter missing, name"
|
@@ -13,6 +26,22 @@ class MonitorType
|
|
13
26
|
end
|
14
27
|
@name = params[:name]
|
15
28
|
@email = params[:email]
|
29
|
+
if !@email.nil? then
|
30
|
+
if params[:email_sender].nil? then
|
31
|
+
if ENV["EMAIL_SENDER"].nil? then
|
32
|
+
puts "*** Alert parameter missing, email_sender"
|
33
|
+
puts "*** An email recipient has been specified for monitor, #{@name}, but no email sender has been specified"
|
34
|
+
puts "*** :email_sender => <email of sender>"
|
35
|
+
puts "*** or, a catch all environment variable"
|
36
|
+
puts "*** EMAIL_SENDER=<email of sender>"
|
37
|
+
abort
|
38
|
+
else
|
39
|
+
@admin_email = ENV["EMAIL_SENDER"]
|
40
|
+
end
|
41
|
+
else
|
42
|
+
@admin_email = params[:admin_email]
|
43
|
+
end
|
44
|
+
end
|
16
45
|
|
17
46
|
cron_string = params[:cron] || "0 1 * * *"
|
18
47
|
@cron = CronParser.new(cron_string)
|
@@ -21,14 +50,19 @@ class MonitorType
|
|
21
50
|
log "Loaded Monitor, #{@name}."
|
22
51
|
end
|
23
52
|
|
24
|
-
#Overload this method if any parameters should be checked
|
53
|
+
#Overload this method if any parameters should be checked in context
|
25
54
|
def sanitise
|
26
55
|
end
|
27
56
|
|
57
|
+
#Check if the monitor has tripped
|
28
58
|
def process
|
29
59
|
raise "Method needs to be overridden"
|
30
60
|
end
|
31
61
|
|
62
|
+
#An extention of the main run loop.
|
63
|
+
#Each monitor is responsible for knowing when it should run, so this function
|
64
|
+
#is called pretty much continuosuly.
|
65
|
+
#
|
32
66
|
def run
|
33
67
|
if Time.now > @next then
|
34
68
|
begin
|
@@ -37,18 +71,20 @@ class MonitorType
|
|
37
71
|
self.sanitise
|
38
72
|
self.process
|
39
73
|
rescue MonitorTypeExceptionHandled => e
|
40
|
-
|
74
|
+
self.alert( e.message )
|
41
75
|
end
|
42
76
|
end
|
43
77
|
end
|
44
78
|
|
45
|
-
|
79
|
+
#Called when a monitor has been tripped
|
80
|
+
#
|
81
|
+
# @param [String] string A description of the trip that occurred
|
46
82
|
def alert( string )
|
47
83
|
body = "#{@name} tripped.\n#{string}"
|
48
84
|
puts "*** "
|
49
85
|
if !@email.nil? then
|
50
86
|
Alert_Email.new( @email, body ).Send
|
51
|
-
puts "Emailed, @email
|
87
|
+
puts "Emailed, #{@email}"
|
52
88
|
else
|
53
89
|
puts body
|
54
90
|
end
|
@@ -1,15 +1,21 @@
|
|
1
1
|
require "beanstalk-client"
|
2
2
|
require "MonitorType/Threshold"
|
3
3
|
|
4
|
+
#A Beanstalk class for checking how many msgs are in a Queue
|
4
5
|
class MonitorType_Beanstalk<MonitorType_Threshold
|
5
|
-
|
6
|
+
|
6
7
|
def sanitise
|
7
8
|
@beanstalk = Beanstalk::Pool.new([@connection_string])
|
8
9
|
end
|
9
10
|
|
11
|
+
#Constructor: Extract parameters
|
12
|
+
#
|
13
|
+
# @param [String] beanstalk Optional connection string. Default to local
|
14
|
+
# @param [String] queue Name of queue to monitor
|
10
15
|
def initialize( params )
|
11
16
|
super( params )
|
12
17
|
@connection_string = params[:beanstalk] || "localhost:11300"
|
18
|
+
|
13
19
|
if params[:queue].nil? then
|
14
20
|
puts "*** Beanstalk parameter missing, queue"
|
15
21
|
puts "*** :queue => <queue name>"
|
data/lib/MonitorType/Dir.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "MonitorType/Threshold"
|
2
2
|
|
3
|
+
#A directory class for checking how many files are in a directory
|
3
4
|
class MonitorType_Dir<MonitorType_Threshold
|
4
5
|
|
5
6
|
def sanitise
|
@@ -22,6 +23,9 @@ class MonitorType_Dir<MonitorType_Threshold
|
|
22
23
|
raise MonitorTypeExceptionHandled.new(string)
|
23
24
|
end
|
24
25
|
|
26
|
+
#Constructor: Extract parameters
|
27
|
+
#
|
28
|
+
# @param [String] path Path to directory to check
|
25
29
|
def initialize( params )
|
26
30
|
super( params )
|
27
31
|
if params[:path].nil? then
|
data/lib/MonitorType/FluidDb.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
require "FluidDb"
|
2
2
|
require "MonitorType/Threshold"
|
3
3
|
|
4
|
+
#A database class for checking a single number against a threshold.
|
5
|
+
# For example,
|
6
|
+
# get the max timestamp from a table as a date.
|
7
|
+
# subtract this from now
|
8
|
+
# => check that the number is not greater than 2
|
9
|
+
|
4
10
|
class MonitorType_FluidDb<MonitorType_Threshold
|
5
11
|
|
12
|
+
#Create the connection to the db, and get the value
|
13
|
+
#This ensures that all params are correct.
|
6
14
|
def sanitise
|
7
15
|
begin
|
8
16
|
@fluidDb = FluidDb.Db( @uri )
|
@@ -13,7 +21,7 @@ class MonitorType_FluidDb<MonitorType_Threshold
|
|
13
21
|
puts "*** Please fix the error and run again"
|
14
22
|
abort()
|
15
23
|
end
|
16
|
-
|
24
|
+
|
17
25
|
begin
|
18
26
|
value = @fluidDb.queryForValue( @sql, [] )
|
19
27
|
rescue Exception=>e
|
@@ -24,6 +32,10 @@ class MonitorType_FluidDb<MonitorType_Threshold
|
|
24
32
|
end
|
25
33
|
end
|
26
34
|
|
35
|
+
#Constructor: Extract parameters
|
36
|
+
#
|
37
|
+
# @param [String] uri Connection string to db
|
38
|
+
# @param [String] sql SQL statement to gather a single value
|
27
39
|
def initialize( params )
|
28
40
|
super( params )
|
29
41
|
if params[:uri].nil? then
|
@@ -1,12 +1,15 @@
|
|
1
1
|
|
2
|
+
#A base class for checking a number against a min and/or max value
|
2
3
|
class MonitorType_Threshold<MonitorType
|
3
4
|
|
5
|
+
#See super method for generic description
|
4
6
|
def initialize( params )
|
5
7
|
@min = params[:min] ||= 0
|
6
8
|
@max = params[:max]
|
7
9
|
super( params )
|
8
10
|
end
|
9
11
|
|
12
|
+
#Provides the means to check a value against thresholds
|
10
13
|
def check( value, context_sentence )
|
11
14
|
value = value.to_i
|
12
15
|
if !@min.nil? && value < @min then
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: servicemonitor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-10-
|
12
|
+
date: 2013-10-27 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Monitor various parts of the system
|
15
15
|
email: guy@guyirvine.com
|