Constructing Helpful Log Messages

under construction This post is a work in progress, and may be updated at some point in the potentially distant future!

I saw this post on hacker news and wanted to share my thoughts on error messaging (not in rust, but in a more general sense). In rust, this can be tackled by wrapping errors inside other errors.

When logging an error to the console, which one seems more useful?:

expected byte {, found ","
error: config load: json parse error: at index: 32, expected "{", found ","

For most languages, it’s relatively easy to build error types and strings so that your messaging is helpful. In a lot of cases, such as with python, you can make custom error types which can stringify to a helpful message like the ones in this document.

Important Pieces:

  1. Class of message We need to be clear if this log is an error the user needs to care about. Most logging libraries have independent levels debug, info, trace which can be filtered, and the level automatically printed. Some of these even inject (or can inject) filenames / line numbers, which is cool too if you aren’t good at finding things.

  2. High-Level Module This can be accomplished by auto-printed filenames, but I usually try to include the high-level task that’s occurring beyond just the module. In the above example, config load: is the string under this category. That way, it’s easy to tell what is actually meaningful to something you’re debugging.

  3. Error Type This is the kind of error you’re experiencing - for this could be a string, or error type if your language’s error handling supports it. In the above example, this is the json parse error: bit.

  4. Error Context This includes error context. In the case of a failed system call, this should probably be the error code / messaging, if parsing / validating inputs, this should be information on what was expected vs. what was found. next at index: 32, expected "{", found "," - context on exactly what went wrong, and how to fix it.

  5. Fix Info If this error is caused by something the user can correct (incorrect config, or something related), it may be useful to append a string explaining what they can do to fix this in (concise) plain english.

This section may or may not be desired depending on the audience for your log output. If producing a command line tool to be used by the software community at large, this section may be useful for people who are new/getting used to your tool.

Sometimes this isn’t needed, as the context also explains the fix.

More Examples

you might log more things like this:

error: config: validation error: no bind address specified. Specify this via the --bind-addr command line flag.
error: newsletter-subscribe: failed to send email: the upstream service responded with status code 503.
error: blog: failed to load post: connection timeout. Is your network connected?
warning: auth: the current user does not have 2FA enabled.
info: config: consider enabling the `content-security-policy` flag.

The format

<log type>: <module/task>: <error type>: <error context> <fix info?>

Change Log

  • 12/12/2020 - Initial Revision

Found a typo or technical problem? file an issue!