Core Logging Module

Package: structum-core (modules structum.logging)
Status: Core Protocol
Dependencies: Zero (Python Standard Library only)


Overview

[!NOTE] Architectural Role: This module is part of the Foundation Layer.
See Enterprise Architecture Guide for the full architectural map.

The Core Logging module defines the Logging Protocols that all Structum applications use. It provides zero-dependency interfaces that allow applications to log without caring about the underlying implementation (stdout, file, JSON, ELK, etc.).

By coding against these interfaces, your application remains:

  1. Testable: Easy to mock logging in unit tests

  2. Portable: No hard dependencies on specific libraries

  3. Modular: The logging backend can be swapped at any time


LoggerInterface

The primary contract is the LoggerInterface protocol. It extends standard Python logging with support for structured context (**kwargs).

class LoggerInterface(Protocol):
    def debug(self, message: str, **kwargs: Any) -> None: ...
    def info(self, message: str, **kwargs: Any) -> None: ...
    def warning(self, message: str, **kwargs: Any) -> None: ...
    def error(self, message: str, **kwargs: Any) -> None: ...
    def critical(self, message: str, **kwargs: Any) -> None: ...

Key Features

  1. StructuredByDefault: All methods accept arbitrary keyword arguments.

  2. Runtime Checkable: Supports isinstance(logger, LoggerInterface).

  3. Type Safe: Fully typed for Mypy compliance.


Usage

Getting a Logger

Use the global factory function to get a logger conforming to the interface.

from structum.logging import get_logger

# Returns a logger implementing LoggerInterface
logger = get_logger(__name__)

Logging Structured Data

Do not format strings! Pass data as keyword arguments.

DO:

logger.info("user_login", user_id=123, status="success")

DON’T:

# Bad: Hard to parse, hard to index
logger.info(f"User {123} logged in with status success")

Exception Logging

Pass exc_info=True to include stack traces.

try:
    risky_operation()
except Exception:
    logger.error("operation_failed", exc_info=True)

Architecture: Core vs. Plugin

Feature

Core Logging (structum-core)

Observability Plugin (structum-observability)

Role

Interface definition

Implementation

Dependencies

None (stdlib)

structlog, opentelemetry

Output

Basic console (fallback)

JSON, Colors, Context Propagation

Context

Definitions only

full log_context management

[!TIP] Use the Core interface in your business logic.
Only use the Plugin when you need to configure the backend or use advanced observability features like tracing context injection.


Extending

To create a custom logging backend, implement the protocol:

from structum.logging.interfaces import LoggerInterface

class MyCustomLogger(LoggerInterface):
    def info(self, message: str, **kwargs: Any) -> None:
        print(f"[MYLOG] {message} {kwargs}")
        
    # ... implement other methods