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 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