To make structlog’s behavior less magicy, it ships with a standard library-specific wrapper class that has an explicit API instead of improvising: structlog.stdlib.BoundLogger. It behaves exactly like the generic structlog.BoundLogger except:
structlog comes with one standard library-specific processor:
import structlog
structlog.configure(
processors=[structlog.stdlib.filter_by_level,
structlog.processors.format_exc_info,
structlog.processors.JSONRenderer()],
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
)
See also Logging Best Practices.