Logging Handler

Rich supplies a logging handler which will format and colorize text written by Python’s logging module.

Here’s an example of how to set up a rich logger:

import logging
from rich.logging import RichHandler

FORMAT = "%(message)s"
logging.basicConfig(
    level="NOTSET", format=FORMAT, datefmt="[%X]", handlers=[RichHandler()]
)

log = logging.getLogger("rich")
log.info("Hello, World!")

Rich logs won’t render Console Markup in logging by default as most libraries won’t be aware of the need to escape literal square brackets, but you can enable it by setting markup=True on the handler. Alternatively you can enable it per log message by supplying the extra argument as follows:

log.error("[bold red blink]Server is shutting down![/]", extra={"markup": True})

Similarly, the highlighter may be overridden per log message:

log.error("123 will not be highlighted", extra={"highlighter": None})

Handle exceptions

The RichHandler class may be configured to use Rich’s Traceback class to format exceptions, which provides more context than a built-in exception. To get beautiful exceptions in your logs set rich_tracebacks=True on the handler constructor:

import logging
from rich.logging import RichHandler

logging.basicConfig(
    level="NOTSET",
    format="%(message)s",
    datefmt="[%X]",
    handlers=[RichHandler(rich_tracebacks=True)]
)

log = logging.getLogger("rich")
try:
    print(1 / 0)
except Exception:
    log.exception("unable print!")

There are a number of other options you can use to configure logging output, see the RichHandler reference for details.

Suppressing Frames

If you are working with a framework (click, django etc), you may only be interested in seeing the code from your own application within the traceback. You can exclude framework code by setting the suppress argument on Traceback, install, and Console.print_exception, which should be a list of modules or str paths.

Here’s how you would exclude click from Rich exceptions:

import click
import logging
from rich.logging import RichHandler

logging.basicConfig(
    level="NOTSET",
    format="%(message)s",
    datefmt="[%X]",
    handlers=[RichHandler(rich_tracebacks=True, tracebacks_suppress=[click])]
)

Suppressed frames will show the line and file only, without any code.