CodeNebula
Python📦Standard Libraryintermediate

`logging` — Structured Logging

Python · Standard Library · Run with python3

Explanation

The `logging` module provides a configurable, hierarchical logging system. Loggers are arranged in a dotted-name hierarchy (`__name__` is idiomatic). Handlers direct log records to outputs (stderr, files, sockets, HTTP). Formatters control the output format. Log levels: DEBUG < INFO < WARNING < ERROR < CRITICAL. Python 3.12 added `logging.getLogger(__name__)` convenience and Python 3.11 added `logging.getLevelNamesMapping()`. Use `structlog` or Python 3.12's `logging.getLogger` for structured JSON logging in production.

Real-World Scenario

A microservice uses one logger per module (`logger = logging.getLogger(__name__)`). A JSON formatter in production emits structured logs that Elasticsearch or Loki can index and search. Log levels control verbosity between development (DEBUG) and production (WARNING). ```python import logging import json import sys class JSONFormatter(logging.Formatter): def format(self, record: logging.LogRecord) -> str: log_entry = { "level": record.levelname, "message": record.getMessage(), "module": record.module, "line": record.lineno, } if record.exc_info: log_entry["exception"] = self.formatException(record.exc_info) return json.dumps(log_entry) logger = logging.getLogger("myapp.service") handler = logging.StreamHandler(sys.stdout) handler.setFormatter(JSONFormatter()) logger.addHandler(handler) logger.setLevel(logging.DEBUG) logger.info("Service started") logger.debug("Connecting to %s", "localhost:5432") try: 1 / 0 except ZeroDivisionError: logger.error("Unexpected error", exc_info=True) ```

Quick Snippet

snippet.py
import logging
import json
import sys

class JSONFormatter(logging.Formatter):
    def format(self, record: logging.LogRecord) -> str:
        log_entry = {
            "level": record.levelname,
            "message": record.getMessage(),
            "module": record.module,
            "line": record.lineno,
        }
        if record.exc_info:
            log_entry["exception"] = self.formatException(record.exc_info)
        return json.dumps(log_entry)

logger = logging.getLogger("myapp.service")
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(JSONFormatter())
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

logger.info("Service started")
logger.debug("Connecting to %s", "localhost:5432")
try:
    1 / 0
except ZeroDivisionError:
    logger.error("Unexpected error", exc_info=True)

Full Example

logging_basics.py
# Compile: python3 logging_basics.py
# Output:
# JSON log lines printed to stdout

import logging
import json
import sys

class JSONFormatter(logging.Formatter):
    def format(self, record: logging.LogRecord) -> str:
        log_entry = {
            "level": record.levelname,
            "message": record.getMessage(),
            "module": record.module,
        }
        if record.exc_info:
            log_entry["exception"] = self.formatException(record.exc_info)
        return json.dumps(log_entry)

logger = logging.getLogger("myapp.service")
# Clear any existing handlers to avoid duplicate output in tests
logger.handlers.clear()
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(JSONFormatter())
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.propagate = False

logger.info("Service started")
logger.debug("Connecting to %s", "localhost:5432")

try:
    1 / 0
except ZeroDivisionError:
    logger.error("Unexpected division error", exc_info=True)
Run command
python3 logging_basics.py