Customizing Sanic's Logging output on Gunicorn

For those of you who didn't know, Sanic is a Python 3.6+ web server and web framework that’s written to go fast. It allows the usage of the async/await syntax added in Python 3.5, which makes your code non-blocking and speedy.

Sanic's API is highly influenced by Flask and the API is really good.

I worked on a personal project lately and found out that doing custom logging on Sanic is quite hard. You don't get a lot of information from Sanic's logging library and since it's based on the default Python 3 logging library, the information it provides is limited.

My initial thought was since I will use Gunicorn, let's use Gunicorn's --access-logformat to get the information I needed. The functionality provided a lot of information and I can make use of it to get what I need. However, when you use Sanic Gunicorn Worker, which you need to use to make it work on Gunicorn, it will only use Sanic's logging output.

I did a lot of googling and it seems like a lot of people have the same problem. Then, I found this issue on github. Apparently you can leverage middleware to modify request and responses and make it a standardised way for all endpoints.

There are 3 things you would need to do, though.

First, you would need to turn off Sanic's logging configuration when you create the app. You can do this by passing in the configure_logging=False into the constructor. You can see the example in the gist.

Second, create the middleware for response. Use the print functionality to print whatever information you needed. You can get the information from both the request and the response object. In my example I use the request middleware as well since I want to know the latency.

Third, in the Gunicorn startup script you need to use the --capture-output flag.

These two combined will stop Sanic from using it's default logging, print log from the middleware and get Gunicorn to capture the printed output.

The middleware code is as shown below:


My Gunicorn startup script looked like this:

gunicorn app:app --bind ${HOST:-0.0.0.0}:${PORT:-5000} --worker-class sanic.worker.GunicornWorker -w 3 --capture-output

That should do the trick.

Hope this saves you the pain of googling for solutions.

Regards

-E-

follow @femmerling on twitter

Comments

Popular posts from this blog

LDAP Login Authentication Using Python LDAP

My Take on The 10X Engineer Myth

Android TDD Using JUnit, Robolectric and Mockito