Logging Exceptions

Importance of Logging Exceptions

Logging exceptions is crucial for:

  • Debugging: Helps trace and identify issues during development and after deployment.
  • Monitoring: Keeps track of application behavior and performance.
  • Auditing: Provides a record of events for security and compliance purposes.

The logging Module

Python’s built-in logging module provides a flexible framework for emitting log messages from Python programs. It’s designed to meet the needs of simple scripts as well as complex applications.

Basic Logging Setup

To log exceptions, you first need to set up a logger.

import logging

logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')

Logging an Exception

You can log an exception within an except block using logging.error with exc_info=True to include the traceback.

try:
    result = 10 / 0
except ZeroDivisionError as e:
    logging.error("An error occurred: %s", e, exc_info=True)

Logging Levels

The logging module provides several levels of logging, which indicate the severity of events.

  • DEBUG: Detailed 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.
  • 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.

Customizing Log Output

You can customize the log format to include various details like time, level, and message.

logging.basicConfig(level=logging.ERROR, 
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S')

Using Logger Objects

For more complex applications, it’s beneficial to create logger objects.

logger = logging.getLogger(__name__)
logger.setLevel(logging.ERROR)

try:
    result = 10 / 0
except ZeroDivisionError as e:
    logger.error("Zero Division Error occurred", exc_info=True)

Logging to a File

Instead of logging to the console, you can log to a file by configuring a FileHandler.

file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.ERROR)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)

logger.addHandler(file_handler)

try:
    result = 10 / 0
except ZeroDivisionError as e:
    logger.error("Zero Division Error occurred", exc_info=True)

Rotating Log Files

To avoid a single large log file, you can use RotatingFileHandler to create rotating logs.

from logging.handlers import RotatingFileHandler

rotating_handler = RotatingFileHandler('app.log', maxBytes=2000, backupCount=5)
rotating_handler.setLevel(logging.ERROR)
rotating_handler.setFormatter(formatter)

logger.addHandler(rotating_handler)

try:
    result = 10 / 0
except ZeroDivisionError as e:
    logger.error("Zero Division Error occurred", exc_info=True)