« April 2004 | Main | June 2004 »

May 27, 2004

XMLRPC as a debugging aid

I have a server application which is responsible for processing data as it becomes available. It scans all of the available data at startup and starts work on any source data which isn't already taken care of, and, once done, it waits. It gets notified when new data is added to the system (by another application which is responsible for getting new data), at which point it processes the new data, then waits again. As new source data is processed, a third application is notified that new processed data is available.

The applications here are built using Python, and the notifications are done using XMLRPC, using the xmlrpclib library included with Python. I chose XMLRPC because it's a workable IPC mechanism across processes that may or may not be on the same machine, and because it's ridiculously simple to use with Python.

Recently, I've had a need to debug this application while it's running. The time between startup and the satte I want to inspect is pretty long, and I don't want debug output spewing about the screen in the meantime, amking it harder to find the one message I'm actually interested in. (What I'm looking for is the state work queue once most of the available data has been processed, but some errors are occuring in a few items in the queue, which are getting retried.)

So I'm thinking back to my C programming days, where I could run gdb then attach to an already running program and see what's going on, then detach and let it continue. I find out that there is a python debugger, but you need to run the program in the debugger, plus I don't really want a gdb-like UI.

XMLRPC to the rescue! I'm already running an XMLRPC server, so I can poke at my program that way. All I have to do is fire up the Python interpreter and has at it:

[bluntman:~] wsanchez% python
Python 2.3 (#1, Sep 13 2003, 00:49:11) 
[GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import xmlrpclib
>>> p = xmlrpclib.ServerProxy("http://localhost:8001", allow_none = 1)
>>> p.queue()
{'thread01': {'group_data': {'Group1': True, 'Group2': True, 'Group3': True}, 'data': {}},
 'thread02': {'group_data': {}, 'data': {}}}

The dictionary returned by p.queue() is the internal representation of the work queue I keep in my application. I can see here that thread01 has some grouped data to work on, and no individual itmes to work on. thread02 has no work to do. Additionally, I can set the logging level as I need, and add items to the work queue:

>>> p.logger.set_level(0)
>>> p.add_to_queue("group_data", "Group5")
>>> p.logger.set_level(1)

Simply being able to turn debug-level logging on and off while the program is running is a huge win, but being able to modify its state is limitless in its utility.

One downside here is that running an XMLRPC server brings you into the world of threaded applications, and if you aren't already there, it can present a new class of problems for you to worry about. However, if all you need to do is look at state or modify settings that aren't subject to major concurrency issues (eg. set the logging level), you don't have to worry too much about threads, and that much utility alone can be quite worthwhile.

May 26, 2004

Subversion 1.0.4 package available

I've updated the Subversion package on my iDisk to 1.0.4.
Dependencies are unchanged, so if upgrading you only need to install Subversion.