require 'net/http'
require 'uri'
class UrlMonitor < ScoutAgent::Plugin
include Net
TEST_USAGE = "#{File.basename($0)} url URL last_run LAST_RUN"
TIMEOUT_LENGTH = 50 # seconds
def build_report
url = option("url").to_s.strip
if url.empty?
return error("A url wasn't provided.")
end
unless url =~ %r{\Ahttps?://}
url = "http://#{url}"
end
response = http_response(url)
report(:status => response.class.to_s)
is_up = valid_http_response?(response) ? 1 : 0
report(:up => is_up)
if is_up != memory(:was_up)
if is_up == 0
alert( "The URL [#{url}] is not responding",
"URL: #{url}\n\nStatus: #{response}" )
remember(:down_at => Time.now)
else
if memory(:was_up) && memory(:down_at)
alert( "The URL [#{url}] is responding again",
"URL: #{url}\n\nStatus: #{response}. " +
"Was unresponsive for #{(Time.now - memory(:down_at)).to_i} seconds" )
else
alert( "The URL [#{url}] is responding",
"URL: #{url}\n\nStatus: #{response}. " )
end
memory.delete(:down_at)
end
end
remember(:was_up => is_up)
rescue Exception => e
error( "Error monitoring url [#{url}]",
"#{e.message}
#{e.backtrace.join('
')}" )
end
def valid_http_response?(result)
[HTTPOK,HTTPFound].include?(result.class)
end
# returns the http response (string) from a url
def http_response(url)
uri = URI.parse(url)
response = nil
retry_url_trailing_slash = true
retry_url_execution_expired = true
begin
Net::HTTP.start(uri.host,uri.port) {|http|
http.open_timeout = TIMEOUT_LENGTH
req = Net::HTTP::Get.new((uri.path != '' ? uri.path : '/' ) + (uri.query ? ('?' + uri.query) : ''))
if uri.user && uri.password
req.basic_auth uri.user, uri.password
end
response = http.request(req)
}
rescue Exception => e
# forgot the trailing slash...add and retry
if e.message == "HTTP request path is empty" and retry_url_trailing_slash
url += '/'
uri = URI.parse(url)
h = Net::HTTP.new(uri.host)
retry_url_trailing_slash = false
retry
elsif e.message =~ /execution expired/ and retry_url_execution_expired
retry_url_execution_expired = false
retry
else
response = e.to_s
end
end
return response
end
end