Real men test in production



Logging


Created: 2024-03-17 | Modified: 2024-11-02

Python logging with ✨pretty colors🌸

Logging > print

Logging is useful, because all python code can use the same standard, allowing you to centrally control:

A python "module" is simply just the name for a .py file. e.g. the file database_handler.py is a module called database_handler

import logging


class ColorFormatter(logging.Formatter):
    grey = "\x1b[90;20m"
    cyan = "\x1b[96;20m"
    yellow = "\x1b[33;20m"
    red = "\x1b[31;20m"
    bold_red = "\x1b[31;1m"
    reset = "\x1b[0m"
    format = "%(asctime)s,%(msecs)03d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s"

    FORMATS = {
        logging.DEBUG: grey + format + reset,
        logging.INFO: cyan + format + reset,
        logging.WARNING: yellow + format + reset,
        logging.ERROR: red + format + reset,
        logging.CRITICAL: bold_red + format + reset
    }

    def format(self, record):
        log_fmt = self.FORMATS.get(record.levelno)
        formatter = logging.Formatter(log_fmt)
        return formatter.format(record)


logger = logging.getLogger(__name__)  # Instantiate a logger to be used in this module

# Display every message Change this to INFO to see INFO and above (filter out DEBUG)
# See: https://docs.python.org/3/howto/logging.html#logging-levels
logger.root.setLevel(logging.DEBUG)

stream_handler = logging.StreamHandler()  # This catches and handles log messages on the root handler
stream_handler.setFormatter(ColorFormatter())
logger.root.addHandler(stream_handler)

logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical message")

Code snippet is modified, but based on: stackoverflow.com - How can I color Python logging output?. Used and credited as per stackoverflow.com - CC BY-SA 4.0 content license

$ python /tmp/1.py
2024-03-17 14:09:06,411,411 DEBUG    [1.py:37] debug message
2024-03-17 14:09:06,411,411 INFO     [1.py:38] info message
2024-03-17 14:09:06,411,411 WARNING  [1.py:39] warning message
2024-03-17 14:09:06,411,411 ERROR    [1.py:40] error message
2024-03-17 14:09:06,411,411 CRITICAL [1.py:41] critical message

In subsequent modules, do the following:

import logging

logger = logging.getLogger(__name__) # Set the logger name, to the name of the module

logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical message")

Wish to change the colors? Color codes can be found here: wikipedia.org - ANSI escape codes

Okay, but why do we need to do it this way?

Because logging is hieratical, these 2 loggers will be siblings under the root logger (see following tree structure). Therefore we set a handler on the root logger which ensures all logging will hit our formatting code.

$ root
├──  main
└──  module_a

You can set a breakpoint and inspect logger.parent to see this structure:

>>> logger.parent
<RootLogger root (DEBUG)>

Read more: docs.python.org - Logging HOWTO


Comments













(Will await approval before becoming public)