structlog

v2026.09.24

structlog - structured logging library for Python with native JSON support, context binding, and processor pipeline. Integrates with FastAPI, Django, and standard logging module. USE WHEN: user mentions "structlog", "python structured logging", "context binding", asks about "JSON logging python", "fastapi logging", "django structured logging" DO NOT USE FOR: Standard Python logging - use `python-logging` instead, Node.js logging - use `pino` or `winston`, Java logging - use `slf4j` or `logback` instead

GitHub
Install command
npx skhub add claude-dev-suite/structlog
Markdown
SKILL.md

structlog - Quick Reference

When to Use This Skill

  • Structured logging in Python
  • Integration with JSON logging
  • Context binding for request tracing

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: structlog for comprehensive documentation.

Basic Setup

pip install structlog

Essential Patterns

Basic Configuration

import structlog

structlog.configure(
    processors=[
        structlog.stdlib.filter_by_level,
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        structlog.stdlib.PositionalArgumentsFormatter(),
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.processors.UnicodeDecoder(),
        structlog.processors.JSONRenderer()
    ],
    wrapper_class=structlog.stdlib.BoundLogger,
    context_class=dict,
    logger_factory=structlog.stdlib.LoggerFactory(),
    cache_logger_on_first_use=True,
)

Basic Usage

import structlog

log = structlog.get_logger()

log.info("user_logged_in", user_id=123, ip="192.168.1.1")
log.warning("rate_limit_exceeded", endpoint="/api/users", count=100)
log.error("database_error", error="connection timeout", retry=3)

Context Binding

log = structlog.get_logger()

# Bind context for all subsequent logs
log = log.bind(request_id="abc-123", user_id=42)

log.info("processing_started")  # Includes request_id and user_id
log.info("step_completed", step=1)
log.info("processing_finished")

# New context
log = log.new(request_id="xyz-789")

FastAPI Integration

from fastapi import FastAPI, Request
import structlog

app = FastAPI()

@app.middleware("http")
async def add_request_context(request: Request, call_next):
    structlog.contextvars.clear_contextvars()
    structlog.contextvars.bind_contextvars(
        request_id=request.headers.get("X-Request-ID", str(uuid.uuid4())),
        path=request.url.path,
    )
    return await call_next(request)

Django Integration

# settings.py
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "json": {
            "()": structlog.stdlib.ProcessorFormatter,
            "processor": structlog.processors.JSONRenderer(),
        },
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "json",
        },
    },
    "root": {
        "handlers": ["console"],
        "level": "INFO",
    },
}

Exception Logging

try:
    risky_operation()
except Exception:
    log.exception("operation_failed", operation="risky")
    # Automatically includes stack trace

When NOT to Use This Skill

  • Simple scripts: Standard logging module is sufficient for basic needs
  • Legacy codebases: Migration effort may not be worth it for small projects
  • Text-only log requirements: structlog is JSON-first, requires parsing
  • Non-Python projects: Use language-appropriate logging frameworks
  • Applications without centralized logging: Standard logging may be simpler

Anti-Patterns

Anti-PatternWhy It's BadSolution
Using ConsoleRenderer in productionWastes CPU, not machine-parseableUse JSONRenderer for production
Not clearing context variablesLeaks context across requestsUse structlog.contextvars.clear_contextvars()
Logging large objectsSerialization overheadLog only necessary fields or IDs
Creating new logger per requestPerformance overheadUse logger.bind() to add context
Missing exception loggingLoses stack tracesUse logger.exception() in except blocks
Not configuring processorsIncomplete/inconsistent outputConfigure full processor pipeline

Quick Troubleshooting

IssueCauseSolution
Plain text output instead of JSONConsoleRenderer configuredChange to JSONRenderer() in processors
Context not appearing in logsNot using context bindingUse logger.bind() or contextvars
Performance issuesToo many processorsRemove unnecessary processors, use JSONRenderer
Missing timestampsNo TimeStamper processorAdd TimeStamper(fmt='iso') to processors
Logs not colorized in devMissing dev configurationUse ConsoleRenderer(colors=True) for development
Context bleeding across requestsNot clearing contextvarsClear context at request start with middleware
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/logging/structlog

Default branch

main

Latest commit

9496306

Tree SHA

fe4e2f1