Initialize git, add Apache-2.0 LICENSE, .gitattributes (LF line endings), AGENTS.md (entry points, stack, discovery order, baseline checks), RUNBOOK.md (dev boot, prod deploy with overlay, ingestion, failures, rollback, scaling notes), .env.prod.example with rotated credential placeholders, and dev-only warnings on .env.example. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
62 lines
1.7 KiB
Python
62 lines
1.7 KiB
Python
"""Structured logging via structlog with stdlib bridge.
|
|
|
|
All modules use ``get_logger(__name__)`` and emit key/value pairs.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import sys
|
|
from typing import Any
|
|
|
|
import structlog
|
|
|
|
from app.config import settings
|
|
|
|
|
|
def configure_logging() -> None:
|
|
level = getattr(logging, settings.app_log_level.upper(), logging.INFO)
|
|
|
|
timestamper = structlog.processors.TimeStamper(fmt="iso", utc=True)
|
|
|
|
shared_processors: list[Any] = [
|
|
structlog.contextvars.merge_contextvars,
|
|
structlog.stdlib.add_log_level,
|
|
structlog.stdlib.add_logger_name,
|
|
timestamper,
|
|
structlog.processors.StackInfoRenderer(),
|
|
structlog.processors.format_exc_info,
|
|
]
|
|
|
|
structlog.configure(
|
|
processors=shared_processors
|
|
+ [structlog.stdlib.ProcessorFormatter.wrap_for_formatter],
|
|
logger_factory=structlog.stdlib.LoggerFactory(),
|
|
wrapper_class=structlog.stdlib.BoundLogger,
|
|
cache_logger_on_first_use=True,
|
|
)
|
|
|
|
formatter = structlog.stdlib.ProcessorFormatter(
|
|
foreign_pre_chain=shared_processors,
|
|
processors=[
|
|
structlog.stdlib.ProcessorFormatter.remove_processors_meta,
|
|
structlog.processors.JSONRenderer(),
|
|
],
|
|
)
|
|
|
|
handler = logging.StreamHandler(sys.stdout)
|
|
handler.setFormatter(formatter)
|
|
|
|
root = logging.getLogger()
|
|
root.handlers.clear()
|
|
root.addHandler(handler)
|
|
root.setLevel(level)
|
|
|
|
# Quiet down noisy libs
|
|
for noisy in ("urllib3", "botocore", "s3transfer", "elasticsearch", "opensearch", "httpx"):
|
|
logging.getLogger(noisy).setLevel(logging.WARNING)
|
|
|
|
|
|
def get_logger(name: str | None = None) -> structlog.stdlib.BoundLogger:
|
|
return structlog.get_logger(name)
|