Making python xmlrpclib.ServerProxy log method names and parameters revisited

In my previous post I described a procedure to log XMLRPC client calls. The procedure will do the job, but it does not suffice when you’re connecting to multiple XMLRPC servers from a single process and you want to log calls sent to one specific server. So, here’s an improvement.

You can provide a Transport instance upon creation of an instance of the ServerProxy. The ServerProxy will create a Transport if you don’t provide one, thus enabling specific overrides. You’ll find another example of an implementation of a Transport here. Using a Transport for debugging purposes is almost perfect, there is just one thing that needs to be done. The method and parameters are serialized. You need to deflate serialized data using xmlrpclib.loads when you don’t want to log the serialized (XML) format. Enough for theory, here’s the practice:

  1. import xmlrpclib
  3. class PrintingTransport(xmlrpclib.Transport):
  4.   def _log_request(self, host, request_body):
  5.    deflated_request = xmlrpclib.loads(request_body)
  6.    method = deflated_request[1]
  7.    params = deflated_request[0]
  8.    # deflated_request now contains a tuple
  9.    print 'Calling %s(%s) @ %s' % \
  10.          (method, \
  11.          ', '.join([str(e) for e in params]),\
  12.          host)
  14.   def request(self, host, handler, request_body, verbose=0):
  15.    self._log_request(host, request_body);
  16.    return xmlrpclib.Transport.request(self, host, handler, \
  17.           request_body, verbose=verbose)
  20. if __name__ == '__main__':
  21.    client = xmlrpclib.ServerProxy(
  22.               "",
  23.               transport = PrintingTransport(),
  24.    )
  25.    print client.examples.getStateName(12)

When started it will output this:

  1. Calling examples.getStateName(12) @
  2. Idaho

Suggestions, remarks or improvements? Drop me a line.

Leave a Reply

Your email address will not be published. Required fields are marked *