Dozer is mostly known for
its memory profiling capabilities, but the as-yet unreleased version has
more. I've talked
about log capturing, now it's time for
Profiling
This WSGI middleware profiles every request with the cProfile module.
To see the profiles, visit a hidden URL /_profiler/showall:

What you see here is heavily tweaked in my fork of Dozer; upstream
version had no Cost column and didn't vary the background of Time by age (that
last bit helps me see clumps of requests).
Here's what an individual profile looks like:

The call tree nodes can be expanded and collapsed by clicking on the
function name. There's a hardcoded limit of 20 nesting levels (upstream had a
limit of 15), sadly that appears not to be enough for practical purposes,
especially if you start profiling Zope 3 applications...
You can also take a look at the WSGI environment:

Sadly, nothing about the response is captured by Dozer. I'd've liked to
show the Content-Type and perhaps Content-Length in the profile list.
The incantation in development.ini is
[filter-app:profile]
use = egg:Dozer#profile
profile_path = /tmp/profiles
next = main
Create an empty directory /tmp/profiles and make sure other users
cannot write to it. Dozer stores captured profiles as Python
pickles, which are insecure
and allow arbitrary
command execution.
To enable the profiler, run paster like this:
$ paster serve development.ini -n profile
Bonus feature: call graphs
Dozer also writes a call graph in Graphviz "dot" format in the profile
directory. Here's the graph corresponding to the profile you saw earlier,
as displayed by the excellent XDot:

See the fork where the "hot" red path splits into two?

On the left we have Routes deciding to spend 120 ms (70% total time)
recompiling its route maps. On the right we have the actual request dispatch.
The actual controller action is called a bit further down:

Here it is, highlighted. 42 ms (24% total time), almost all of which is
spent in SQLAlchemy, loading the model object (a 2515 byte image stored as a
blob) from SQLite.
A mystery: pickle errors
When I first tried to play with the Dozer profiler, I was attacked by
innumerable exceptions. Some of those were due to a lack of configuration
(profile_path) or invalid configuration (directory not existing), or now
knowing the right URL (going to /_profiler raised TypeError). I
tried to make Dozer's profiler more forgiving or at least produce clearer
error messages in my fork,
e.g. going to /_profiler now displays the profile list.
However some errors were very mysterious: some pickles, written by Dozer
itself, could not be unpickled. I added a try/except that put those at the end
of the list, so you can see and delete them.

Does anybody have any clues as to why profile.py
might be writing out broken pickles?
Dozer is mostly known for
its memory profiling capabilities, but the as-yet unreleased version has
more:
Log capturing
This WSGI middleware intercepts logging calls for every request. Here
we see a toy Pylons application I've
been working on in my spare time. Dozer added an info bar at the top:

When you click on it, you get to see all the log messages produced for this
request. I've set SQLAlchemy's loglevel to INFO in my
development.ini, which produces:

(Why on Earth does SQLAlchemy think I want to see the memory address of the
Engine object in my log files, I don't know. The parentheses contain
argument values for parametrized queries, of which there are none on this
page.)
Upstream version displays absolute timestamps (of the YYYY-MM-DD
HH:MM:SS.ssssss variety) in the first column; my fork shows deltas in
milliseconds. The incantation in development.ini is
[filter-app:logview]
use = egg:Dozer#logview
next = main
which makes it disabled by default. To enable, you run paster like this:
$ paster serve development.ini -n logview
(Upstream version lacks the paste entry point for logview; it's in my
fork, for which I submitted a pull request weeks ago like a good open-source
citizen. Incidentally, patches for stuff I maintain have been known to
languish for years in my inbox, so I'm not one to throw
stones.)
Coming soon: profiling with Dozer.
irclog2html, the IRC log to HTML
converter, is now (finally!) available from the Python Package Index.
In other news, logs2html now copies irclog.css to the
destination directory (if it doesn't exist there already). I've been noticing
logs produced with irclog2html on random places, and sometimes they were
unstyled; hopefully this will become rare now.
If you click on an ePub download link in the Android browser and get back
an error saying "Cannot download. The content type is not supported on the
device", then make sure the web server is setting the Content-Type header to
"application/epub+zip" and not "application/octet-stream". When you do this,
Android will launch FBReaderJ automatically (provided that you have it
installed, of course).
My N900 has a SIM card with a flat-rate 3G data plan. My laptop hasn't.
What do I do when I want to use the Internet on my laptop somewhere that
doesn't have WiFi? Well, there are many options:
Option 1: N900 as a USB modem
Use the provided USB cable to connect the N900 to the laptop. Choose "PC
Suite" mode on the N900 when you get the USB connection menu. The laptop
now sees your N900 as a bog-standard USB 3G modem. Use Network Manager to
connect to the internet.
Pros: no extra setup required. The N900 and the laptop can both access
the Internet at the same time.
Cons: you have to use a USB cable (I hate cables). You cannot ssh into your
N900 (and ssh is my primary file transfer protocol between the laptop and the
M900).
Option 2: N900 as a Bluetooth DUN modem
Install Bluetooth DUN
support from Maemo Extras. Then use it like you would any other phone
that has Bluetooth DUN.
Pros: no cables.
Cons: Bluetooth is the worst technology ever. I never had it
work reliably. Plus, Network Manager in Ubuntu 10.04 doesn't support
Bluetooth DUN (it supports only Bluetooth PAN, as far as I know).
Option 3: N900 as a WiFi access point with Joikuspot
I haven't tried this.
Pros: simple (hopefully), no cables required.
Cons: Joikuspot is non-free. I'm not an absolute zealot, but I will
avoid closed-source stuff when open-source alternatives are available.
Option 4: N900 as a WiFi access point with Mobilehotspot
I haven't tried this either.
Pros: it's an open-source app available from Maemo Extras. No cables
required.
Cons: requires a non-standard kernel (or so I've heard). Way outside my
comfort level.
Option 5: N900 as a WiFi access point with shell scripts
Here's the shell script I run on my N900: share-wifi. It sets up an ad-hoc WiFi
network, and starts a DHCP and DNS server (dnsmasq). Sadly, it cannot set up
connection sharing (NAT), so I rely on OpenSSH as a SOCKS5 proxy. The whole
setup is like this:
- You want the latest firmware (PR 1.2) to avoid this bug.
- You need to have OpenSSH installed on
the N900. Also, setting up key-based authentication makes it more
convenient.
- The script assumes that you've set up sudo on the N900 so that you
can run any command as root.
- You need to have wireless-tools
installed. It's in the main SSU repository so you should be able to sudo
apt-get install it (if it's not preinstalled; I don't remember).
- On the N900 run share-wifi in a terminal (optionally passing a
WiFi channel number from 1 to 11, in case you need to avoid interference with
nearby networks).
- On the laptop connect to the new n900 WLAN and run
ssh -D 1080 user@n900. You will get a shell session; the SOCKS proxy
will be active while it is open.
- Reconfigure your laptop to use a SOCKS5 proxy on localhost:1080.
For GNOME systems I've a couple of shell scripts: proxy-on and proxy-off. For applications
that do not use the GNOME proxy settings (such as Subversion access
over SSH), use tsocks.
- When done, hit Ctrl-C on the N900 to terminate the sharing script.
Pros: no non-free software or custom kernel required. No cables.
Cons: complicated to set up. No WLAN power savings available for ad-hoc
networks, so battery life is extremely poor (~2 hours). But, hey, no
cables!