Structured logging for Python that emphasizes simplicity, power, and performance
npx @tessl/cli install tessl/pypi-structlog@25.4.0Structured logging for Python that emphasizes simplicity, power, and performance. Structlog uses a function-based approach where everything revolves around functions that take and return dictionaries, all hidden behind familiar APIs. It offers flexible output formatting with built-in support for JSON, logfmt, and pretty console output, while allowing users to choose whether structlog handles log output directly or forwards entries to existing logging systems.
pip install structlogimport structlogCommon usage patterns:
# For basic configuration and logger creation
from structlog import configure, get_logger
# For specific components
from structlog import processors, dev, stdlib, testing
# For context management - import specific functions
from structlog.contextvars import bind_contextvars, get_contextvars, bound_contextvars
# For development tools
from structlog.dev import ConsoleRenderer
# For testing
from structlog.testing import capture_logs, ReturnLoggerFactoryimport structlog
# Configure structlog (typically done once at application startup)
structlog.configure(
processors=[
structlog.processors.TimeStamper(fmt="iso"),
structlog.dev.ConsoleRenderer()
],
wrapper_class=structlog.stdlib.BoundLogger,
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=True,
)
# Get a logger
logger = structlog.get_logger()
# Use the logger with structured data
logger.info("User logged in", user_id=123, username="alice")
# Bind context that persists across log calls
logger = logger.bind(user_id=123, session_id="abc-def")
logger.info("Action performed", action="file_upload")
logger.warning("Rate limit approaching", remaining_requests=5)
# Create new logger with cleared context
logger = logger.new(request_id="xyz-789")
logger.error("Processing failed", error_code="INVALID_INPUT")Structlog's architecture is built around three key concepts:
The design allows maximum flexibility - you can use structlog as a pure structured logging library, integrate it with Python's standard logging module, or adapt it to any existing logging system.
Global configuration system for setting up processors, logger factories, and wrapper classes. Controls how structlog initializes loggers and processes log events throughout the application.
def configure(
processors=None,
wrapper_class=None,
context_class=None,
logger_factory=None,
cache_logger_on_first_use=None
) -> None: ...
def configure_once(**kwargs) -> None: ...
def get_config() -> dict[str, Any]: ...
def is_configured() -> bool: ...
def reset_defaults() -> None: ...Core functions for creating and wrapping loggers, providing the main entry points for getting configured logger instances and wrapping existing loggers.
def get_logger(*args, **initial_values) -> Any: ...
def getLogger(*args, **initial_values) -> Any: ...
def wrap_logger(
logger,
processors=None,
wrapper_class=None,
context_class=None,
cache_logger_on_first_use=None,
logger_factory_args=None,
**initial_values
) -> Any: ...Immutable context-carrying logger classes that provide the core structlog API with context binding, unbinding, and delegation to wrapped loggers.
class BoundLoggerBase:
def bind(**new_values) -> Self: ...
def unbind(*keys) -> Self: ...
def try_unbind(*keys) -> Self: ...
def new(**new_values) -> Self: ...
class BoundLogger(BoundLoggerBase): ...
def get_context(bound_logger) -> Context: ...Extensible pipeline of functions that transform, filter, and format log events. Includes built-in processors for timestamps, JSON/logfmt rendering, exception handling, and more.
class TimeStamper:
def __init__(self, fmt=None, utc=True, key="timestamp"): ...
def __call__(self, logger, name, event_dict) -> EventDict: ...
class MaybeTimeStamper:
def __init__(self, fmt=None, utc=True, key="timestamp"): ...
def __call__(self, logger, name, event_dict) -> EventDict: ...
class JSONRenderer:
def __init__(self, serializer=json.dumps, **dumps_kw): ...
def __call__(self, logger, name, event_dict) -> str | bytes: ...
class LogfmtRenderer:
def __init__(self, key_order=None, drop_missing=False, repr_native_str=True): ...
def __call__(self, logger, method_name, event_dict) -> str: ...
class KeyValueRenderer:
def __init__(self, sort_keys=False, key_order=None, drop_missing=False, repr_native_str=True): ...
def __call__(self, logger, method_name, event_dict) -> str: ...
class ExceptionPrettyPrinter:
def __init__(self, file=None): ...
def __call__(self, logger, name, event_dict) -> EventDict: ...Rich console output, colored logging, column formatting, and advanced traceback rendering designed for development environments and debugging.
class ConsoleRenderer:
def __init__(
self,
pad_event=30,
colors=True,
force_colors=False,
repr_native_str=False,
level_styles=None,
exception_formatter=...,
sort_keys=True,
event_key="event",
timestamp_key="timestamp",
columns=None,
pad_level=True
): ...
def __call__(self, logger, name, event_dict) -> str: ...Complete integration with Python's standard logging module, including stdlib-compatible loggers, formatters, and processors for bridging structlog with existing logging infrastructure.
class BoundLogger(BoundLoggerBase):
def debug(self, event=None, **kw) -> None: ...
def info(self, event=None, **kw) -> None: ...
def warning(self, event=None, **kw) -> None: ...
def error(self, event=None, **kw) -> None: ...
def critical(self, event=None, **kw) -> None: ...
def exception(self, event=None, **kw) -> None: ...
class AsyncBoundLogger:
async def adebug(self, event: str, *args, **kw) -> None: ...
async def ainfo(self, event: str, *args, **kw) -> None: ...
async def awarning(self, event: str, *args, **kw) -> None: ...
async def aerror(self, event: str, *args, **kw) -> None: ...
async def acritical(self, event: str, *args, **kw) -> None: ...
async def aexception(self, event: str, *args, **kw) -> None: ...
class ProcessorFormatter(logging.Formatter):
def __init__(self, processor, foreign_pre_chain=None, keep_exc_info=False, keep_stack_info=False): ...
def format(self, record) -> str: ...Thread-safe context binding using contextvars and deprecated thread-local storage, enabling global context that persists across function calls and async boundaries.
def get_contextvars() -> dict[str, Any]: ...
def bind_contextvars(**kw) -> Mapping[str, contextvars.Token[Any]]: ...
def clear_contextvars() -> None: ...
def unbind_contextvars(*keys) -> None: ...
def bound_contextvars(**kw) -> Generator[None, None, None]: ...
def merge_contextvars(logger, method_name, event_dict) -> EventDict: ...Comprehensive testing support including log capture, return loggers, and utilities for asserting on structured log output in test suites.
class ReturnLogger:
def msg(self, *args, **kw): ...
class CapturingLogger:
calls: list[CapturedCall]
def capture_logs() -> Generator[list[EventDict], None, None]: ...
class LogCapture:
entries: list[EventDict]
def __call__(self, logger, method_name, event_dict) -> NoReturn: ...Direct file output loggers that bypass standard logging infrastructure for high-performance logging scenarios and simple output requirements.
class PrintLogger:
def __init__(self, file=None): ...
def msg(self, message: str) -> None: ...
class WriteLogger:
def __init__(self, file=None): ...
def msg(self, message: str) -> None: ...
class BytesLogger:
def __init__(self, file=None): ...
def msg(self, message: bytes) -> None: ...
class PrintLoggerFactory:
def __init__(self, file=None): ...
def __call__(self, *args) -> PrintLogger: ...
class WriteLoggerFactory:
def __init__(self, file=None): ...
def __call__(self, *args) -> WriteLogger: ...
class BytesLoggerFactory:
def __init__(self, file=None): ...
def __call__(self, *args) -> BytesLogger: ...Advanced exception processing including structured traceback extraction, rich formatting, and JSON-serializable exception representations.
class ExceptionDictTransformer:
def __init__(
self,
show_locals=True,
locals_max_length=10,
locals_max_string=80,
locals_hide_dunder=True,
locals_hide_sunder=False,
suppress=(),
max_frames=50,
use_rich=True
): ...
def __call__(self, exc_info) -> list[dict[str, Any]]: ...
def extract(exc_type, exc_value, traceback, **kwargs) -> Trace: ...# Type aliases
WrappedLogger = Any # Logger wrapped by bound logger
Context = Union[Dict[str, Any], Dict[Any, Any]] # Dict-like context carrier
EventDict = MutableMapping[str, Any] # Event dictionary for processors
ProcessorReturnValue = Union[Mapping[str, Any], str, bytes, bytearray, Tuple[Any, ...]]
Processor = Callable[[WrappedLogger, str, EventDict], ProcessorReturnValue]
ExcInfo = Tuple[Type[BaseException], BaseException, Optional[TracebackType]]
ExceptionRenderer = Callable[[TextIO, ExcInfo], None]
# Additional types
Self = TypeVar('Self', bound='BoundLoggerBase') # For bound logger methods
NoReturn = typing.NoReturn # For functions that don't return
CapturedCall = NamedTuple # Testing utility type with fields: method_name, args, kwargs
# Core exception
class DropEvent(BaseException):
"""Exception to drop log events silently."""