servicemonitor 0.1.4 → 0.2.0

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