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 CHANGED
@@ -1,7 +1,18 @@
1
1
  #ServiceMonitor
2
2
 
3
- Monitor various parts of the system
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
- puts "*** Your dsl is not formatted correctly"
42
- puts "*** Ensure each line has the format,"
43
- puts "*** <command>, [:arg=>value]"
44
- rescue SystemExit=>e
45
- rescue SIGTERM=>e
46
- rescue Exception=>e
47
- puts e.class.name
48
- puts e.message
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
@@ -1,4 +1,4 @@
1
-
1
+ #Base class / Interface for implementing alert types
2
2
  class Alert
3
3
 
4
4
  def Send( destination, body )
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: Agrimetrics <girvine@lic.co.nz>
15
+ From: #{ENV['APP_NAME']} <girvine@lic.co.nz>
14
16
  To: #{@destination}
15
- Subject: Agrimetrics Alert
17
+ Subject: #{ENV['APP_NAME']} Alert
16
18
 
17
19
  #{@body}
18
20
  .
@@ -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.5
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
- m.alert( e.message )
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, Body, #{body}"
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>"
@@ -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
@@ -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.12
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-26 00:00:00.000000000 Z
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