CFML, Clojure, Software Design, Frameworks and more...

Remote Debugging

May 8, 2012 ·

Your application is live but it isn't quite behaving the way you
expect - what do you do? You'd like to instrument the code, you'd
like to be able to run parts of your production code in the live
environment and look at the output, you might even like to replace
functions with updated code. How can you do that?

With most languages, this would be very difficult. Lisp languages
tend to make this possible and Clojure makes this possible on the
JVM.

You can run Clojure on Heroku and they've recently published a great
article
about debugging an application remotely using a REPL (Read Eval
Print Loop) over HTTP. At World Singles, we've necessarily taken a
slightly different tack. Our main web applications are built in CFML
(powered by the JBoss community project Railo) and we dynamically
load Clojure code for the model. We also have long-running processes
that are pure Clojure (which are not web applications). The approach
in the Heroku article won't work for us.

By simply making swank-clojure 1.4.2 a dependency and
calling (swank.swank/start-server :host "0.0.0.0" :port
n), you get a REPL over SLIME (Superior Lisp Interaction Mode
for Emacs) and therefore you can connect from your development
environment direct into your live, running application.

We don't have Swank running all the time. We can start and stop the
Swank server at will. When it is running, we can connect from Emacs
with M-x slime-connect and then specifying the server IP
address and port. At that point, we have a live connection from our
IDE (Emacs) directly into our running, production application, so we
can run database queries, execute code and even replace code in the
live image.

Whilst that might sound a little scary, it's also very empowering. You can
execute any function in your code base directly in the production
context. SQL queries (and updates) are the obvious first step but
any business logic functions are also accessible. You can either
type them into the REPL or from existing code with c-x c-e
which transfers code from an edit buffer across the REPL to the live
server.

This allows you to do full debugging in a live context,
investigating the data and behavior of your application. If you find
a bug, you can formulate new versions of the functions in your
application and then apply those definitions live as well.

Very few technologies provide you with this level of power. A power
that comes with commensurate responsibility - debug carefully young man!