Customer: Your app crashed again.
Developer: How? What were you doing when it crashed? What happened?
Customer: I don't know. I was playing with it and it crashed.
Developer: Do you remember which page you were on?
Developer: bangs head against wall
One of the first things I do when I start a project (or when I inherit one) is set up logging. You'd be amazed and depressed at how many projects just don't have any, or bolt it on as an after thought. Here's a hint: it's much easier to debug your app while you're developing it if you know where it's breaking. Ground-breaking, I know
There are a couple of things we want to do:
1. Log when the app crashes. Do it quickly and reliably, and don't rely on any app infrastructure (e.g. injected loggers) as it's already been torn down at this point. 2. Send the log message the next time the app starts. This will allow us to use all our nice web services etc. and means we can use just the one logging mechanism rather than having several different ones. MonoDevelop creates a fairly standard-looking Main.cs for us:
Let's change that to add a simple try/catch block:
The key here is line 11 - it makes it simple and obvious as to what it's doing.
So... the CrashLog class itself is a static class and doesn't do very much at all. The idea is that it's simple to call and doesn't rely on having any of the app's components still available.
We're using the My Documents special folder as that's where we're reliably allowed to write things to on the filesystem.
So now that we have our crash logger, let's hook things up so that we can log when the app starts again. In our AppDelegate class:
Yes, we're using our IoC container as a service locator. This isn't good, but we can't use constructor injection in our AppDelegate as it's the class responsible for creating our IoC container.
So how does the logger work? Well, that's up to you. You can choose to make a web-service call; you could spit it to another text file and periodically upload it; you could even send an email if you really wanted to.
My preference is using a web service as I tend to just hook it straight to the server-side logger (which usually uses log4net under the covers), but your mileage may vary.
The next time a customer tells you that your app crashed, though, you'll be able to respond with, "I know - and I've already fixed that bug."