web-monitor 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in web-monitor.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Piotr Macuk
2
+
3
+ MIT License
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.
@@ -0,0 +1,42 @@
1
+ # WebMonitor
2
+
3
+ Website monitoring tool by response time and status
4
+
5
+ ## Installation
6
+
7
+ Install
8
+
9
+ gem install web-monitor
10
+
11
+ Create config.yml file with following options
12
+
13
+ $ cat config.yml
14
+ response_time_limit: 3.0 # in seconds
15
+ alert_mail: login@somedomain.com # errors will be sent there
16
+ urls_file: urls.csv # file with site list to monitor
17
+ log_file: web-monitor.log # file with logs
18
+ delay: 1.0 # delay between requests (in seconds)
19
+
20
+ Create urls.csv file to monitor
21
+
22
+ $ cat urls.csv
23
+ google,https://www.google.pl
24
+ bbc,http://www.bbc.co.uk
25
+ err1,http://aaa.bbb.ccc.ddd.com
26
+ err2,https://wp.pl
27
+
28
+ Execute
29
+
30
+ $ web-monitor config.yml
31
+
32
+ Read logfile
33
+
34
+ $ cat web-monitor.log
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
4
+ require 'web-monitor'
5
+
6
+ monitor = WebMonitor::Monitor.new(ARGV.first || 'config.yml')
7
+ monitor.process
@@ -0,0 +1,5 @@
1
+ response_time_limit: 3 # in seconds
2
+ alert_mail: alert@domain.com # errors will be sent there
3
+ urls_file: urls.csv # sites to monitor
4
+ log_file: web-monitor.log # file with logs
5
+ delay: 1 # delay between requests
@@ -0,0 +1,8 @@
1
+ require 'web-monitor/version'
2
+
3
+ require 'web-monitor/config'
4
+ require 'web-monitor/logger'
5
+ require 'web-monitor/mailer'
6
+ require 'web-monitor/monitor'
7
+ require 'web-monitor/requester'
8
+ require 'web-monitor/response_validator'
@@ -0,0 +1,35 @@
1
+ module WebMonitor
2
+ class Config
3
+ require 'yaml'
4
+ require 'ostruct'
5
+
6
+ DEFAULTS = {
7
+ response_time_limit: 3.0,
8
+ alert_mail: nil,
9
+ urls_file: 'urls.csv',
10
+ log_file: 'web-monitor.log',
11
+ delay: 1.0,
12
+ }
13
+
14
+ def initialize(config_file)
15
+ struct = YAML::load(File.open(config_file))
16
+ @config = OpenStruct.new(struct)
17
+ end
18
+
19
+ def method_missing(method, *args, &block)
20
+ out = @config.send(method)
21
+ if out.nil?
22
+ return DEFAULTS[method]
23
+ else
24
+ case method
25
+ when :response_time_limit
26
+ out.to_f
27
+ when :delay
28
+ out.to_f
29
+ else
30
+ out
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ module WebMonitor
2
+ class Logger
3
+ require 'logger'
4
+
5
+ def initialize(config)
6
+ @log = ::Logger.new(config.log_file)
7
+ @log.datetime_format = "%Y-%m-%d %H:%M:%S"
8
+ @log.formatter = proc do |severity, datetime, progname, msg|
9
+ "#{datetime} #{severity} #{msg}\n"
10
+ end
11
+ end
12
+
13
+ def info(msg)
14
+ @log.info(msg)
15
+ end
16
+
17
+ def error(msg)
18
+ @log.error(msg)
19
+ end
20
+
21
+ def fatal(msg)
22
+ @log.fatal(msg)
23
+ end
24
+
25
+ def close
26
+ @log.close
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ module WebMonitor
2
+ class Mailer
3
+ def initialize(config)
4
+ @email = config.alert_mail
5
+ end
6
+
7
+ def send(msg)
8
+ return unless @email
9
+ system %(echo '' | mail -s "#{msg}" #{@email})
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,32 @@
1
+ module WebMonitor
2
+ class Monitor
3
+ require 'csv'
4
+
5
+ def initialize(config_file)
6
+ @config = Config.new(config_file)
7
+ @logger = Logger.new(@config)
8
+ @mailer = Mailer.new(@config)
9
+ @requester = Requester.new(@config)
10
+ end
11
+
12
+ def process
13
+ CSV.foreach(@config.urls_file) do |name, url|
14
+ begin
15
+ @requester.check(url)
16
+ rescue Exception => e
17
+ @logger.fatal("#{name} (#{url}): #{e.class} #{e.message}")
18
+ @mailer.send("#{name} #{e.class}")
19
+ next
20
+ end
21
+ v = ResponseValidator.new(@requester.time, @requester.status, @config)
22
+ if v.valid?
23
+ @logger.info("#{name} (#{url}): %.1fs" % @requester.time)
24
+ else
25
+ @logger.error("#{name} (#{url}): #{v.error_msg}")
26
+ @mailer.send("#{name} #{v.error_msg}")
27
+ end
28
+ sleep @config.delay
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ module WebMonitor
2
+ # Request URL and return time and status
3
+ class Requester
4
+ require 'net/http'
5
+ require 'benchmark'
6
+ require 'timeout'
7
+
8
+ attr_reader :time, :status
9
+ attr_writer :benchmark
10
+
11
+ def initialize(config)
12
+ @limit = config.response_time_limit
13
+ @timeout = @limit + 1.0
14
+ @benchmark = Benchmark
15
+ end
16
+
17
+ def check(url)
18
+ Timeout::timeout(@timeout) do
19
+ time = @benchmark.measure { get(url.strip) }
20
+ @time = time.real.to_f
21
+ end
22
+ rescue Timeout::Error
23
+ @time = @timeout
24
+ @status = 0
25
+ end
26
+
27
+ protected
28
+ def get(url)
29
+ uri = URI.parse(url)
30
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
31
+ request = Net::HTTP::Get.new uri.request_uri
32
+ response = http.request request
33
+ @status = response.code.to_i
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module WebMonitor
2
+ # Validate response time and status
3
+ class ResponseValidator
4
+ attr_accessor :time, :status
5
+
6
+ def initialize(time, status, config)
7
+ @time, @status = time.to_f, status.to_i
8
+ @limit = config.response_time_limit
9
+ end
10
+
11
+ def valid?
12
+ validate_status and validate_time
13
+ end
14
+
15
+ def error_msg
16
+ return "Status=#{@status}" unless validate_status
17
+ return "Time=%.1fs" % @time unless validate_time
18
+ end
19
+
20
+ protected
21
+ def validate_time
22
+ @time <= @limit
23
+ end
24
+
25
+ def validate_status
26
+ @status == 200
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module WebMonitor
2
+ VERSION = "0.9.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ require 'minitest/autorun'
2
+ require 'web-monitor/config'
3
+ require 'ostruct'
4
+
5
+ class ConfigTest < MiniTest::Unit::TestCase
6
+ def test_file_settings
7
+ config = WebMonitor::Config.new('test/test-config.yml')
8
+ assert_equal 2.5, config.response_time_limit
9
+ assert_equal 'test@domain-test.com', config.alert_mail
10
+ assert_equal 'url-list.csv', config.urls_file
11
+ assert_equal 'monitor.log', config.log_file
12
+ assert_equal 1.5, config.delay
13
+ end
14
+
15
+ def test_default_values
16
+ config = WebMonitor::Config.new('test/test-minimal-config.yml')
17
+ assert_equal 3.0, config.response_time_limit
18
+ assert_equal 'test-min@domain-test.com', config.alert_mail
19
+ assert_equal 'urls.csv', config.urls_file
20
+ assert_equal 'web-monitor.log', config.log_file
21
+ assert_equal 1.0, config.delay
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ require 'minitest/autorun'
2
+ require 'web-monitor/logger'
3
+ require 'ostruct'
4
+
5
+ class LoggerTest < MiniTest::Unit::TestCase
6
+ def setup
7
+ @config = OpenStruct.new(log_file: '/tmp/test.log')
8
+ @l = WebMonitor::Logger.new(@config)
9
+ end
10
+
11
+ def test_info
12
+ @l.info('test')
13
+ @l.close
14
+ content = File.read(@config.log_file)
15
+ assert_match /INFO/, content
16
+ assert_match /test/, content
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/mock'
3
+ require 'web-monitor/requester'
4
+ require 'ostruct'
5
+
6
+ class RequesterTest < MiniTest::Unit::TestCase
7
+ def setup
8
+ @config = OpenStruct.new(response_time_limit: 3)
9
+ @r = WebMonitor::Requester.new(@config)
10
+ end
11
+
12
+ def test_check_200
13
+ @r.check 'https://www.google.pl'
14
+ assert @r.time < 1.0
15
+ assert_equal 200, @r.status
16
+ end
17
+
18
+ def test_check_404
19
+ @r.check 'http://www.google.pl/abc'
20
+ assert @r.time < 1.0
21
+ assert_equal 404, @r.status
22
+ end
23
+
24
+ class MyBenchmark
25
+ def measure; sleep 5; end
26
+ end
27
+
28
+ def test_timeout
29
+ config = OpenStruct.new(response_time_limit: 0.5)
30
+ r = WebMonitor::Requester.new(config)
31
+ r.benchmark = MyBenchmark.new
32
+ r.check 'https://www.google.pl'
33
+ assert_equal 1.5, r.time
34
+ assert_equal 0, r.status
35
+ end
36
+ end
@@ -0,0 +1,41 @@
1
+ require 'minitest/autorun'
2
+ require 'web-monitor/response_validator'
3
+ require 'ostruct'
4
+
5
+ class ResponseValidatorTest < MiniTest::Unit::TestCase
6
+ def setup
7
+ @config = OpenStruct.new(response_time_limit: 3)
8
+ @v = WebMonitor::ResponseValidator.new(1, 200, @config)
9
+ end
10
+
11
+ def test_when_valid
12
+ assert @v.valid?
13
+ end
14
+
15
+ def test_when_timeout
16
+ @v.time = 10
17
+ assert_equal false, @v.valid?
18
+ end
19
+
20
+ def test_when_wrong_status
21
+ @v.status = 404
22
+ assert_equal false, @v.valid?
23
+ end
24
+
25
+ def test_time_error_msg
26
+ @v.time = 10.18315
27
+ assert_match /Time=10.2s/, @v.error_msg
28
+ end
29
+
30
+ def test_status_error_msg
31
+ @v.status = 500
32
+ assert_match /Status=500/, @v.error_msg
33
+ end
34
+
35
+ def test_time_as_float
36
+ @v.time = 0.2
37
+ assert @v.valid?
38
+ @v.time = 3.2
39
+ assert_equal false, @v.valid?
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ response_time_limit: 2.5
2
+ alert_mail: test@domain-test.com
3
+ urls_file: url-list.csv
4
+ log_file: monitor.log
5
+ delay: 1.5
@@ -0,0 +1 @@
1
+ alert_mail: test-min@domain-test.com
@@ -0,0 +1,4 @@
1
+ google,https://www.google.pl
2
+ bbc,http://www.bbc.co.uk
3
+ err1,http://aaa.bbb.ccc.ddd.com
4
+ err2,https://wp.pl
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/web-monitor/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Piotr Macuk"]
6
+ gem.email = ["piotr@macuk.pl"]
7
+ gem.description = %q{Website monitoring tool by response time and status}
8
+ gem.summary = %q{Website monitoring tool}
9
+ gem.homepage = "https://github.com/macuk/web-monitor"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "web-monitor"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = WebMonitor::VERSION
17
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: web-monitor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Piotr Macuk
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-12 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Website monitoring tool by response time and status
15
+ email:
16
+ - piotr@macuk.pl
17
+ executables:
18
+ - web-monitor
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - bin/web-monitor
28
+ - config.yml
29
+ - lib/web-monitor.rb
30
+ - lib/web-monitor/config.rb
31
+ - lib/web-monitor/logger.rb
32
+ - lib/web-monitor/mailer.rb
33
+ - lib/web-monitor/monitor.rb
34
+ - lib/web-monitor/requester.rb
35
+ - lib/web-monitor/response_validator.rb
36
+ - lib/web-monitor/version.rb
37
+ - test/config_test.rb
38
+ - test/logger_test.rb
39
+ - test/requester_test.rb
40
+ - test/response_validator_test.rb
41
+ - test/test-config.yml
42
+ - test/test-minimal-config.yml
43
+ - urls.csv
44
+ - web-monitor.gemspec
45
+ homepage: https://github.com/macuk/web-monitor
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Website monitoring tool
69
+ test_files:
70
+ - test/config_test.rb
71
+ - test/logger_test.rb
72
+ - test/requester_test.rb
73
+ - test/response_validator_test.rb
74
+ - test/test-config.yml
75
+ - test/test-minimal-config.yml