servicemonitor 0.0.12 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|