Monitoring a Golang application with Supervisor

Dear reader… If you are reading this post a few years after his publication date you must understand that in 2018 we were very excited about things like micro services, Docker, Kubernetes and related technologies.

So, our first reaction when thinking about “application deployment” is put all this magic together and run our API, or a hand full of micro services, in a complex environment with Kubernetes, Istio, and so on. I’ve ‘Been there, done that’…

But, in moments like these, we can always count on internet wisdom:

In this post, I will present a simple solution that I believe will fit for a lot of projects out there: Supervisor. According to the Supervisor’s site:

Supervisor is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems.

The first time I used Supervisor was in 2008, to monitor some queue consumer workers, developed in PHP. This can prove two facts:

1. I’m getting old;
2. Supervisor is a battle tested tool.

Let’s jump to the example.

Installation

In this post, I used a Linux box with Ubuntu 18.04, but in the Supervisor’s site, we can find instructions regarding the installation process in other distros.

I executed:

We can use the following command to check the status of Supervisor:

We don’t have any service been monitored, so the command result is empty.

Let’s create an API in Go (version 1.11) to use as our service. I created a main.go with:

We can now generate the binary with the command:

The next step is to configure Supervisor to manage our API. We need to create a config file in:

With the content:

We need to create a file like this for each process that Supervisor will manage. In this file, we define the name of our process ([program:api]), the command that will be executed (command=/usr/local/bin/api), if Supervisor should restart the service if any kind of error occurs (autorestart=true) and the log destination (stderr_logfile and stdout_logfile). We can configure environment variables that will be used by the process (environment) and other options that can be found in the documentation.

Now we need to tell Supervisor to reload the configuration files, including the one we just created:

And let’s check the process status:

As we can see, the process is alive and running.

Let’s change our API to write some access logs :

To update our service we need to execute:

After a few access, we can see that the logs are been stored in the file /var/log/api.log, as configured in /etc/supervisor/conf.d/api.conf:

As a final test, let’s change our API again, this time to emulate an error:

Updating the service again:

Let’s access the error generation URL:

As we can see, the error log was generated in the expected place:

As Supervisor is monitoring our process, we know that the API is running again, what we can prove with the command:

With Supervisor you can count on a simple infrastructure to manage your services, at least until the project became more complex and you need to move to something like Kubernetes.