Fork me on GitHub

Thursday, August 7, 2008

Ruby: A Simple Web Site Monitoring Using Schnell

Update - A small correction in the notify method. Please refer the code in the blog post for the change.

I have been working on schnell for quiet sometime and am moving towards another release. But the beginning of schnell is not as an automation testing tool. I started writing schnell as a wrapper to WWW::Mechanize to help my team to do the automated monitoring of websites. We had the requirement of monitoring a set of production websites to see their status every few minutes. But the condition was not to just see if the websites are accessible but to run a quick smoke test on them and see if they work.

A typical scenario would be to check if the website is available, log into it and see if it works. Here is the sample code of the site monitor we used to have. This has taken a mature version now which I am planning to release as open source.

You need to have mechanize, rubyful_soup, rufus_scheduler, log4r for this code to run. You can also do this with the latest jruby version of schell with a few changes in the notify method (Exceptions are handled differently in jruby version). The advantage of mechanize version is it can be run on native ruby. If you are running this code on latest version use jruby instead of ruby.

THIS IS ONLY A SAMPLE CODE.

require "../hui"
require "log4r"
require "rufus/scheduler"
include Log4r

class TestSite1
URL = "http://localhost:9999"
def self.monitor
browser = Browser.new
browser.goto URL
browser.link(:text, "buttons1.html").click
browser.button(:value,"Click Me").click
raise "Not able to get PASS" unless browser.text.include?("PASS")
end
end

class TestSite2
URL = "http://localhost:8888"
def self.monitor
browser = Browser.new
browser.goto URL
browser.link(:text, "links1.html").click
browser.link(:text,"test1").click
raise "Not able to get Links2-Pass" unless browser.text.include?("Links2-Pass")
end
end

$sitelog = Logger.new 'sitelog'
$sitelog.outputters = Outputter.stdout

scheduler = Rufus::Scheduler.new

trap("INT") do
$sitelog.info "stopping SiteMon..."
scheduler.stop
end

scheduler.start
monitered_websites = [TestSite1,TestSite2]

def notify(website,message)
if message.include? "Unable to navigate"
$sitelog.error "#{website.const_get('URL')} #{message}"
else
$sitelog.warn "#{website.const_get('URL')} #{message}"
end
end

$sitelog.info "starting SiteMon..."

scheduler.schedule_every "60s", :first_in => "5s" do
monitered_websites.each do |site|
begin
site.monitor
rescue => ex
notify site, ex.message
end
end
end

scheduler.join


There are a few things I am exploring now. Parallelism in monitoring, notification through Microsoft Office Communicator (We use mails as of now.) and a better modular structure.

I have published this code as well as the mechanize version of schnell (Used to call it hui) in GPL license as a download here. It is a very basic version of schnell and not all conditions and exceptions are covered. If you want to have better functionality, you can use the latest version with schnell in jruby. Please let me know if you have any suggestions and queries.

Download

3 comments:

Mark said...

Many thanks for sharing this code. It was just what I was looking for.

Any chance you can put the code up at github, or similar, when it is ready?

Sai said...

Sure Mark. I will do it in this weekend. schnell jruby version is already available in the Google Code (http://code.google.com/p/schnell-jruby). You can explore the code there as well.

rusty zarse said...

Sai,

Thanks so much. I spec'd out a monitoring service this morning following yet another failure notification from our third party web host monitor. I need much more than an email that a url was down 5 minutes after we discover it ourselves and its too late to figure out what happened to hang it.

Thanks for sharing this. I'll be sure to contribute back anything that I can if I happen to extend the service.

cheers