Monday, July 25, 2011

Checking Web Application Health

There are certain things you want to know about your web application to make sure it has started correctly and to help diagnose problems.
  • Is it up?
  • Can it connect to the database(s)?
  • Can it connect to the web service(s)?
  • Can it do any other actions that may independently break?
  • What are the server settings?
  • What version of the code is running?
The first question is easy to answer? But what about the others? You can obviously determine if the other dependencies are up by going to the appropriate place in your application, but it'd be nice to have a single location to check all of these. And what about server settings or code version? Ever had a bug reported that you know you fixed? It's nice to also be able to make sure that you really are running the version you think you are.

Here's how I've accomplished this on a Ruby on Rails project.

Single Location
First, I created a controller with a single page:
prompt> rails generate controller Admin index
Here is the beginning of the controller class.
class AdminController < ApplicationController
  before_filter :require_admin

  def index
  end
end
As you can see, I've protected it, so only administrative users can view this page. Here is the views/admin/index.html.haml where I show server state.
This is the status page.
%br
%h2 Version
%pre= @version
%h2 Environment
%br
%b RAILS_ENV:
= ENV['RAILS_ENV']
%br
%hr
%h2 Site Tests
.test
  = button_to "Test DB", {:action=>"test_db"}, :remote=>true, :onClick=>"startTest()"
%hr
%h2 Test Output
#testOutput

:javascript
  function startTest() {
    $("#testOutput").replaceWith('<div id="testOutput">Loading...</div>');
  }

Dependency Tests
I've implemented each test as a separate Ajax call. In the view code above, this everything from "Site Tests" on down. This consists of the buttons (one for each test, just one here), a place to show the output, and the javascript to make this work. For each test, I just add a new button in the .test div. As you can see in the code above, the button makes an Ajax call (:remote=>true) and calls a javascript function to show that the result is loading. It is up to the controller to then update the testOutput div with output status.

In my admin_controller.rb I have a function for each button that looks like:
def test_db
  standard_test do
    # insert test code here
  end
end
The helper function standard_test looks like:
def standard_test
  begin
    yield
    @success = true
  rescue Exception => e
    @success = false
    @exception = e
  end
  respond_to do |format|
    format.html {
      flash[:error] = "This should've been ajax"
      redirect_to admin_index_path
    }
    format.js {
      render 'test_output', :layout=>false
    }
  end
end
All it does is executes the test code (via the yield statement) and catches any thrown exceptions. If there is no exception, it considers the test a success. Assuming it was called via an Ajax call, it then renders the javascript template test_output.js.haml which is simply:
!= "$('#testOutput').replaceWith('#{escape_javascript render(:partial=>'test_output')}')"
As you can see, this merely replaces the testOutput div with what is rendered by the _test_output.html.haml partial:
#testOutput
  - if @success
    %b SUCCESS
  - else
    %b ERROR
    %br
    %b Error Class:
    = @exception.class
    %br
    %b Error Message:
    %pre= @exception.message
    %b Error Stack Trace:
    %pre
      - @exception.backtrace.each do |line|
        = line
    %b Error Inspect
    %pre= @exception.inspect
Of course, don't forget to make sure your routes are in your config/routes.rb.
get 'admin/index'
post 'admin/my_test' # separate route for each test
Version
Including version information is going to be very specific to your environment. We use Mercurial for our version control, and since we have a number of Java project, we use ant for our deployment process. Here is how I connected these together.

In the ant deployment script, I added a target that looks like:
<target name="write.hg.version">
  <exec executable="hg" dir="${project}" output="${project}/config/version.txt">
    <arg value="summary" />
  </exec>
</target>
All that is left is to get the contents of this version.txt file into the @version variable that is displayed by index.html.haml. This is done by simply having the index method in admin_controller.rb read in the file.
def index
  name = File.join(RAILS_ROOT, 'config', 'version.txt')
  if File.exists? name
    f = File.new(name)
    @version = f.read
  else
    @version = "Unknown version"
  end
end
Conclusion
This really wasn't too much work, and now I have a single page that I can go to and at a glance see what version of the code was deployed and which rails environment is being used. Adding new tests is just a simple matter of adding a new button to the view, which calls a new test method in the controller. By leveraging the standard_test method, new tests can consist of just the code they are intended to test.

Monday, July 18, 2011

Windows Command Line Cut & Paste Rant

Just a quick rant this week. When selecting text in the windows command console, why does it do a "block" mark rather than a line based mark?!?! In every other text based environment I've used, including Windows Notepad and MS Word, if you start highlighting text in the middle of one line and move down to the middle of the next line it select the end of the first line and the beginning of the next line.  i.e. all the text that starts where you started the mark and ends where you ended the mark. For some reason the Windows Command shell only marks the text that is actually in the box, i.e. a couple characters in the middle of both lines.

Is there a time that this behavior is useful? If you know, please share it with me.

For me, I often want to copy either a long command line I ran, or the output of a command, to put in an email, IM, a wiki, or even to paste into another terminal to run. But if the line is wrapped, then to make sure I get everything I want, I have to also copy the command prompt. This means I have to add an intermediate step of editing my selection before I can send it.

What's even more bizzarre to me, is that in searching on the web, I can't even find any other comments about this behavior. Nor can I find a way to change this. Am I the only one who finds this annoying? More importantly, does anyone know how to change this behavior?

(I know, I know. I shouldn't be using Windows, and I shouldn't be cutting and pasting. Well, I have to admit that I sometimes do both, and I was doing a lot of both this past week.)

Monday, July 11, 2011

Attack of the Clones

As I mentioned, I was recently at ICSE. One of the big topics there was Clones. How do you detect them? How do you remove them? The talk that I found most interesting on the topic was one where they tried to measure how bad clones really are.

First, the definition for those of you aren't familiar with the term clone in the context of software engineering. (I wasn't before this conference). A clone is just what it sounds like, duplicated code. Clones are most often created via cut and paste.

The idea of removing duplicated code through common modules, whether they are libraries, classes, functions, procedures, or macros is an old one. Probably about as old as programming. In recent years, removing duplicated code has even got a hip acronym: DRY. The idea that clones are bad was basically a given at this conference. I have pretty much internalized that idea, so this didn't seem strange to me at all.

So how bad are they? Well, as I mentioned above, there was research that tried to answer this question. Researchers analyzed the version control history of a few different projects and tracked all of the clones in these projects. They then tried to evaluate some of the problems. For example, one of the problems with clones is that if you change the code, you have to remember to do that change in multiple locations. What they found was that in the vast majority of the time, clones either never changed, or only changed once. Meaning that the majority of the time, the work of refactoring the code to remove the clones would be at least as large as the work of just maintaining them.

What about the situation where one clone is modified, but another copy doesn't get updated. Well, they found that this is also very rare, and a lot of the time when this does happen, its intentional. And even of the times when they are unintentionally out of sync, the resulting code is typically not a bug.

So what does all this mean? I don't know. Maybe their sample projects weren't representative of most software projects. Or maybe, just like most other engineering decisions, there are trade offs, and there isn't a 100% right answer, independent of context. I still find that clones offend my sense of software ascetics most of the time, but I am trying to be a little more open-minded and be critical about what and when I refactor.

Monday, July 4, 2011

GCJ 2011 T-Shirt

Due to the holiday weekend, I am just making a short post this week.

Last week I mentioned that I got knocked out of the TCO 2011 competition, and so will get no shirt for it. Well, a couple days later FedEx delivered my Google Code Jam 2011 t-shirt. It's not as cool as getting the trip to Japan for the finals, but I guess I'll take what I can get. Since a picture was requested, here it is. And, no Alan, programming contests don't completely eliminate the need to go clothes shopping, though I do have around two dozen t-shirts plus a nice winter coat and hat from various programming contests.