getting full exception information from an xmlrpc server

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Scott

    getting full exception information from an xmlrpc server

    I'm debugging an xmlrpc client/server application. Often when an
    exception occurs in the server, I receive only a very short error
    message on the client. For example:

    xmlrpclib.Fault : <Fault 1: "<type 'exceptions.Ass ertionError'>:" >

    Presumably this is because xmlrpclib on the server is catching the
    exception, and only sending the exception name to the client, not the
    server's stack trace.

    What I would like is the full stack trace of what went wrong on the
    server (i.e. the junk python usually dumps to the console when an
    exception occurs). I don't care which side I see the dump on (client
    or server), but I need to see the whole trace so I can figure out what
    the problem is. Is there an easy way to do this?

    Thanks,
    Scott
  • Fredrik Lundh

    #2
    Re: getting full exception information from an xmlrpc server

    Scott wrote:
    I'm debugging an xmlrpc client/server application. Often when an
    exception occurs in the server, I receive only a very short error
    message on the client. For example:
    >
    xmlrpclib.Fault : <Fault 1: "<type 'exceptions.Ass ertionError'>:" >
    >
    Presumably this is because xmlrpclib on the server is catching the
    exception, and only sending the exception name to the client, not the
    server's stack trace.
    xmlrpclib is a client library. The faultString message you see here is
    provided by the server.

    </F>

    Comment

    • draghuram@gmail.com

      #3
      Re: getting full exception information from an xmlrpc server

      On Aug 13, 3:31 pm, Scott <smba...@gmail. comwrote:
      What I would like is the full stack trace of what went wrong on the
      server (i.e. the junk python usually dumps to the console when an
      exception occurs). I don't care which side I see the dump on (client
      or server), but I need to see the whole trace so I can figure out what
      the problem is. Is there an easy way to do this?
      I had the same need and I am copying the code I used here. Please note
      that the code does a little bit more than getting the full stack
      traces. To use it, simply copy it to a file and use "Server" and
      "ServerProx y" from this module.

      Thanks,
      Raghu

      ---

      '''

      This package provides a userful wrapper around the xmlrpc client and
      server
      from stdlib. The main benefits include:

      The server provides functions alive and kill. More over, any exception
      generated
      in rpc functions result in the whole stack trace to be sent across.
      The client
      processes this stack trace and re-raises the exception.

      '''

      from SimpleXMLRPCSer ver import SimpleXMLRPCSer ver
      import xmlrpclib
      import sys
      import socket
      import SocketServer
      import traceback

      # All public methods in this class are callable by clients.
      class UtilityFuncs(ob ject):
      def __init__(self, *args, **kwargs):
      self.running = True

      def kill(self):
      self.running = False
      return True

      def alive(self):
      return True

      class Server(SimpleXM LRPCServer):
      def __init__(self, *args, **kwargs):
      self.util_inst = UtilityFuncs()
      SimpleXMLRPCSer ver.__init__(se lf, *args, **kwargs)
      self.register_i nstance(self.ut il_inst)

      def server_bind(sel f):
      self.socket.set sockopt(socket. SOL_SOCKET, socket.SO_REUSE ADDR,
      1)
      SimpleXMLRPCSer ver.server_bind (self)

      # The default dispatcher does not send across the whole stack
      trace.
      # Only type and value are passed back. The client has no way of
      knowing
      # the exact place where error occurred in the server (short of
      some
      # other means such as server logging). This dispatcher sends the
      whole
      # stack trace.
      def _dispatch(self, method, params):
      try:
      return SimpleXMLRPCSer ver._dispatch(s elf, method, params)
      except:
      # can't use format_exc() as it is not available in jython
      yet (even
      # in trunk).
      type, value, tb = sys.exc_info()
      raise xmlrpclib.Fault (1,
      ''.join(traceba ck.format_excep tion(type, value, tb)))

      def serve_until_don e(self):
      # In a threaded server, kill() may need to be called twice.
      The first,
      # time it is called, the loop may test 'running' before the
      new thread
      # has a chance to set it to False.
      while self.util_inst. running:
      self.handle_req uest()

      class ThreadedServer( SocketServer.Th readingMixIn, Server):
      pass

      # A special exception has been defined just to indicate in the client
      that the exception
      # has in fact originated on the server.
      class ServerException (Exception):
      pass

      # The server sends the whole stack trace as a string. Convert it back
      to
      # an exception here.
      class ExceptionUnmars haller(xmlrpcli b.Unmarshaller) :
      def close(self):
      try:
      return xmlrpclib.Unmar shaller.close(s elf)
      except xmlrpclib.Fault , e:
      raise ServerException (e.faultString)

      class ExceptionTransp ort(xmlrpclib.T ransport):
      # getparser() in xmlrpclib.Trans port has logic to choose fastest
      parser
      # available. The parser needs to be passed an unmarshaller.
      Unfortunately,
      # getparser() there does not take unmarshaller as a parameter so
      we
      # can not simply call it with our unmarshaller. Either the whole
      code
      # there needs to be replicated here using our unmarshaller or we
      use
      # a much simpler version. The latter is chosen (partly because the
      code is
      # inspired by ASPN recipe 365244.
      def getparser(self) :
      unmarshaller = ExceptionUnmars haller()
      parser = xmlrpclib.Expat Parser(unmarsha ller)
      return parser, unmarshaller

      class ServerProxy(xml rpclib.ServerPr oxy):
      def __init__ (self, *args, **kwargs):
      # Supply our own transport
      try:
      kwargs['transport']
      except:
      # This is expected
      pass
      else:
      raise Exception('A transport (%s) is provided. This is not
      expected as '
      'a custom transport is being used' %
      kwargs['transport'])

      kwargs['transport'] = ExceptionTransp ort()
      xmlrpclib.Serve rProxy.__init__ (self, *args, **kwargs)
      ---

      Comment

      Working...