servicemonitor 0.1.4 → 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.
@@ -1,45 +0,0 @@
1
- require "beanstalk-client"
2
- require "MonitorType/Threshold"
3
-
4
- #A Beanstalk class for checking how many msgs are in a Queue
5
- class MonitorType_Beanstalk<MonitorType_Threshold
6
-
7
- #Extract parameters
8
- #
9
- # @param [String] beanstalk Optional connection string. Default to local
10
- # @param [String] queue Name of queue to monitor
11
- def extractParams()
12
- @connection_string = @params[:beanstalk] || "localhost:11300"
13
-
14
- if @params[:queue].nil? then
15
- string = "*** Beanstalk parameter missing, queue\n"
16
- string = "#{string}*** :queue => <queue name>"
17
- raise MonitorTypeParameterMissingError.new(string)
18
- end
19
- @queue = @params[:queue]
20
-
21
- @context_sentence = "Checking number of jobs in queue, #{@queue}"
22
-
23
- end
24
-
25
- def setup
26
- @beanstalk = Beanstalk::Pool.new([@connection_string])
27
- end
28
-
29
-
30
- def getValue
31
- count = 0
32
- begin
33
- tubeStats = @beanstalk.stats_tube(@queue)
34
- count = tubeStats["current-jobs-ready"]
35
- rescue Beanstalk::NotFoundError=>e
36
- end
37
-
38
- return count
39
- end
40
- end
41
-
42
- def beanstalk( params )
43
- $a.add( MonitorType_Beanstalk.new( params ) )
44
- end
45
-
@@ -1,45 +0,0 @@
1
- require "MonitorType/Threshold"
2
-
3
- #A directory class for checking how many files are in a directory
4
- class MonitorType_Dir<MonitorType_Threshold
5
-
6
- #Extract parameters
7
- #
8
- # @param [String] path Path to directory to check
9
- def extractParams()
10
- if @params[:path].nil? then
11
- string = "*** Dir parameter missing, path\n"
12
- string = "#{string}*** :path => <path to directory to be monitored>"
13
- raise MonitorTypeParameterMissingError.new(string)
14
- end
15
- @path = @params[:path]
16
-
17
- @context_sentence = "Checking number of files in, #{@path}"
18
- end
19
-
20
-
21
- def setup
22
- inputDir = Dir.new( @path )
23
- @path = inputDir.path
24
- @params[:dir] = inputDir
25
-
26
- rescue Errno::ENOENT => e
27
- string = "***** Directory does not exist, #{@path}.\n"
28
- string = "#{string}***** Create the directory, #{@path}, and try again.\n"
29
- string = "#{string}***** eg, mkdir #{@path}"
30
- raise MonitorTypeExceptionHandled.new(string)
31
- rescue Errno::ENOTDIR => e
32
- string = "***** The specified path does not point to a directory, #{@path}.\n"
33
- string = "#{string}***** Either repoint path to a directory, or remove, #{@path}, and create it as a directory.\n"
34
- string = "#{string}***** eg, rm #{@path} && mkdir #{@path}"
35
- raise MonitorTypeExceptionHandled.new(string)
36
- end
37
-
38
- def getValue
39
- return Dir.glob( "#{@path}/*" ).length
40
- end
41
- end
42
-
43
- def dir( params )
44
- $a.add( MonitorType_Dir.new( params ) )
45
- end
@@ -1,50 +0,0 @@
1
- require "MonitorType/Threshold"
2
- require "sys/filesystem"
3
- include Sys
4
-
5
- class MonitorType_Drive<MonitorType_Threshold
6
-
7
- def extractParams
8
- if @params[:path].nil? then
9
- string = "*** Drive parameter missing, drive\n"
10
- string = "#{string}*** :drive => <name of the drive to be monitored>"
11
- raise MonitorTypeParameterMissingError.new(string)
12
- end
13
- @path = @params[:path]
14
-
15
- log "#{@process_name}", "result: #{(@process_name =~ /^(.*\[{1}.+\]{1}.*)$|^(\w+)$/) == 0}"
16
-
17
- if @params[:min].nil? then
18
- string = "*** Min parameter missing, min\n"
19
- string = "#{string}*** :min => <the minimum amount of free space on the drive to be monitored>"
20
- raise MonitorTypeParameterMissingError.new(string)
21
- end
22
-
23
- log "*** Max value will be ignored, setting to nil" unless @params[:max].nil?
24
- @max = nil
25
-
26
- @context_sentence = "Checking that available drive space is greater than min, #{@process_name}"
27
- end
28
-
29
- def setup
30
- begin
31
- #Check that the path exists
32
- drive = Filesystem.stat(@path)
33
-
34
- rescue=>e
35
- string = "*** Unable to mount the specifed path\n"
36
- string = "#{string}*** path: #{@path}\n"
37
- string = "#{string}*** Please fix the error and run again\n"
38
- raise MonitorTypeExceptionHandled.new("Unable to mount path: #{@path}")
39
- end
40
- end
41
-
42
- def getValue
43
- return ((Filesystem.stat(@path).blocks_available.to_f / Filesystem.stat(@path).blocks.to_f) * 100).round(2)
44
- end
45
-
46
- end
47
-
48
- def process(params)
49
- $a.add(MonitorType_Drive.new(params))
50
- end
@@ -1,77 +0,0 @@
1
- require "FluidDb"
2
- require "MonitorType/Threshold"
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
-
10
- class MonitorType_FluidDb<MonitorType_Threshold
11
-
12
- #Extract parameters
13
- #
14
- # @param [String] uri Connection string to db
15
- # @param [String] sql SQL statement to gather a single value
16
- def extractParams
17
- if @params[:uri].nil? then
18
- string = "*** FluidDb parameter missing, uri\n"
19
- string = "#{string}*** :uri => <uri pointing to db to be monitored>"
20
- raise MonitorTypeParameterMissingError.new(string)
21
- end
22
- begin
23
- @uri = URI.parse( @params[:uri] )
24
- rescue URI::InvalidURIError=>e
25
- string = "*** FluidDb encountered an error while parsing the uri"
26
- string = "#{string}*** uri: #{@params[:uri]}"
27
- string = "#{string}*** Please fix the uri and run again"
28
- raise MonitorTypeParameterMissingError.new(string)
29
- end
30
-
31
- if @params[:sql].nil? then
32
- string = "*** FluidDb parameter missing, sql"
33
- string = "#{string}*** :sql => <sql statement, producing a single column, single row which yeidls a number>"
34
- raise MonitorTypeParameterMissingError.new(string)
35
- end
36
- @sql = @params[:sql]
37
-
38
- @context_sentence = "Checking result of sql query, #{@sql}"
39
-
40
- end
41
-
42
- #Create the connection to the db, and get the value
43
- #This ensures that all params are correct.
44
- def setup
45
-
46
- begin
47
- @fluidDb = FluidDb.Db( @uri )
48
- rescue Exception=>e
49
- string = "*** FluidDb encountered an error while connecting to the db\n"
50
- string = "#{string}*** Error: #{e.message}\n"
51
- string = "#{string}*** uri: #{@uri}\n"
52
- string = "#{string}*** Please fix the error and run again\n"
53
- raise MonitorTypeExceptionHandled.new(string)
54
- end
55
-
56
- @params[:fluidDb] = @fluidDb
57
- end
58
-
59
- def getValue
60
- begin
61
- return @fluidDb.queryForValue( @sql, [] )
62
- rescue Exception=>e
63
- string = "*** FluidDb encountered an error while running the sql\n"
64
- string = "#{string}*** sql: #{@sql}\n"
65
- string = "#{string}*** Please fix the query and run again\n"
66
- raise MonitorTypeExceptionHandled.new(string)
67
- end
68
- end
69
-
70
- def teardown
71
- @fluidDb.close
72
- end
73
- end
74
-
75
- def fluiddb( params )
76
- $a.add( MonitorType_FluidDb.new( params ) )
77
- end
@@ -1,58 +0,0 @@
1
- require "restclient"
2
- require "MonitorType/Threshold"
3
-
4
- #An http class for checking the length of a json list.
5
- # For example,
6
- # Get the list of outstandinig errors
7
- # => check that the number is not greater than 2
8
-
9
- class MonitorType_HttpGetJsonList<MonitorType_Threshold
10
-
11
- #Extract parameters
12
- #
13
- # @param [String] uri Connection string to db
14
- # @param [String] sql SQL statement to gather a single value
15
- def extractParams
16
- if @params[:uri].nil? then
17
- string = "*** HttpGetJsonList parameter missing, uri\n"
18
- string = "#{string}*** :uri => <uri pointing to url to be monitored>"
19
- raise MonitorTypeParameterMissingError.new(string)
20
- end
21
-
22
- begin
23
- @uri = URI.parse( @params[:uri] )
24
- rescue URI::InvalidURIError=>e
25
- string = "*** HttpGetJsonList encountered an error while parsing the uri"
26
- string = "#{string}*** uri: #{@params[:uri]}"
27
- string = "#{string}*** Please fix the uri and run again"
28
- raise MonitorTypeParameterMissingError.new(string)
29
- end
30
-
31
- url = "#{@uri.scheme}://#{@uri.host}#{@uri.path}"
32
- @context_sentence = "Checking size of json list returned from, #{url}"
33
-
34
- end
35
-
36
- def getValue
37
- begin
38
- content = RestClient.get( @uri.to_s )
39
- list = JSON.parse( content )
40
- raise MonitorTypeExceptionHandled.new( "Expected type, Array - Actual type, #{list.class.name}") unless list.class.name == "Array"
41
- return list.length
42
-
43
- rescue MonitorTypeExceptionHandled=>e
44
- raise e
45
-
46
- rescue Exception=>e
47
- string = "*** HttpGetJsonList encountered an error while running the HTTP Get\n"
48
- string = "#{string}*** uri: #{@uri}\n"
49
- string = "#{string}*** Please fix the query and run again\n"
50
-
51
- raise MonitorTypeExceptionHandled.new(string)
52
- end
53
- end
54
- end
55
-
56
- def httpgetjsonlist( params )
57
- $a.add( MonitorType_HttpGetJsonList.new( params ) )
58
- end
@@ -1,57 +0,0 @@
1
- require "MonitorType/Threshold"
2
- require "helper_functions"
3
-
4
- InvalidProcessNameError = Class.new(StandardError)
5
-
6
- #A class for checking if a Process is running in Unix based systems
7
- class MonitorType_Process<MonitorType_Threshold
8
-
9
- #Extract parameters
10
- #
11
- # @param [String] :process_name THe name of the process to monitor
12
- def extractParams
13
- if @params[:process_name].nil? then
14
- string = "*** Process Name parameter missing, process_name\n"
15
- string = "#{string}*** :process_name => <name of the process to be monitored>"
16
- raise MonitorTypeParameterMissingError.new(string)
17
- end
18
- @process_name = @params[:process_name]
19
-
20
- log "#{@process_name}", "result: #{(@process_name =~ /^(.*\[{1}.+\]{1}.*)$|^(\w+)$/) == 0}"
21
-
22
- unless (@process_name =~ /^(.*\[{1}.+\]{1}.*)$|^(\w+)$/) == 0 then
23
- string = "*** Process Name parameter doest not match the required pattern, #{@process_name}\n"
24
- string = "#{string}*** :process_name => <plain string, or a string with one or more characters enclosed in square brackets, i.e. 'foo', '[f]oo' or '[foo]'>"
25
- raise InvalidProcessNameError.new(string)
26
- end
27
-
28
- log "*** Min value will be ignored, setting to 1" unless (params[:min].nil? || params[:min] == 0)
29
- @min = 1
30
-
31
- log "*** Max value will be ignored, setting to nil" unless params[:max].nil?
32
- @max = nil
33
-
34
- @context_sentence = "Checking that process is running, #{@process_name}"
35
- end
36
-
37
- def setup
38
- self.sanitise
39
- rescue MonitorTypeExceptionHandled => e
40
- puts e.message
41
- abort
42
- end
43
-
44
- def sanitise
45
- #Ensure that the process name contains a single character surrounded by square brackets
46
- @process_name = @process_name.insert(0,'[').insert(2,']') unless @process_name =~ /^.*\[.+\].*/
47
- end
48
-
49
- def getValue
50
- return `ps aux | grep #{@process_name}`.length
51
- end
52
-
53
- end
54
-
55
- def process(params)
56
- $a.add(MonitorType_Process.new(params))
57
- end
@@ -1,50 +0,0 @@
1
-
2
- #A base class for checking a number against a min and/or max value
3
- class MonitorType_Threshold<MonitorType
4
-
5
- #See super method for generic description
6
- def initialize( params )
7
- @min = params[:min] ||= 0
8
- @max = params[:max]
9
- super( params )
10
- end
11
-
12
- #Get the context dependent value which is to be checked
13
- def getValue
14
- raise "Method needs to be overridden"
15
- end
16
-
17
- def process
18
- if @block.nil? then
19
- value = self.getValue
20
- else
21
- value = @block.call( @params )
22
- string = "value: #{value}\n"
23
- puts string
24
- end
25
-
26
- self.check( value )
27
- end
28
-
29
- #Provides the means to check a value against thresholds
30
- def check( value )
31
- context_sentence = ""
32
- unless @context_sentence.nil? then
33
- context_sentence = "#{@context_sentence}\n"
34
- end
35
-
36
- url = ""
37
- unless @url.nil? then
38
- url = "\n\n#{@url}\n"
39
- end
40
-
41
- value = value.to_i
42
- if !@min.nil? && value < @min then
43
- self.alert( "#{context_sentence}Minimum threshold exceeded. Minimum: #{@min}, Actual: #{value}#{url}" )
44
- end
45
- if !@max.nil? && value > @max then
46
- self.alert( "#{context_sentence}Maximum threshold exceeded. Maximum: #{@max}, Actual: #{value}#{url}" )
47
- end
48
-
49
- end
50
- end
data/lib/MonitorType.rb DELETED
@@ -1,119 +0,0 @@
1
- require 'parse-cron'
2
-
3
- #This is provided for reporting purposes.
4
- # It essentially indicates if an error case was expected
5
- #
6
- #The idea is to provide clear direction to the user to fix the error, but
7
- # not stop all monitors in case of a production issue.
8
- class MonitorTypeExceptionHandled<StandardError
9
- end
10
-
11
- class MonitorTypeParameterMissingError<MonitorTypeExceptionHandled
12
- end
13
-
14
- class MonitorTypeMustHaveNameError<MonitorTypeParameterMissingError
15
- end
16
-
17
- class MonitorTypeMustHaveSenderEmailAddressForEmailAlertError<MonitorTypeParameterMissingError
18
- end
19
-
20
-
21
- #Base class for Monitors
22
- #
23
- #Given that this is a DSL, it extracts named parameters from a hash in order to provide
24
- #more precise reporting of errors, without spewing syntax errors at a user
25
- class MonitorType
26
-
27
- #Check that all required parameters have been passed in
28
- #Make sure that any errors encountered are reported in a way that
29
- # fixing the error is made easier
30
- def initialize( params )
31
- if params[:name].nil? then
32
- string = "*** Monitor parameter missing, name"
33
- string = "#{string}*** :name => <name of monitor>"
34
- raise MonitorTypeMustHaveNameError.new(string)
35
- end
36
- @params = params
37
- @block = params[:block] unless params[:block].nil?
38
- @name = params[:name]
39
- @email = params[:email]
40
- @url = params[:url] unless params[:url].nil?
41
-
42
- if !@email.nil? then
43
- #Sender email address from ENV allows for a single sender across all alerts
44
- #Checking params before ENV allows a particular entry to be different
45
- if params[:email_sender].nil? then
46
- if ENV["EMAIL_SENDER"].nil? then
47
- string = "*** Alert parameter missing, email_sender"
48
- string = "#[string}*** An email recipient has been specified for monitor, #{@name}, but no email sender has been specified"
49
- string = "#[string}*** :email_sender => <email of sender>"
50
- string = "#[string}*** or, a catch all environment variable"
51
- string = "#[string}*** EMAIL_SENDER=<email of sender>"
52
-
53
- raise MonitorTypeMustHaveSenderEmailAddressForEmailAlertError.new(string)
54
- else
55
- @sender_email = ENV["EMAIL_SENDER"]
56
- end
57
- else
58
- @sender_email = params[:admin_email]
59
- end
60
- end
61
-
62
- cron_string = params[:cron] || "0 1 * * *"
63
- @cron = CronParser.new(cron_string)
64
- @next = Time.now - 1
65
-
66
- log "Loaded Monitor, #{@name}."
67
- end
68
-
69
- #Overload this method if any parameters should be checked in context
70
- def extractParams
71
- end
72
-
73
- #Overload this method if any parameters should be checked in context
74
- def setup
75
- end
76
-
77
- #Overload this method if any parameters should be checked in context
78
- def teardown
79
- end
80
-
81
- #Check if the monitor has tripped
82
- def process
83
- raise "Method needs to be overridden"
84
- end
85
-
86
- #An extention of the main run loop.
87
- #Each monitor is responsible for knowing when it should run, so this function
88
- #is called pretty much continuosuly.
89
- #
90
- def run
91
- if Time.now > @next then
92
- begin
93
- @next = @cron.next( Time.now )
94
- log "Monitor, #{@name}, next run time, #{@next}"
95
- self.extractParams
96
- self.setup
97
- self.process
98
- self.teardown
99
- rescue MonitorTypeExceptionHandled => e
100
- self.alert( e.message )
101
- end
102
- end
103
- end
104
-
105
- #Called when a monitor has been tripped
106
- #
107
- # @param [String] string A description of the trip that occurred
108
- def alert( string )
109
- body = "#{@name} tripped.\n#{string}"
110
- puts "*** "
111
- if !@email.nil? then
112
- Alert_Email.new( @sender_email, @email, body ).Send
113
- puts "Emailed, #{@email}"
114
- else
115
- puts body
116
- end
117
- end
118
-
119
- end