Add structured logging to Python with structlog. Use when a user asks to implement structured logging, add context to Python logs, configure log processing pipelines, or replace standard logging with typed output.
structlog adds structured, context-rich logging to Python. Instead of format strings, you pass key-value pairs that render as JSON (production) or colorized human-readable output (development). Bound loggers carry context across function calls.
# logging_config.py — structlog setup
import structlog
import logging
import sys
def setup_logging(environment: str = "development"):
"""Configure structlog for the application.
Args:
environment: 'development' for pretty output, 'production' for JSON
"""
shared_processors = [
structlog.contextvars.merge_contextvars,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.StackInfoRenderer(),
structlog.processors.UnicodeDecoder(),
]
if environment == "production":
renderer = structlog.processors.JSONRenderer()
else:
renderer = structlog.dev.ConsoleRenderer(colors=True)
structlog.configure(
processors=[
*shared_processors,
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=True,
)
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(structlog.stdlib.ProcessorFormatter(
processors=[*shared_processors, renderer],
))
root_logger = logging.getLogger()
root_logger.addHandler(handler)
root_logger.setLevel(logging.INFO)
# services/orders.py — Structured logging in business logic
import structlog
log = structlog.get_logger()
async def process_order(order_id: str, user_id: str):
# Bind context that carries through the entire function
log_ctx = log.bind(order_id=order_id, user_id=user_id)
log_ctx.info("Processing order")
items = await fetch_order_items(order_id)
log_ctx.info("Items fetched", item_count=len(items), total=sum(i.price for i in items))
try:
payment = await charge_payment(order_id)
log_ctx.info("Payment charged", payment_id=payment.id, amount=payment.amount)
except PaymentError as e:
log_ctx.error("Payment failed", error=str(e), error_code=e.code)
raise
log_ctx.info("Order completed", status="success")
# middleware.py — Add request context to all logs
import structlog
from uuid import uuid4
async def logging_middleware(request, call_next):
request_id = request.headers.get("x-request-id", str(uuid4()))
structlog.contextvars.clear_contextvars()
structlog.contextvars.bind_contextvars(
request_id=request_id,
method=request.method,
path=request.url.path,
user_id=getattr(request.state, "user_id", None),
)
log = structlog.get_logger()
log.info("Request started")
response = await call_next(request)
log.info("Request completed", status_code=response.status_code)
response.headers["x-request-id"] = request_id
return response
contextvars for request-scoped context — all logs in the request include requestId, userId.log.bind(...)) and it carries through all subsequent log calls.logging.log.info("order_processed", order_id=id) not log.info(f"Processed order {id}").npx skills add TerminalSkills/structlog-python下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer