Recording errors is an important part of error handling. In short, when certain errors occur in programs, you want to know about it. This is particularly important with bugs.
You need to:
- know that they occurred
- have useful information about them so you can debug them later
One way to do this is to use an error monitoring or logging service. Some examples are New Relic and Splunk. These will automatically record any program errors and such.
In particular, logging is very useful. It records a lot of information about what’s happening in your program. This can help a lot with debugging.
Alternatively, you can manually record information about errors.
How to manually record errors
The goal is to be able to view errors later. You can achieve that in any number of ways.
One way is to manually record errors in a database.
To do this, you can:
- prepare your database for recording errors
- set up some code to record errors to the database
- set up a global error handler to catch errors. (This error handler would call the code from step 2)
- set up an endpoint in the back end so the front end can record errors too. (This endpoint would call the code from step 2)
For example, you might use a MongoDB database with a collection for errors. Every time an error occurs in your application, add information about it to the collection. You can organise the information in any way you like. For example, you could organise by the type of error or exception, by the error message, or by the last code in the call stack for the error.
After setting that up, you could set up a global error handler. This error handler would be called on errors that occur in your application. In the handler, record the error in your database.
Different frameworks and "environments" provide different ways to set up global error handlers. For example, in the Unity game engine, you can use Application.logMessageReceived += Handler;
. On the front end of a website, you can use window.addEventListener('error', handler);
.
Finally, you can set up an endpoint so that the front end can record errors too. Then, the front end can make a network request with information about the error it encountered.
Here’s an example call you could make from the front end:
function handleError(errorEvent) {
const {error} = errorEvent;
const data = {stack: error.stack, message: error.message, type: error.name};
fetch('https://example.com/errors', {method: 'POST', body: JSON.stringify(data)});
}
window.addEventListener('error', handleError);
The function handleError
above is executed any time an error occurs. It creates an object with useful information about the error. Then, it sends a network request to the back end. The back end will then record the information about the error so it can be viewed later.
What information to record
You want as much useful information about the error as possible. This will help you debug it later.
The article .NET best practices on exceptions has some guidelines for this. Adapted for both error values and exceptions, they are to:
- use the predefined error types in your programming language if they’re relevant. Only create custom types if the predefined ones don’t apply.
- if you create custom error types:
- they should usually be subclasses of the main error types (if you use an OOP language)
- they can optionally have custom properties (if they would be useful)
- use grammatically correct error messages. For example ‘The file "foo.txt" could not be found.’.
- include a localised string message in every error (if your application is localised)
Final notes
So that’s it for this article. I hope that you found it useful.
As always, if any points were missed, or if you disagree with anything, or have any comments or feedback then please leave a comment below.
For the next steps, I recommend looking at the other articles in the error handling series.
Alright, thanks and see you next time.
Credits
Recording photo – Photo by Krists Luhaers on Unsplash