python --version
pip install structlog
Set up structlog for structured JSON logging with request correlation IDs and log aggregation best practices.
1 import structlog 2 import logging 3 import uuid 4 from contextlib import contextmanager 5 6 # Configure structlog 7 structlog.configure( 8 processors=[ 9 structlog.contextvars.merge_contextvars, 10 structlog.processors.add_log_level, 11 structlog.processors.TimeStamper(fmt="iso"), 12 structlog.processors.StackInfoRenderer(), 13 structlog.processors.ExceptionRenderer(), 14 structlog.processors.JSONRenderer(), 15 ], 16 wrapper_class=structlog.make_filtering_bound_logger(logging.INFO), 17 context_class=dict, 18 logger_factory=structlog.PrintLoggerFactory(), 19 ) 20 21 log = structlog.get_logger() 22 23 # Always add service metadata 24 structlog.contextvars.bind_contextvars( 25 service="payment-service", 26 version="2.3.1", 27 environment="production", 28 ) 29 30 @contextmanager 31 def request_context(user_id: str | None = None): 32 """Bind a request-scoped correlation ID to all logs within context.""" 33 token = structlog.contextvars.bind_contextvars( 34 request_id=str(uuid.uuid4()), 35 user_id=user_id, 36 ) 37 try: 38 yield 39 finally: 40 structlog.contextvars.unbind_contextvars("request_id", "user_id") 41 42 def process_payment(order_id: str, amount: float) -> dict: 43 log.info("payment_started", order_id=order_id, amount=amount) 44 45 if amount <= 0: 46 log.warning("invalid_payment_amount", order_id=order_id, amount=amount) 47 return {"status": "failed", "reason": "invalid_amount"} 48 49 # Simulate processing 50 log.debug("payment_gateway_called", gateway="stripe", order_id=order_id) 51 log.info("payment_completed", order_id=order_id, amount=amount, 52 transaction_id="txn-" + uuid.uuid4().hex[:8]) 53 return {"status": "success"} 54 55 # Simulate requests 56 with request_context(user_id="user-123"): 57 result = process_payment("ORD-001", 99.99) 58 log.info("request_completed", result=result) 59 60 with request_context(user_id="user-456"): 61 result = process_payment("ORD-002", -5) 62 log.info("request_completed", result=result) 63
Sign in to share your feedback and join the discussion.