From problem to Python


Developing a website monitoring tool

By Joseph Carboni

This is an example of using an acute business problem as an opportunity to use Python for a helpful solution – a website status monitor. An exercise in looping, making web requests, and running a python utility from the command line.

(Given the nature of the problem, a basic network ping wasn’t going to be helpful, as the server was technically reachable but returning a 503. So, I turned to the requests library.)

A key web tool stopped working

Perusing customer service emails, I notice a handful of responses from the team about a commonly used tool being down – a platform for building, generating, and tracking job quotes for Friedrich Air Conditioning products – something the team uses daily.

I go to the page myself to investigate and see this.

Yikes! After some digging into the issue, it turns out the data center hosting this application is experiencing an outage. In the back and forth of customer service emails, it’s apparent that my team is constantly going back to the site to check whether it’s up or down

Taking the opportunity

Surely there are existing services for this, but as an exercise, I decided to write a script that will “ping” the site and send me an email when anything changes. I notified the team that I’d be monitoring the site for changes (and it was nice to get that “Thank You!” even before opening the editor.)

What I came up with looked like this:

def ping(host: str, success_code: int, expected_code: int) -> None: 
    # send an initial email that monitoring of `host` has started
    
    # while the page returns any status code other the `success_code`, loop
        ## send a request and get a response
        
        ## if the status code changes from expected, capture the response content and email it
        
        ## if the status code is the `success_code`, loop exits

    # trigger an email that the site is back up and return

Not too bad. When you get into it, all you really need is `requests` and the standard library. I did use a custom utility function for emailing that takes care of opening a connection to the mail server, setting up the components of the email, and sending it (under my own email address), but I’m going to skip over that module.

Here’s the code in full, with the emailing stuff commented out.

import sys  # used later
import time
from datetime import datetime
import requests
import email_as_jdc as email

def ping(host: str, success_code: int, expected_code: int) -> None:
# send the initializing email here -> email.send_email(“Monitoring started”)
    current_code = expected_code
    msg = ""
    while current_code != success_code:
        if current_code != expected_code:
            expected_code = current_code
            # send email that status code changed->email.send_email(msg)
        try:
            response = requests.get(host)
        except Exception as e:
      # keep looping, but show exception in print under finally
            result = str(e)
        else:
            result = response.status_code
            current_code = result
            if current_code != expected_code:
   # used in if-statement up top, which will trip
                msg = response.text
        finally:
            print(f"{datetime.now()}: {result}")
            time.sleep(5)
    msg = “Monitoring halted. Site back up”
    # trigger success email -> email.send_email(msg)
    return

With this working, I set up an if __name___ == “__main__” section so that I could get it going in a straightforward way.

if __name__ == "__main__":
    try:
        host, success, expected = sys.argv[1:4]
        success = int(success)
        expected = int(expected)
    except Exception:
        print("Error with parameters: please provide a host, a success code and current expected code.")
        print("For example -> python website_monitor.py [host] [success] [expected]")
    else:
        ping(host,success,expected)

And there we have it. A call in my terminal to get things started:

python website_monitor.py https://salesrep.friedrich.com/ 200 503

This was just good enough for the job, nothing fancy, and it ran for a couple days checking status every 5 seconds.

The tool comes back online

While at the gym, I check my email and I’m pleased to see an email, from myself to myself, with a notification! I forwarded this afterwards to the team and let them know the site was back up.

And just to make sure, I visited the site.

The actual code took no longer than a few minutes to write, and I just ran it from the command line in my laptop. In the end, I was able to provide a timely notification to my own team and even sales managers at Friedrich (another “Thank You!”) all while having fun with Python.

About The Author

Joseph Carboni is a multifaceted programmer with a background in bioinformatics, neuroscience, and sales, now focusing on Python development. He developed a ribosomal loading model and contributed to a neuroscience paper before transitioning to a six-year sales career, enhancing his understanding of business and client relations. Currently, he’s a Python Developer at Shupe, Carboni & Associates, improving business processes, and runs Carboni Technology for independent tech projects. Joseph welcomes collaborations and discussions via LinkedIn (Joseph Carboni), Twitter (@JoeCarboni1), or email (joe@carbonitech.com).


Publish your writings here!

We are always looking to publish your writings on the pyATL website. All content must be related to Python, non-commercial (pitches), and comply with out code of conduct.
If you’re interested, reach out to the editors at hello@pyatl.dev

, ,