Hacking Flask: A Success Story

     

AKA Flask Howto: Add request execution time to log output

By Jay Taylor, published April 24th 2013


I scoured the internet high and low for a way to add request execution time logging to my Flask server console output, but failed to find any examples of how to do it. Here is my formula for one way to make it happen.

We are going to turn this:

INFO:werkzeug:127.0.0.1 - - [24/Apr/2013 18:36:46] "GET / HTTP/1.1" 200 -

into this:

INFO:werkzeug:127.0.0.1 - - [24/Apr/2013 18:45:13] "GET / HTTP/1.1" 200 - [37ms]

It turns out that the HTTP server component of Flask is a super thin wrapper around the Werkzeug WSGI library. The strategy is simply going to be implementing our own subclass of werkzeug’sBaseRequestHandler with a few overrides to capture and then inject information related to HTTP request execution time:

serving.py:

# -*- coding: utf-8 -*-

import time
from werkzeug.serving import BaseRequestHandler

class MyFancyRequestHandler(BaseRequestHandler):
    """Extend werkzeug request handler to suit our needs."""
    def handle(self):
        self.fancyStarted = time.time()
        rv = super(MyFancyRequestHandler, self).handle()
        return rv

    def send_response(self, *args, **kw):
        self.fancyProcessed = time.time()
        super(MyFancyRequestHandler, self).send_response(*args, **kw)

    def log_request(self, code='-', size='-'):
        duration = int((self.fancyProcessed - self.fancyStarted) * 1000)
        self.log('info', '"{0}" {1} {2} [{3}ms]'.format(self.requestline, code, size, duration))

gist

Next we tell the server which request_handler to use where the server gets started:

Before:

app.run(host='0.0.0.0', port=port)

After:

app.run(host='0.0.0.0', port=port, request_handler=MyFancyRequestHandler)

And then that’s it, we’re all done.


I’m impressed with Flask’s potent combination of simplicity and flexibility. It’s second to no other python web framework I’ve encountered.

About The Author