DevOps Zone is brought to you in partnership with:

Software developer and architect with over 10 years experience. Diarmuid is a DZone MVB and is not an employee of DZone and has posted 2 posts at DZone. You can read more from them at their website. View Full User Profile

Open Source Application Monitoring: Catching Exceptions

09.02.2012
| 9238 views |
  • submit to reddit

Imagine if you will, you are working on a new critical application and you need to write the output of your process calculations to a file. Simple stuff, a few lines of Java later you have...

File file = new File("myfile.txt");
try {
  boolean fileCreated = file.createNewFile();
  log.debug("fileCreated = " + fileCreated);
} catch (IOException e) {
  log.error("Could not create file",e);
}

You even remembered to log the exception to the logs just in case there was a problem in production. A few weeks later the code ships and works perfectly for weeks until one day the network mount disappears and the application starts to throw exceptions.

Your applications logs then fill up with the exception message and stacktrace but no one realizes there is an issue until an angry customer rings up complaining that they never received their report.

A far worse scenario is that the exception occurs in production but the development staff decide that it is a “good exception” and that the best course of action is to ignore it. Forever! Well until the new guy starts and they have to explain that it is a “good exception”, and so are the following 600 exceptions.

I remember when I first heard the term “Good Exception”, I was working for startup in London over ten years ago. I was new to the company and the first phase of the application was already in production as part of a critical beta phase of the product. Each morning a developer would have to be in the office ready to deal with any issues that may arise from 6am.

One cold December morning I was in the office and as part of the morning grind I was going through a checkout of the application. Checkpoint number 27 was “Check application logs”. No more detail, so I jumped on to the application server and started to tail the logs and to my dismay hundreds of exceptions were being logged in realtime.

I spent the next hour trying to work out what was wrong with the application and what had changed to cause such an exception storm in production. At around 8:00am one of the developers who had the longest tenure in the team arrived in and calmly pointed out “oh those, those are good exceptions, you can ignore them. They occur the day after a billing cycle due to a bug in one the core components”.

Key lesson; Exceptions should be exceptional, if you get an exception in production you need to deal with it.

Exceptional Workflow

Exceptions are part of both the development process and the application monitoring process. An ideal flow is that once an alert is generated in production it is fed back into the development process as a potential bug fix or improvement. The key is to provide adequate monitoring of exceptions in production and to provide sufficient feedback into the development team.

How many of the applications you have worked on have had anything more than log level or log scrapping exception monitoring?

How many development processes have you seen that link production exception to bug fix and strive to fix as many exceptions as possible?

How many “good exceptions” were written to your logs in production since you started reading this post?

Baking Exception Monitoring

Personally I think one of the reasons for poor infrastructure in critical areas like this is down to the way different parts of the organizations are structured. In many large teams people are dedicated to different function of the application lifecycle. Developers are generally focused on the application business requirements and have unforgiving deadlines. Support teams have deadlines of a different type. They also tend to support many applications across a range of functions.

With the advancement of the DevOps movement these communities are starting to join forces and work on the infrastructure behind the applications. So one problem is certainly being addressed and will start to become more and more widespread in the next 2-3 years The other major factor is tool support. How many good modern tools are available for application monitoring that are quick to use and onboard? There are a number of interesting commercial startups in this space at the moment, AirBrake for example is used by a number of corporation to add monitoring support to their application.

Airbrake offers rich functionality but also supports almost all popular languages in it’s API arsenal. However it is hosted on their servers and this deployment configuration will not suit a large majority of application developers who build bespoke software for internal clients and are forbidden to publish information external regardless of content. Interestingly enough there is an open source alternative to AirBrake called ErrBit which is compatible with the AirBrake API.

It’s a ruby on rails application that can be easily installed on your local server or for the purpose of this blog I put it up on Heroku mainly for ease of use. Once you have installed ErrBit you can quickly post exceptions and stacktraces to the server and it has some basic workflow for your support staff to monitor and deal with the exception. It also has integration with some of the most popular Issue Trackers however there is currently no Jira support.

Installing ErrBit

This was the first time I used Heroku for anything even though I had heard great things. I had an account but it was unverified something that I over looked when I did my first installation. ErrBit needs MongoDB and to use MongoDB with Heroku you need to verify your account with a credit card. This surprisingly stop my application working for a while and it took me ages to notice the small error message in the install script. You have been warned!

To install the application you need to follow the simple steps from the github page https://github.com/errbit/errbit (you will need git and ruby installed locally)

Clone the repository

git clone http://github.com/errbit/errbit.git

Create & configure for Heroku

gem install heroku
heroku create example-errbit --stack cedar
heroku addons:add mongolab:starter
cp -f config/mongoid.mongolab.yml config/mongoid.yml
git add -f config/mongoid.yml
git commit -m "Added mongoid config for Mongolab"
heroku addons:add sendgrid:starter
heroku config:add HEROKU=true
heroku config:add ERRBIT_HOST=some-hostname.example.com
heroku config:add ERRBIT_EMAIL_FROM=example@example.com
git push heroku master

Seed the DB

heroku run rake db:seed

Pretty quick, well once you have a validated Heroku account. Once completed simply type

heroku open

And your new ErrBit install should be running. My instance is at ebit.herokuapp.com and you can use anyone@anyone.com/password to login

Once you have installed ErrBit you will need to configure your users and whatever applications you plan to monitor. Again straightforward, clicking “Add a new app” button will bring you to configuration screen And once you create the application record you will get the important application id You will need this later when publishing exceptions

Publishing Exceptions from Java

As I mentioned earlier ErrBit is compatible with all the language APIs that AirBrake provide and luckily for me there is an actively developed API for Java available at http://github.com/airbrake/airbrake-java. This will allow you to send Exceptions from you Java Server Appications, Mobile Applications and Desktop Clients. To start using it with maven add the following dependencies to your pom file

<project>
    <dependencies>
        <dependency>
        <groupId>io.airbrake</groupId>
        <artifactId>airbrake-java</artifactId>
        <version>2.2.0</version>
        </dependency>
    </dependencies>
</project>

Once I imported the libraries I saw a slight problem in how to override the url for communicating with the backend server. In the AirBrakeNotifier class, which is responsible for calling the server side rest api, the URL for AirBrake is hardcoded whereas I needed to override it for ErrBit. A quick solution was to create a new ErrBitNotifier class which takes the base url a construction argument.

import airbrake.AirbrakeNotice;
import airbrake.NoticeXml;

import java.io.*;
import java.net.*;

public class ErrBitNotifier {

    private final String baseUrl;

    public ErrBitNotifier(String baseUrl) {
        this.baseUrl = baseUrl;
    }

    private void addingProperties(final HttpURLConnection connection) throws ProtocolException {
        connection.setDoOutput(true);
        connection.setRequestProperty("Content-type", "text/xml");
        connection.setRequestProperty("Accept", "text/xml, application/xml");
        connection.setRequestMethod("POST");
    }

    private HttpURLConnection createConnection() throws IOException {
        return (HttpURLConnection) new URL(String.format("http://%s/notifier_api/v2/notices", baseUrl)).openConnection();
    }

    private void err(final AirbrakeNotice notice, final Exception e) {
        e.printStackTrace();
    }

    public int notify(final AirbrakeNotice notice) {
        try {
            final HttpURLConnection toairbrake = createConnection();
            addingProperties(toairbrake);
            String toPost = new NoticeXml(notice).toString();
            return send(toPost, toairbrake);
        } catch (final Exception e) {
            err(notice, e);
        }
        return 0;
    }

    private int send(final String yaml, final HttpURLConnection connection) throws IOException {
        int statusCode;
        final OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
        writer.write(yaml);
        writer.close();
        statusCode = connection.getResponseCode();
        return statusCode;
    }

}

Perhaps the AirBrake API could potentially allow for custom configuration of the URL in the next revision. Once you have created a new ErrBitNotifier you can start publishing exceptions. Going back to our previous example

import airbrake.AirbrakeNotice;
import airbrake.AirbrakeNoticeBuilder;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;

public class TestException {

    private static org.apache.log4j.Logger log = Logger
            .getLogger(TestException.class);

    public static void main(String[] args) {

        File file = new File("h://myfile.txt");
        try {
            boolean fileCreated = file.createNewFile();
            System.out.println("fileCreated = " + fileCreated);
        } catch (IOException e) {
            log.error("Could not create file",e);
            AirbrakeNotice notice = new AirbrakeNoticeBuilder("b4f7cb2020b2972bde2f21788105d645", e, "prod").newNotice();
            ErrBitNotifier notifier = new ErrBitNotifier("ebit.herokuapp.com");
            notifier.notify(notice);
        }

    }
}

This code will throw an IOException (well at least on my computer, since I don’t have a h drive!) and the exception will be seen on the ErrBit console It has the ability to spot duplication of exceptions and you can set it up to email you when the exception is generated.

Also the AirBrake API has log4j appender support but it is tied to the AirBrake public URL and I have left it out of the post. However it can be turned on by the following log4j configuration example

log4j.rootLogger=INFO, stdout, airbrake

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%d,%p] [%c{1}.%M:%L] %m%n

log4j.appender.airbrake=airbrake.AirbrakeAppender
log4j.appender.airbrake.api_key=YOUR_AIRBRAKE_API_KEY
#log4j.appender.airbrake.env=development
#log4j.appender.airbrake.env=production
log4j.appender.airbrake.env=test
log4j.appender.airbrake.enabled=true

Conclusion

Application Exception Monitoring is an important part of your application lifecycle.

Exceptions should be easily visible to the support and development teams and your development process should look to address all exceptions in forthcoming sprints.

Exceptions should be used for exceptional cases only, any exception that is not acted upon in production is noise and creates confusion.

Tool Support is important in this area and ErrBit looks like a great multi-language tool that can help support your Exception Management workflow.

Published at DZone with permission of Diarmuid Moloney, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)