Python logging Module

The logging module provides a flexible framework for emitting log messages from Python programs. It supports multiple output destinations, configurable severity levels, and structured formatting.

Use Cases:
- Recording application events for debugging and monitoring
- Separating debug, info, warning, and error messages by severity
- Writing logs to files, console, network sockets, or external services
- Configuring different log levels for different modules
- Structured logging for production observability

Example 1: Basic logging setup
    import logging

    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S"
    )
    logger = logging.getLogger(__name__)

    logger.info("Application started")
    logger.warning("Disk usage above 80%%")
    logger.error("Failed to connect to database")

Example 2: File and console logging
    import logging

    logger = logging.getLogger("myapp")
    logger.setLevel(logging.DEBUG)

    file_handler = logging.FileHandler("app.log")
    file_handler.setLevel(logging.DEBUG)

    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.WARNING)

    formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
    file_handler.setFormatter(formatter)
    console_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)

The logging module follows a hierarchy: loggers propagate messages to parent loggers. The root logger is the ultimate parent. Handlers determine where messages go, while formatters control the output format. Filters provide fine-grained control over which records are emitted.
