Recently, the need arose for me to monitor a URL so that notifications could be sent out if the site was suddenly unavailable. Later on down the road this will need to evolve into a more proactive system rather than reactive but for now I am just focusing on site down notifications.
To start, I set some minimal requirements for myself.
When looking at the requirements I had to think about what kind of scripting environment would be best served for the task. I had several options available to me each with pros and cons.
It should be no surprise that I chose to use Groovy for this project. For me, Groovy just fits the bill better in terms of code verbosity and features available.
Building the script was a snap. One of the cool things about shell scripting is that you are able to specify the binary that you want to use to execute your script. So by adding a single line of declaration I was able to create a script that can run as if it was a native executable.
#!/usr/bin/env groovy
After that it's just a matter of writing the code that does the work! Lets start with the dependent libraries.
First I needed to make sure I had the HTTP-Builder library. Grape makes this a snap to get by letting me take advantage of the @Grab annotation. I just place the following towards the top of my script and like magic everything I need is available.
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.2')
I also need to make sure I have the Apache commons httpclient libraries. I use another @Grab to do this.
@Grab(group='commons-httpclient',module='commons-httpclient',version='3.1')
Grape is actually going out to the maven repositories and downloading the jars I requested and adding them to my classpath. Pretty slick eh?
I'll skip the imports (but you can check out the full source if those kinds of things excite you) and just straight to the guts of the script.
Next, among other things, I wanted to make sure that the script was configurable enough that I could add a list of phone numbers and be able to easily specify the url to monitor. To do that I created a nice little HashMap of key value pairs.
def options = [
server: "https://google.com/",
intervalSeconds: 600,
sid: "",
authToken: "",
fromPhone: "",
toPhone: "",
smsOnStart: false,
smsOnStartMessage: "Site monitoring script started at ${new Date().format('H:mm:ss')} on ${new Date().format('yyyy-MM-dd')}"
]
Ok, so options are great, but without some functionality they really mean nothing. Next I define two functions.
Here's the method that sends the SMS.
def sendSMS(def message, def opts){
if (opts.sid != "" && opts.authToken != "" && message != ""){
String twilioHost = "api.twilio.com"
String sid = opts.sid
String authToken = opts.authToken
def hc = new HostConfiguration()
hc.setHost(twilioHost, 443, "https")
def url = "/2010-04-01/Accounts/$sid/SMS/Messages"
def client = new HttpClient()
Credentials defaultcreds = new UsernamePasswordCredentials(sid, authToken)
client.getState().setCredentials(null, null, defaultcreds)
opts.toPhone.split(',')?.each { toPhn ->
PostMethod postMethod = new PostMethod(url)
postMethod.addParameter("IfMachine","Continue")
postMethod.addParameter("Method","POST")
postMethod.addParameter("From",opts.fromPhone)
postMethod.addParameter("To",toPhn)
postMethod.addParameter("Body",message)
client.executeMethod(hc, postMethod)
postMethod.releaseConnection()
}
}
}
And here's the method that checks the status of the url.
def doPing(def opts) {
if (opts.server != ""){
try {
new HTTPBuilder( opts.server ).get( path:'' ) { response ->
def msg = ""
if (response.statusLine.statusCode == 200){
msg = "${new Date()} :: UP!"
println msg
} else {
msg = "${new Date()} :: There might be a production problem! -> ${response.statusLine.statusCode}"
println msg
sendSMS(msg,opts)
}
}
} catch( e ){
println "${new Date()}"
e.printStackTrace()
sendSMS("There was an error when connecting to the production server, it might be down.",opts)
}
if (opts.intervalSeconds > 0){
def then = new Date()
then.seconds += opts.intervalSeconds
println "Checking again at ${then}"
while (new Date() <= then){
// do nothing
}
doPing( opts )
}
}
}
Since these are both method declarations and they won't just call themselves we need to do one last thing, call the doPing method.
if (options.smsOnStart){
sendSMS(options.smsOnStartMessage,options)
}
doPing( options )
That's the whole script! If you are interested in looking at or using the script Github's going to be the best place to do that. With comments and code the whole thing come to a mere 106 lines of code! Not bad for something that monitors a URL and then sends an SMS when there is a problem.
I know I glossed over how the methods actually work but I felt they were pretty self explanatory. Feel free to ask questions in the comments if you would like further explanation.
Thanks for reading!
KaiNexus, the company where I am the Principal Architect, has just released our latest "Explainer" video. The new video includes 3 use cases and a bunch of screen grabs from the actual software. This video is quite exciting as I think it really shows what kinds of problems our software solves. Check it out!
A few weeks ago I mentioned that I was building a Grails plugin that aimed to wrap the SmugMug API. As of today, I am about 80% done with the coding and will be giving it a through test phase and creating docs soon. Once done, it will be available through the normal Grails plugin channels and be completely open source.
Sometimes it is so easy to ignore the things around us that we see on a daily basis. The subject of this photo was no exception. This is a walkway at the office complex where I work 5 days a week and I never once thought to bring my camera and shoot it. A few days ago I decided to change that. Here are the results.
I've spent the last five days pretty much living at UT Southwestern Medical Center. My step daughter has been unable to eat more than a few bites of food without throwing up for about three months. After many tests and even a surgery to remove her gall bladder, doctors finally admitted her to the hospital for observation and even more tests. As a result, my wife and I have spent nearly the whole time living I the hospital room with her. I ask, for those comfortable with it, for prayers for her health and that the doctors would be able find the problem and come up with a solution.
There is a really interesting hallway at UT Southwestern Medical Center that just screamed "spooky" at me. I wanted to grab my camera and shoot some of the interesting angles and lines but I was a bit worried about offending patients and staff by walking around the hotel with camera and tripod in hand. As an alternative, I used my iPhone and captured the following video. I processed it a little bit in iMovie.
I saw a post on Google+ where someone posted a collage with the brackets used to make up one of their HDRs. I thought this was pretty cool and decided to do one of my own using Diptic for Mac. What do ya' think?

This is the finished product of the image above. It was taken in downtown Fort Worth on my last photowalk research day. I was fascinated by the combination of glass, metal and concrete and the lines they formed. Normally, this is filled with flowing water but I got there just shortly after they turned everything off. I really dig the way everything looks even without the water.
Here is another shot I snapped while exploring Fort Worth and gathering info for my fall photowalk. This is on the side of Bass Performance Hall. The building and the angel are carved out of Texas limestone, which was quarried near Austin. You can read more about these amazing sculptures on Google Books.
A while back I found a really interesting utility for visualizing the activity of a Git repository. Here's a cool little video of the repo for this site as visualized by Gource. Enjoy
I have been experimenting with a number of different photography techniques, one of those is the invisible black backdrop. Using this technique, I decided to follow my chihuahua around and generally annoy him with my flash. The result was a yawn captured at just the right moment. Isn't he just so vicious?
To all the father's out there, including my own, happy Father's Day! Kids, if you know what's good for you you'll wait on dad hand and foot! No, really.
I grabbed this shot while doing research for a future photowalk around Fort Worth. It was a little bit of a surprise for me since I found this on a street that was more of an alley. It is located behind Risky's BBQ at Sundance Square.
I started messing around with some techniques to add a feeling of grunge to a couple of the portraits in my library (nothing worth sharing yet) and found that I can't get enough. I found a pretty good, if not fast, tutorial (below) on the basics of applying grunge to a photo. One thing to note, I don't have one of the plugins this video uses but I was able to get the same effect by creating a new layer and desaurating it completely and messing around with the levels, curves and exposure. It's not as easy as the plugin filters but it costs way less.
I stopped on my way home from the office about a week ago and took a few shots of a park that I pass everyday. It is amazing how many power lines and other modern things there are in almost every frame I want to capture. This was one of those rare shots where I was able to avoid the power lines and hide the pesky water towers and street lights. All-in-all, I like the final result.
Over the next few weekends I'll be in or around downtown Fort Worth doing research for a photowalk. If you would like to join me be sure to follow me on Twitter or circle me on Google+ to get the details of where I will be and when I will be there.
The first exploration will be June 15th 16th, 2012 at 5pm and I will be starting at the little park between Bluff St and Belknap (across from the court house) and working my way towards Sunset Square. If you are planning to come make sure to bring water and hydrate ahead of time, nobody needs to be getting dehydrated in the Texas heat. Comment below with questions or to let me know you will be joining me (that way I don't just take off and leave you behind). Also, street parking is generally free on the weekends after 6 or 7 but space is limited so you may want to be there early to find a parking spot. Also, if anyone joins me, we can head over to the Flying Saucer afterwards for drinks and german food.
UPDATE: I originally posted the wrong date. The correct date should have been June 16th (Saturday)
While the Fort Worth Water Gardens were awesome for me to visit not all people share my enthusiasm. Perhaps the next date will be better. Smile!