Observability: Python Health Check Example

08.22.2021

Intro

Building out health checks is a common task when building a web server. You may have seen status sites, such as Github status, where we can see the update time of each service that is offered. In this article, we will learn how to create a basic health check end point in Python.

The first step to building out a feature like this could be a simple health route, then we can combine this with a metrics counter to log a time of up and down time. We could also add alerting for when our service goes down. In later articles, we will explore adding these features. Let's get started with a few basics.

Installing the Modules

For this project, we will simply build a basic http service and eventually we will connect to our DB to ensure the service is fully connected. To do this, install the following.

pip install flask psycopg2

A Basic Health Endpoint

Let's start by creating a simply endpoint called /health that we can ping. This endpoint will simply return a 200 status. If we don't get a 200 status, we can assume the server is down.

from flask import Flask

app = Flask(__name__)

@app.route("/health")
def health():
    return

if __name__ == "__main__":
    app.run()

Checking the Health

Now, to ping the service, we can curl as such:

curl http://localhost:3000/health

In practice, we would most likely have a cron service that will ping this on an interval, log the result so we can view stats later, and send alerts if there is down time. In a later article, we will build this out.

Adding More to the Health Check

Let's add a little more details our health check. You can get as complex or as simple as you want here. The complexity will depend on what kind of health reports you want. For example, let's say we had a postgres database. To consider our service "healthy" we also want to confirm that we can query to database. Let's add the following:

from flask import Flask
import psycopg2

app = Flask(__name__)
conn = psycopg2.connect("dbname=test user=postgres")

@app.route("/health")
def health():
    cur = conn.cursor()
    cur.execute("SELECT ACK as status;")
    cur.close()
    return

if __name__ == "__main__":
    app.run()