Table of Contents
Logging
Once our application grows beyond a basic project, having good logging as oppose to just print statement is going to allow us to look at behaviors and errors over time and give us a better overall picture of what's going on.
There are 5 different kinds of logging levels. Levels allow us to to specify exactly what we want to log by separating them into categories. The description of each of these is as follows:
DEBUG
: Detailed debug information, typically of interest only when diagnosing problems.INFO
: Confirmation that things are working as expected.WARNING
: An indication that something unexpected happened, or indicative of some problem in the near future (e.g. disk space low). The software is still working as expected.ERROR
: Due to a more serious problem, the software has not been able to perform some function.CRITICAL
: A serious error, indicating that the program itself may be unable to continue running.
The default level is WARNING, meaning that it will capture anything that is a warning or above, and ignore the DEBUG and INFO level. we can change this behavior using the basicConfig method.
After running the code, we should a logging file in the same directory as the notebook. And it should something along the lines of:
The code chunk logs the information in the root logger. If we have multiple scripts that does the logging, they will get logged to the same place, which might not be ideal. Thus we can create a separate logger for each module.
Logging Exception
In the previous section, we've were logging the exception to the log file. This is actually an important practice and should not be taken lightly.
When using try and except to catch exceptions, we should be more diligent in the way we handle the exceptions. In other words, NEVER do the following:
It might be quick for us as a developer to simply ignore the exception so that we can move on with our life and not worry about dealing with the exception. But when we do this, it is actually doing a massive disservice as it not only swallows up the various errors that might occur, even the ones we weren't expecting when writing try, expect block, but also throws away the stack trace, which provides useful information to speed up our bugging process when an error occurs.
This is not to say that we should not be using try and expect to catch Exception, as this ensures our critical or long-running process doesn't go down due to some unexpected error. It is to enforce the fact that we should not be silently swallowing the error.
The solution to this is to use a more specific exception type and log the full stack trace. In the function we've defined, we:
Use the
ZeroDivisionError
to specify what errors we were expecting when writing the try, except block.We also leverage logging object's exception method.
If for some reason, our application does logging in some other way, then we can use the trackback module to format the exception's stack trace.
The bottom line is do log the full stack trace if we decide to use the try, except pattern in our codebase. This ensures we get as much information as possible when an unexpected error occurs, which significantly speeds up the debugging process.
Apart from the base logging module, there are projects like logzero that tries to make it less tedious to setup the logs.