Advanced Logging

Aidanmc
2 min readNov 8, 2020

While it is nice to be able to look at what went wrong easily, the organization of it is important. There are some built-in tools that allowed us to more easily organize where information is placed. These tools are loggers, handlers, formatters, and configuration logging.

Loggers

Logger objects are used to split up how certain messages are handled. They have three many jobs: exposing methods for the application, determine which messages are handled, and pass messages to their appropriate destination.

How we interact with a logger object starts with getLogger() this allows us to get the object to properly set up the loggers. From here we are able to change how the logger is set up using the methods within:

  • Logger.setLevel() specifies the lowest-severity log message a logger will handle, where debug is the lowest built-in severity level and critical is the highest built-in severity. These follow the same levels as started before.
  • Logger.addHandler() and Logger.removeHandler() add and remove handler objects from the logger object. The handler needs to be added to allow for the message to be sent to the right place. Multiple handlers can be set for a logger.

Handlers

Handler objects are responsible for actually patching the message through to where they need to go. Multiple handlers can be set on the same logger. This allows for messages to be shifted to different places depending on the severity.

Handler objects are responsible for dispatching the appropriate log messages (based on the log messages’ severity) to the handler’s specified destination. Logger objects can add zero or more handler objects to themselves with an addHandler() method. As an example scenario, an application may want to send all log messages to a log file, all log messages of error or higher to stdout, and all messages of critical to an email address. This scenario requires three individual handlers where each handler is responsible for sending messages of a specific severity to a specific location.

  • The setLevel() method, just as in logger objects, it is a bit redundant but this allows us to change where the message is going dependent on the severity.
  • setFormatter() selects a Formatter object for this handler to use.

Formatter

The formatter object is used to configure the structure and contents of the log message. The way that we can do this is by using the logging.Formatter.__init__(fmt=None, datefmt=None) function. For strings you can formater the messages with:

'%(asctime)s - %(levelname)s - %(message)s'

While for dates you can use:

%Y-%m-%d %H:%M:%S

Configuring Logging

While the configuring logs don’t store a lot of data this data can be extremely helpful. The log lets you know how all logger objects are set up. This allows us to easily look up and fix any incorrect logger that has been set up. It also allows us to know which logger to use at different points.

--

--