{"library":"structlog","install":[{"cmd":"pip install structlog","imports":["import logging\nimport structlog\n\n# Configure BEFORE any get_logger() calls\nstructlog.configure(\n    processors=[\n        structlog.contextvars.merge_contextvars,\n        structlog.stdlib.add_log_level,\n        structlog.stdlib.add_logger_name,\n        structlog.processors.TimeStamper(fmt='iso'),\n        structlog.processors.StackInfoRenderer(),\n        structlog.processors.JSONRenderer(),   # JSON output\n    ],\n    wrapper_class=structlog.make_filtering_bound_logger(logging.INFO),  # filter by level\n    logger_factory=structlog.PrintLoggerFactory(),\n    cache_logger_on_first_use=True,\n)\n\nlog = structlog.get_logger()\nlog.info('app_started', version='1.0.0')\nlog.warning('high_memory', usage_pct=95)\n\n# bind() returns NEW logger — immutable\nrequest_log = log.bind(request_id='req-123', user_id='usr-456')\nrequest_log.info('payment_initiated', amount=500)\n# original log is unchanged","import logging\nimport sys\nimport structlog\n\n# Make stdlib logging go through structlog processors\ntimestamper = structlog.processors.TimeStamper(fmt='iso')\npre_chain = [\n    structlog.stdlib.add_log_level,\n    timestamper,\n]\n\nhandler = logging.StreamHandler(sys.stdout)\nhandler.setFormatter(\n    structlog.stdlib.ProcessorFormatter(\n        processor=structlog.processors.JSONRenderer(),\n        foreign_pre_chain=pre_chain,\n    )\n)\n\nroot_logger = logging.getLogger()\nroot_logger.addHandler(handler)\nroot_logger.setLevel(logging.INFO)\n\n# Now both structlog AND stdlib logging output same JSON format\nstructlog.configure(\n    processors=[\n        structlog.stdlib.add_log_level,\n        timestamper,\n        structlog.stdlib.ProcessorFormatter.wrap_for_formatter,\n    ],\n    logger_factory=structlog.stdlib.LoggerFactory(),\n)\n\nlog = structlog.get_logger()\nlog.info('structured', key='val')\nlogging.getLogger('uvicorn').info('stdlib log')  # also JSON"]}]}