|
#!/usr/bin/env ruby |
|
|
|
require 'open-uri' |
|
require 'optparse' |
|
require 'resolv' |
|
|
|
# so we can handle https => http, e.g. bbc.co.uk |
|
module OpenURI |
|
class <<self |
|
alias_method :open_uri_original, :open_uri |
|
alias_method :redirectable_cautious?, :redirectable? |
|
|
|
def redirectable_safe?(uri1, uri2) |
|
uri1.scheme.downcase == uri2.scheme.downcase || |
|
(uri1.scheme.downcase == "http" && uri2.scheme.downcase == "https") |
|
end |
|
|
|
def redirectable_all?(uri1, uri2) |
|
redirectable_safe?(uri1, uri2) || |
|
(uri1.scheme.downcase == "https" && uri2.scheme.downcase == "http") |
|
end |
|
end |
|
|
|
def self.open_uri(name, *rest, &block) |
|
class << self |
|
remove_method :redirectable? |
|
alias_method :redirectable?, :redirectable_all? |
|
end |
|
|
|
self.open_uri_original name, *rest, &block |
|
end |
|
end |
|
|
|
# for stddev, mean |
|
module Enumerable |
|
def sum |
|
self.inject(0) { |a, i| a + i } |
|
end |
|
|
|
def mean |
|
(self.sum/self.length.to_f) |
|
end |
|
|
|
def sample_variance |
|
m = self.mean |
|
sum = self.inject(0){|accum, i| accum + (i-m)**2 } |
|
sum/(self.length - 1).to_f |
|
end |
|
|
|
def stddev |
|
return Math.sqrt(self.sample_variance) |
|
end |
|
end |
|
|
|
options = {} |
|
optparse = OptionParser.new do |opts| |
|
opts.banner = "Usage: #{File.basename($0)} [options]" |
|
options[:uri] = "http://google.com/" |
|
options[:count] = 5 |
|
opts.on("-u", "--uri URI", String, "URI to test (default: google.com)") do |arg| |
|
options[:uri] = arg |
|
end |
|
opts.on("-c", "--count COUNT", Integer, "Number of tests (default: 5)") do |arg| |
|
options[:count] = arg |
|
end |
|
opts.on_tail("-h", "--help", "Show this message") do |
|
puts opts |
|
exit |
|
end |
|
end |
|
optparse.parse! |
|
if options[:uri].nil? |
|
puts optparse |
|
exit |
|
end |
|
|
|
if options[:uri][0..3] != 'http' |
|
warn "Found #{options[:uri]}, assuming you mean http://#{options[:uri]}/" |
|
options[:uri] = "http://#{options[:uri]}" |
|
end |
|
|
|
begin |
|
results = [] |
|
uri = URI.parse(options[:uri]) |
|
puts "HTTP-PING #{uri.host}:#{uri.port} (#{Resolv.getaddress(uri.host)}): GET request" |
|
ok = 0 |
|
error = 0 |
|
|
|
options[:count].times do |c| |
|
t1 = Time.now.to_f |
|
begin |
|
response = open(uri) |
|
t2 = Time.now.to_f |
|
delta = (t2 - t1) * 1000 |
|
results.push(delta) |
|
puts "#{response.size/1000}K bytes from #{response.base_uri.host}:#{response.base_uri.port}: http_seq=#{c} status=#{response.status.first} time=#{delta.round(2)} ms" |
|
ok += 1 |
|
rescue OpenURI::HTTPError => e |
|
response = e.message.split(" ").first |
|
t2 = Time.now.to_f |
|
delta = (t2 - t1) * 1000 |
|
results.push(delta) |
|
puts "0K bytes from #{uri.host}: http_seq=#{c} status=#{response} time=#{delta.round(2)} ms" |
|
error += 1 |
|
end |
|
end |
|
|
|
puts |
|
puts "--- #{uri.host} http-ping statistics ---" |
|
puts "#{options[:count]} packets transmitted, #{ok} ok, #{error} error" |
|
puts "min/avg/max/stddev = #{results.min.round(2)}/#{results.mean.round(2)}/#{results.max.round(2)}/#{results.stddev.round(2)} ms" |
|
rescue Resolv::ResolvError |
|
warn "DNS error: #{options[:uri]}" |
|
exit! |
|
rescue Interrupt => e |
|
exit! |
|
rescue => e |
|
puts e.message |
|
exit! |
|
end |