simple_monitor 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rspec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in simple_monitor.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ SimpleMonitor
2
+ =============
3
+
4
+ Send alerts based on simple monitored conditions in your app.
5
+
6
+ It provides a basic skeleton for writing unique but consistent
7
+ monitoring checks for your application. Examples of such checks
8
+ are a Delayed::Job queue that is too full, too many failed logins
9
+ in the last 5 minutes, or a remote service being unreachable.
10
+
11
+ Installation
12
+ ------------
13
+
14
+ install it via rubygems:
15
+
16
+ ```
17
+ gem install simple_monitor
18
+ ```
19
+
20
+ or put it in your Gemfile:
21
+
22
+ ```ruby
23
+ # Gemfile
24
+ gem 'simple_monitor'
25
+ ```
26
+
27
+ Usage
28
+ -----
29
+
30
+ SimpleMonitor should be mixed in to a SomeConditionMonitor class
31
+
32
+ ```ruby
33
+ require "simple_monitor"
34
+
35
+ class HighJobMonitor
36
+ include SimpleMonitor
37
+
38
+ def needs_alert?
39
+ Queue.jobs.count > options[:job_count_threshold]
40
+ end
41
+
42
+ def send_alert
43
+ # Alert sending method of your choice. SimpleMonitor
44
+ # leaves this up to you
45
+ Mailer.deliver_high_job_alert(Queue.jobs.count)
46
+ end
47
+ end
48
+
49
+ monitor = HighJobMonitor.new(:job_count_threshold => 99)
50
+ monitor.check
51
+ ```
52
+
53
+ For a typical application, it could be desireable to define an
54
+ AppMonitor class with a default send_alert method, and have your
55
+ individual monitor classes inherit from that.
56
+
57
+ A monitor class can take options on initialization; this is recommended
58
+ for passing in thresholds, email addresses, or other dependencies.
59
+
60
+ Logging
61
+ -------
62
+
63
+ SimpleMonitor defaults its logger to a new Logger instance, or
64
+ Rails.logger if that is defined. If you want to override this,
65
+ do so in your class or via the `logger=` instance method.
66
+
67
+ When running a `check`, the logger will be warned or provided
68
+ with info whether an alert was needed. Note this is in addition
69
+ to sending out an alert.
70
+
71
+ #### Copyright
72
+
73
+ Copyright (c) (2012) Brendon Murphy. See license.txt for details.
74
+
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,3 @@
1
+ module SimpleMonitor
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,92 @@
1
+ require "simple_monitor/version"
2
+
3
+ module SimpleMonitor
4
+ attr_reader :options
5
+ attr_accessor :logger
6
+
7
+ LOG_METHODS = %w[info warn error debug].freeze
8
+
9
+ def initialize(options = {})
10
+ @options = options
11
+ end
12
+
13
+ # Runs the check and sends an alert if needed
14
+ #
15
+ # Returns false if the check failed, true if passed
16
+ def check
17
+ if needs_alert?
18
+ warn_alert
19
+ send_alert
20
+ false
21
+ else
22
+ info_passed
23
+ true
24
+ end
25
+ end
26
+
27
+ def warn_alert
28
+ warn(alert_log_message)
29
+ end
30
+
31
+ # Public: Message to log in case of an alert
32
+ #
33
+ # Override this in your monitors to inject data
34
+ #
35
+ # Returns: String
36
+ def alert_log_message
37
+ "check generated an alert"
38
+ end
39
+
40
+ def info_passed
41
+ info(passed_log_message)
42
+ end
43
+
44
+ # Public: Message to log in case of a check passing
45
+ #
46
+ # Override this in your monitors to inject data
47
+ #
48
+ # Returns: String
49
+ def passed_log_message
50
+ "check passed"
51
+ end
52
+
53
+ # Public: Conditional method to check if the alert should be sent
54
+ #
55
+ # This should be overridden in your individual monitor classes
56
+ #
57
+ # Returns a boolean
58
+ def needs_alert?
59
+ false
60
+ end
61
+
62
+ # Public: Send out an alert
63
+ #
64
+ # This should be overridden in your individual monitor classes,
65
+ # or base monitor class. This might be to send an SMS, email
66
+ # or IRC message
67
+ def send_alert
68
+ #no-op
69
+ end
70
+
71
+ # A memoized logger.
72
+ #
73
+ # Returns: a logger that responds to warn, info, debug, and error
74
+ def logger
75
+ @logger ||=
76
+ if defined?(Rails)
77
+ Rails.logger
78
+ else
79
+ require "logger"
80
+ Logger.new(STDOUT)
81
+ end
82
+ end
83
+
84
+ # Generated methods delegated to the logger. This is for convenience
85
+ # as well as for prefixing the monitor class name into the message
86
+ LOG_METHODS.each do |method|
87
+ define_method method do |message|
88
+ message = [self.class.name, message.to_s].join(" -- ")
89
+ logger.send(method, message)
90
+ end
91
+ end
92
+ end
data/license.txt ADDED
@@ -0,0 +1,23 @@
1
+ licensed under MIT License:
2
+
3
+ Copyright (c) 2012 Brendon Murphy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "simple_monitor/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "simple_monitor"
7
+ s.version = SimpleMonitor::VERSION
8
+ s.authors = ["Brendon Murphy"]
9
+ s.email = ["xternal1+github@gmail.com"]
10
+ s.licenses = ["MIT"]
11
+ s.homepage = ""
12
+ s.summary = %q{Send alerts based on simple monitored conditions in your app}
13
+ s.description = s.description
14
+
15
+ s.rubyforge_project = "simple_monitor"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency "rake"
23
+ s.add_development_dependency "rspec"
24
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ class TestMonitor
4
+ include SimpleMonitor
5
+
6
+ attr_reader :last_alert
7
+
8
+ def needs_alert?
9
+ options[:force_alert]
10
+ end
11
+
12
+ def send_alert
13
+ @last_alert = "Test Monitor Alert"
14
+ end
15
+ end
16
+
17
+ describe SimpleMonitor do
18
+ it "is initialized with optional options" do
19
+ monitor = TestMonitor.new
20
+ monitor = TestMonitor.new(:foo => :bar)
21
+ monitor.options[:foo].should == :bar
22
+ end
23
+ end
24
+
25
+ describe SimpleMonitor, "logger" do
26
+ subject { TestMonitor.new }
27
+
28
+ it "is defaulted to Logger.new(STDOUT)" do
29
+ subject.logger.should be_kind_of(Logger)
30
+ end
31
+
32
+ # Problem, what if its vendored and rails and run in a spec run
33
+ # that boots rails?
34
+ it "is defaulted to the Rails.logger if present" do
35
+ module Rails
36
+ def self.logger
37
+ :rails_logger
38
+ end
39
+ end
40
+
41
+ subject.logger.should == :rails_logger
42
+
43
+ Object.send(:remove_const, :Rails)
44
+ end
45
+
46
+ it "sends info, warn, error, and debug methods to it prefixed by the class name" do
47
+ stub_logger = stub('logger')
48
+ subject.logger = stub_logger
49
+ %w[info warn error debug].each do |log_method|
50
+ stub_logger.should_receive(log_method).with("TestMonitor -- #{log_method}")
51
+ subject.send(log_method, log_method)
52
+ end
53
+ end
54
+ end
55
+
56
+ describe SimpleMonitor, "running the check" do
57
+ subject { TestMonitor.new }
58
+ let(:logger) { stub('logger', :warn => nil, :info => nil) }
59
+ before { subject.logger = logger }
60
+
61
+ context "when an alert needs sending" do
62
+ before { subject.options[:force_alert] = true }
63
+
64
+ it "logs a warning that the check is in alert" do
65
+ logger.should_receive(:warn).with(/TestMonitor --.*alert/)
66
+ subject.check
67
+ end
68
+
69
+ it "sends an alert" do
70
+ subject.check
71
+ subject.last_alert.should == "Test Monitor Alert"
72
+ end
73
+
74
+ it "returns false" do
75
+ subject.check.should == false
76
+ end
77
+ end
78
+
79
+ context "when no alert needs sending" do
80
+ before { subject.options[:force_alert] = false }
81
+
82
+ it "logs info that the check passed" do
83
+ logger.should_receive(:info).with(/TestMonitor --.*passed/)
84
+ subject.check
85
+ end
86
+
87
+ it "doesn't send an alert" do
88
+ subject.check
89
+ subject.last_alert.should be_nil
90
+ end
91
+
92
+ it "returns true" do
93
+ subject.check.should == true
94
+ end
95
+ end
96
+ end
97
+
98
+ describe SimpleMonitor, "supports a class including SimpleMonitor" do
99
+ class ChildTestMonitor < TestMonitor
100
+ def needs_alert?
101
+ true
102
+ end
103
+
104
+ def send_alert
105
+ @last_alert = "CHILD HERE"
106
+ end
107
+ end
108
+
109
+ subject { ChildTestMonitor.new }
110
+ let(:logger) { stub('logger', :warn => nil, :info => nil) }
111
+ before { subject.logger = logger }
112
+
113
+ it "to be inherited" do
114
+ subject.check
115
+ subject.last_alert.should == "CHILD HERE"
116
+ end
117
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path("../../lib/simple_monitor", __FILE__)
2
+
3
+ RSpec.configure do |config|
4
+ config.mock_with :rspec
5
+ end
6
+
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_monitor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brendon Murphy
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-21 00:00:00.000000000 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ requirement: &2160677420 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *2160677420
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: &2160677000 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *2160677000
37
+ description: ''
38
+ email:
39
+ - xternal1+github@gmail.com
40
+ executables: []
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitignore
45
+ - Gemfile
46
+ - README.md
47
+ - Rakefile
48
+ - lib/simple_monitor.rb
49
+ - lib/simple_monitor/version.rb
50
+ - license.txt
51
+ - simple_monitor.gemspec
52
+ - spec/simple_monitor_spec.rb
53
+ - spec/spec_helper.rb
54
+ has_rdoc: true
55
+ homepage: ''
56
+ licenses:
57
+ - MIT
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project: simple_monitor
76
+ rubygems_version: 1.6.2
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Send alerts based on simple monitored conditions in your app
80
+ test_files:
81
+ - spec/simple_monitor_spec.rb
82
+ - spec/spec_helper.rb