Skip to content

13. How to Use Logging with the Python logging Module

Overview

The Python logging module is a standard library for recording application events, diagnostics, and runtime information in a structured and configurable manner. It provides a flexible framework to emit log messages with different severity levels, route them to multiple destinations, and control formatting and filtering. Common use cases include application debugging, operational monitoring, audit trails, and incident analysis in both development and production environments.

Logging Architecture

Core Concepts

The logging system is built around a small set of composable components, each with a clear responsibility.

Component Description Responsibility Scope
Logger Entry point used by application code to emit log records Application or module-level
LogRecord Data structure representing a single logging event Internal
Handler Destination that processes and outputs log records Output routing
Formatter Defines the textual representation of a log record Presentation
Filter Provides fine-grained control over which records are processed Conditional processing

Severity Levels

Logging levels define the importance of a message and are used for filtering.

Level Numeric Value Intended Usage
DEBUG 10 Detailed diagnostic information
INFO 20 High-level application flow
WARNING 30 Unexpected events that do not stop execution
ERROR 40 Failures affecting a specific operation
CRITICAL 50 Severe failures requiring immediate attention

Basic Configuration

Minimal Setup

The logging module can be configured with a basic setup suitable for simple scripts.

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s %(message)s"
)

logging.info("Application started")

This configuration routes log messages to standard output using a default handler.

Note

When to use basicConfig Use basicConfig only for simple applications or entry points. Libraries should not call basicConfig to avoid overriding host application logging behavior.

Configuration

There are 3 basic type of method of configuration 1

flowchart LR
lc[logging.config method]
lc --> d[dictConfig] --> dm[Using JSON to declare schema] --> dr[Can use json package read]
lc --> f[fileConfig] --> fm[Using logging.ini to declare schema] --> fr[Use configparser to read]
lc --> l[listen] --> s[Socket Mode]
lc --> k[stopListening] --> s
s --> o[Handle in raw test on the script]

The method with dict or file is familar together and can switch. But from the note of element, there are various differnt which the lower API in the backend.

Note The fileConfig() API is older than the dictConfig() API and does not provide functionality to cover certain aspects of logging. For example, you cannot configure Filter objects, which provide for filtering of messages beyond simple integer levels, using fileConfig(). If you need to have instances of Filter in your logging configuration, you will need to use dictConfig(). Note that future enhancements to configuration functionality will be added to dictConfig(), so it"s worth considering transitioning to this newer API when it"s convenient to do so.

Logger Usage Pattern

Creating and Using Loggers

Each module should create its own logger using a hierarchical naming convention.

import logging

logger = logging.getLogger(__name__)

logger.debug("Debug message")
logger.info("Informational message")
logger.error("Error message")

Logger names form a hierarchy based on dot notation, enabling centralized control.

Execution Flow

Logging Event Lifecycle

The logging process follows a deterministic sequence.

(1) Application code calls a logger method with a severity level and message (2) The logger creates a LogRecord containing contextual metadata (3) The logger checks the effective logging level to decide if processing continues (4) Applicable filters are evaluated (5) The LogRecord is passed to one or more handlers (6) Each handler formats the record using its formatter (7) The formatted message is emitted to the configured destination

Handlers and Outputs

Common Handler Types

Handler Type Output Destination Typical Use Case
StreamHandler Console or standard streams Development and debugging
FileHandler Local file Persistent application logs
RotatingFileHandler File with size-based rotation Disk space management
TimedRotatingFileHandler File with time-based rotation Daily or hourly log files

Handler Configuration Example

import logging
from logging.handlers import RotatingFileHandler

handler = RotatingFileHandler(
    "app.log",
    maxBytes=10_000_000,
    backupCount=5
)

formatter = logging.Formatter(
    "%(asctime)s %(levelname)s %(name)s %(message)s"
)

handler.setFormatter(formatter)

logger = logging.getLogger("app")
logger.setLevel(logging.INFO)
logger.addHandler(handler)

Warning

Production readiness check Ensure log rotation is configured for file-based handlers to prevent unbounded disk usage.

Formatters and Structured Output

Log Message Structure

Formatters control which attributes from the LogRecord are included.

Common attributes include: (1) asctime (2) levelname (3) name (4) message (5) process (6) thread

Structured logging can be implemented by emitting JSON-formatted messages, but this requires custom formatters or third-party libraries.

Formatter instances are used to convert a LogRecord to text.

Formatters need to know how a LogRecord is constructed. They are responsible for converting a LogRecord to (usually) a string which can be interpreted by either a human or an external system. The base Formatter allows a formatting string to be specified. If none is supplied, the style-dependent default value, "%(message)s", "{message}", or "${message}", is used.

The Formatter can be initialized with a format string which makes use of
knowledge of the LogRecord attributes - e.g. the default value mentioned
above makes use of the fact that the user's message and arguments are pre-
formatted into a LogRecord's message attribute. Currently, the useful
attributes in a LogRecord are described by:

%(name)s            Name of the logger (logging channel)
%(levelno)s         Numeric logging level for the message (DEBUG, INFO,
                    WARNING, ERROR, CRITICAL)
%(levelname)s       Text logging level for the message ("DEBUG", "INFO",
                    "WARNING", "ERROR", "CRITICAL")
%(pathname)s        Full pathname of the source file where the logging
                    call was issued (if available)
%(filename)s        Filename portion of pathname
%(module)s          Module (name portion of filename)
%(lineno)d          Source line number where the logging call was issued
                    (if available)
%(funcName)s        Function name
%(created)f         Time when the LogRecord was created (time.time()
                    return value)
%(asctime)s         Textual time when the LogRecord was created
%(msecs)d           Millisecond portion of the creation time
%(relativeCreated)d Time in milliseconds when the LogRecord was created,
                    relative to the time the logging module was loaded
                    (typically at application startup time)
%(thread)d          Thread ID (if available)
%(threadName)s      Thread name (if available)
%(process)d         Process ID (if available)
%(message)s         The result of record.getMessage(), computed just as
                    the record is emitted

Best Practices and Limitations

Operational Guidelines

(1) Do not use the root logger directly in application modules (2) Avoid excessive DEBUG logging in production environments (3) Treat log messages as immutable audit data (4) Never log sensitive information such as credentials or personal data

Limitations

(1) The standard logging module does not provide native JSON logging (2) Distributed tracing correlation requires manual context propagation (3) Misconfigured logger hierarchies can result in duplicate log entries

Tip

Actionable setup checklist

(1) Define a global logging policy at application startup

(2) Standardize log formats across services

(3) Validate logging behavior in both development and production environments

Reference