Skip to content
This repository has been archived by the owner on Apr 12, 2022. It is now read-only.

Commit

Permalink
Made everything a bit less haphazard, made the timeout work, and cove…
Browse files Browse the repository at this point in the history
…red more errors (Socket errors on a non-existent hostname).
  • Loading branch information
tofumatt committed Oct 18, 2009
1 parent be1e027 commit f8f2f93
Showing 1 changed file with 120 additions and 83 deletions.
203 changes: 120 additions & 83 deletions findtheproblems.rb
Expand Up @@ -9,101 +9,138 @@
This software uses my modified version of August Lilleaas's Prowl Library, also MIT-licensed
=end

# Check the sites if this file is being directly executed
if __FILE__ == $0
# Put the URLs of sites you'd like to check in here.
Sites_To_Check = [
'http://lonelyvegan.com/'
]

# Prowl settings (See lib/prowl/README and http://prowl.weks.net/api.php for more info)
Prowl_API_Keys = [
# Put your API key here. If you want a few people to get notifications
# that's cool: you can put up to five (5) API keys in here
'REPLACE_ME_WITH_YOUR_PROWL_API_KEY(s)'
]
Priority = 2 # Priority can be -2..2
Provider_Key = '' # OPTIONAL: You can fill this in if you have a whitelisted provider key

# How many redirects should be followed before we give up?
Max_Redirects = 3

# You can stop editing now.
end

$LOAD_PATH << File.expand_path("#{File.dirname(__FILE__)}/lib/prowl")

require 'net/https'
require 'prowl'
require 'timeout'
require 'uri'

# Put the URLs of sites you'd like to check in here.
Sites_To_Check = [
'http://lonelyvegan.com',
]

# Prowl settings (See lib/prowl/README and http://prowl.weks.net/api.php for more info)
Prowl_API_Keys = [
# Put your API key here. If you want a few people to get notifications
# that's cool: you can put up to five (5) API keys in here
'REPLACE_ME_WITH_YOUR_PROWL_API_KEY(s)'
]
Priority = 2 # Priority can be -2..2
Provider_Key = '' # OPTIONAL: You can fill this in if you have a whitelisted provider key

# How many redirects should be followed before we give up?
Max_Redirects = 3

# You can stop editing now.

# Some silly constants
App_Name = 'FindTheProblems'
Error_SiteIsDown = 'Site is down'
Error_Timeout = 'Timed out'
Error_TooManyRedirects = 'Too many redirects'
User_Agent = App_Name + ': A Simple Ruby -> Prowl Site Monitor (http://github.com/tofumatt/FindTheProblems)'
Timeout_In_Seconds = 25

# Setup Prowl
@prowl = Prowl.new(
:application => App_Name,
:providerkey => Provider_Key,
:priority => Priority,
:apikey => Prowl_API_Keys
)

# Take a URL and perform a GET request on it. If we return a 2xx HTTP Status Code
# then we consider it a win; otherwise, return an error.
def check_site(url, redirects=0, original_url=nil)
uri = URI.parse(url)
class Site_To_Check

# Some silly constants
App_Name = 'FindTheProblems'
Error_BadHostname = "Couldn't find hostname"
Error_BadURL = "Bad URL"
Error_SiteIsDown = 'Site is down'
Error_Timeout = 'Timed out'
Error_TooManyRedirects = 'Too many redirects'
User_Agent = App_Name + ': A Simple Ruby -> Prowl Site Monitor (http://github.com/tofumatt/FindTheProblems)'
Timeout_In_Seconds = 25

# Build up our little HTTP request
http = Net::HTTP.new(uri.host, uri.port)
http.read_timeout = Timeout_In_Seconds
http.use_ssl = (url.index('https://') == 0) ? true : false;
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
# Setup Prowl
Prowl = Prowl.new(
:application => App_Name,
:providerkey => Provider_Key,
:priority => Priority,
:apikey => Prowl_API_Keys
)

# Try to GET the URL. If we can't, let's say the site is down
begin
response = http.get(uri.request_uri, {'User-Agent' => User_Agent})
rescue Errno::ETIMEDOUT
return error(url, Error_Timeout)
# Class constructor (load in either custom or default sites)
def initialize(url)
# Load this instance's URL
@url = url
@original_url = url # Preserve the original URL for any error message

# We start with 0 redirects...
@redirects = 0
end

# Check the response
case response
# 2xx status code: It worked!
when Net::HTTPSuccess then
return
# It's a redirect; increment our redirect counter
when Net::HTTPRedirection then
redirects+=1

# We allow redirects, but if there are too many redirects, return an error
return error(original_url, Error_TooManyRedirects) if redirects > Max_Redirects

# Otherwise, follow the redirect
check_site(response['location'], redirects, url)
# The site returned a non-2xx/redirect status code -- it's down :-(
# Perform a GET request on this instance's @url. If we return a 2xx HTTP Status
# Code then we consider it a win; otherwise, return an error.
def check()
uri = URI.parse(@url)

# Build up our little HTTP request
http = Net::HTTP.new(uri.host, uri.port)
http.read_timeout = Timeout_In_Seconds
http.use_ssl = (@url.index('https://') == 0) ? true : false;
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

# Try to GET the URL. If we can't, let's say the site is down
begin
response = Timeout::timeout(Timeout_In_Seconds) {
http.get(uri.request_uri, {'User-Agent' => User_Agent})
}
rescue Errno::ETIMEDOUT
return self.error(Error_Timeout)
rescue Timeout::Error
return self.error(Error_Timeout)
rescue SocketError
return self.error(Error_BadHostname)
rescue NoMethodError
return self.error(Error_BadURL)
end

# Check the response
case response
# 2xx status code: It worked!
when Net::HTTPSuccess then
return
# It's a redirect; increment our redirect counter
when Net::HTTPRedirection then
@redirects+=1

# We allow redirects, but if there are too many redirects, return an error
return self.error(Error_TooManyRedirects) if @redirects > Max_Redirects

# Otherwise, follow the redirect
@url = response['location']
self.check
# The site returned a non-2xx/redirect status code -- it's down :-(
else
return self.error(Error_SiteIsDown)
end
end

# Send out an error notification via Prowl
def error(error)
# Make sure the notification was successfully sent
result = Prowl.add(:event => error, :description => @original_url)
if result == 200
error
else
return error(url, Error_SiteIsDown)
result
end
end

end

# Send out an error notification via Prowl
def error(url, error)
# Other than ruby-prowl's own error handling, there isn't much in the way of
# error handling here yet
@prowl.add(:event => error, :description => url)
end

# Fun with threads; HTTP lib is thread-safe, so we'll make checking
# all these sites a bit more concurrent...
threads = []
for site in Sites_To_Check
threads << Thread.new(site) { |s|
check_site(s)
}
end

# Stitch 'em back together...
threads.each { | thread | thread.join }
# Check the sites if this file is being directly executed
if __FILE__ == $0

# Fun with threads; we'll make checking
# all these sites a bit more concurrent...
threads = []
for url in Sites_To_Check
threads << Thread.new(url) { |i|
thread_site = Site_To_Check.new(url)
thread_site.check
}
end

# Stitch 'em back together...
threads.each { | thread | thread.join }
end

0 comments on commit f8f2f93

Please sign in to comment.