I just published a release of my open source TFS Test Steps Editor project that can now report application errors to me. To accomplish this, I developed a very simple error reporting service hosted at AppHarbor. When an unhandled exception occurs, a dialog appears offering to report the error. When the user confirms, the exception dump is posted to my cloud service which saves it to a database and emails it to me. Below is a rundown of the steps I took to quickly get it up and running.
The service is hosted in an ASP.NET MVC 4 application. It has a single
ErrorReportingController with a a single POST endpoint
Report that accepts only a string for the error report body. When the API is called, the error report is stored in RavenDB via the RavenHQ cloud service and emailed to me via SendGrid. The great thing is that the only thing deployed with my app is logic - storage and email are all handled by services.
The following sections provide a rough outline of the steps required to get it all working. I consider this spike a “proof of concept,” as it has plenty of hard-coded constants and no unit tests (which I would accomplish via injection of the SendGrid dependency and use of the in-memory RavenDB server).
Set up the required services
- Sign up for an AppHarbor account and create an application.
- Set up AppHarbor to build and deploy the solution when it is pushed to GitHub. Note that AppHarbor will automatically detect which project should be deployed, as long as the solution contains only a single Web Application.
- Add the RavenHQ (for storing error reports) and SendGrid (for emailing error reports) add-ons. Note that this adds entries in the Configuration variables section for the RavenDB connection string and SendGrid username and password.
ErrorReportingController.Report method looks like this:
1 2 3 4 5 6 7 8
The code for sending an email creates a SendGrid email message and delivers it using the
SendGridMail.Transport.REST API. The API requires a username and password, which I load from Web.config. AppHarbor automatically pushes these values into Web.config when you deploy, so these values are only stored securely with your AppHarbor account and live as dummy values in source control:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
The code for persisting the error report creates an
ErrorReport instance, opens a RavenDB session, and stores the error report:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Note the use of
MvcApplication.Store. This is simply a static property defined on the
MvcApplication class in
Global.asax.cs and initialized in
Application_Startusing the Web.config appSettings value automatically set by AppHarbor.
Hooking unhandled exceptions and sending error reports
The final piece is the actual sending of error reports. TFS Test Steps Editor is a Windows Forms application, so I use the following code in the
Program.Main method to get access to unhandled exceptions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
The lock and guard ensures that we don’t enter an infinite loop if an exception occurs while sending the error report.
The ExceptionReporter class logs the exception and presents a dialog asking whether the user wants to email an exception report. If the user confirms, my Error Reporting service is called. Here is the relevant snippet. The logBody variable is a string set by flushing the current NLog file and then reading its text:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
This was a fun exercise that let me explore the integration of several cloud services while providing some value to my end users. I’ve already received several error reports that I can turn into tangible improvements in the TFS Test Steps Editor. Making it easy for your users to report errors lets them help each other. There is a class of “annoying but I can get around it” error that often goes unreported, but in aggregate causes a lot of pain.
AppHarbor makes things really easy. While its UI is not as slick or modern as Azure’s, I find it more intuitive to use than the Azure Web Sites featured, mostly because there are fewer knobs to twiddle. Obviously Azure provides a lot more out of the box, but for these simple purposes, AppHarbor is a perfect fit. And if you need some of the features that Azure has out-of-box, the AppHarbor add-on ecosystem is quite rich, not to mention the bevy of other cloud services that are easily integrated even without a native add-on.
After implementing this minimal, non-configurable service, I have been inspired to develop a generic, open service that could be used by other developers. Development of that service has begun in my GitHub repo and is being tested at http://errorgun.apphb.com.