watch this The wheels are turning, slowly turning. home
Twisted Web in 60 seconds: logging errors 2009-10-22

Welcome to the twelfth installment of “Twisted Web in 60 seconds”. The previous installment created a server which dealt with response errors by aborting response generation, potentially avoiding pointless work. However, it did this silently for any error. In this installment, I’ll modify the previous example so that it logs each failed response.

This example will use the Twisted API for logging errors. As I mentioned in the first post covering Deferreds, errbacks are passed an error. In the previous example, the _responseFailed errback accepted this error as a parameter but ignored it. The only way this example will differ is that this _responseFailed will use that error parameter to log a message.

This example will require all of the imports required by the previous example, which I will not repeat here, plus one new import:

  from twisted.python.log import err

The only other part of the previous example which changes is the _responseFailed callback, which will now log the error passed to it:

      def _responseFailed(self, failure, call):
          err(failure, "Async response demo interrupted response")

I’m passing two arguments to err here. The first is the error which is being passed in to the callback. This is always an object of type Failure, a class which represents an exception and (sometimes, but not always) a traceback. err will format this nicely for the log. The second argument is a descriptive string that tells someone reading the log what the source of the error was.

Here’s the full example with the two above modifications:

from twisted.web.resource import Resource
from twisted.web.server import NOT_DONE_YET
from twisted.internet import reactor
from twisted.python.log import err

class DelayedResource(Resource):
    def _delayedRender(self, request):
        request.write("Sorry to keep you waiting.")

    def _responseFailed(self, failure, call):
        err(failure, "Async response demo interrupted response")

    def render_GET(self, request):
        call = reactor.callLater(5, self._delayedRender, request)
        request.notifyFinish().addErrback(self._responseFailed, call)
        return NOT_DONE_YET

resource = DelayedResource()

Run this server (see the end of the previous installment if you need a reminder about how to do that) and interrupt a request. Unlike the previous example, where the server gave no indication that this had happened, you’ll see a message in the log output with this version.

Next time I’ll show you about a resource that lets you host WSGI applications in a Twisted Web server.