web-monitor 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +42 -0
- data/Rakefile +2 -0
- data/bin/web-monitor +7 -0
- data/config.yml +5 -0
- data/lib/web-monitor.rb +8 -0
- data/lib/web-monitor/config.rb +35 -0
- data/lib/web-monitor/logger.rb +29 -0
- data/lib/web-monitor/mailer.rb +12 -0
- data/lib/web-monitor/monitor.rb +32 -0
- data/lib/web-monitor/requester.rb +37 -0
- data/lib/web-monitor/response_validator.rb +29 -0
- data/lib/web-monitor/version.rb +3 -0
- data/test/config_test.rb +23 -0
- data/test/logger_test.rb +18 -0
- data/test/requester_test.rb +36 -0
- data/test/response_validator_test.rb +41 -0
- data/test/test-config.yml +5 -0
- data/test/test-minimal-config.yml +1 -0
- data/urls.csv +4 -0
- data/web-monitor.gemspec +17 -0
- metadata +75 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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.
|
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
data/bin/web-monitor
ADDED
data/config.yml
ADDED
data/lib/web-monitor.rb
ADDED
@@ -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,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
|
data/test/config_test.rb
ADDED
@@ -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
|
data/test/logger_test.rb
ADDED
@@ -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 @@
|
|
1
|
+
alert_mail: test-min@domain-test.com
|
data/urls.csv
ADDED
data/web-monitor.gemspec
ADDED
@@ -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
|