deepagent-bot
ci: sync dashboard from a5b395d
f291c90
Raw
History Blame Contribute Delete
2.26 kB
"""Structured logging via structlog → JSON to stdout (or pretty in dev)."""
from __future__ import annotations
import logging
import os
import sys
import structlog
_initialised = False
def setup_logging(level: str = "INFO", json_logs: bool | None = None) -> None:
"""Configure structlog + stdlib logging once per process."""
global _initialised
if _initialised:
return
_initialised = True
if json_logs is None:
json_logs = os.getenv("DEEPAGENT_JSON_LOGS", "1") not in ("0", "false", "no", "")
timestamper = structlog.processors.TimeStamper(fmt="iso", utc=True)
shared_processors = [
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.StackInfoRenderer(),
timestamper,
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
]
if json_logs:
renderer = structlog.processors.JSONRenderer()
else:
renderer = structlog.dev.ConsoleRenderer(colors=sys.stderr.isatty())
structlog.configure(
processors=shared_processors + [renderer],
wrapper_class=structlog.make_filtering_bound_logger(
getattr(logging, level.upper(), logging.INFO)
),
context_class=dict,
logger_factory=structlog.PrintLoggerFactory(),
cache_logger_on_first_use=True,
)
# Pipe stdlib loggers (PyGithub, langchain, ...) through structlog too.
logging.basicConfig(
level=level.upper(),
format="%(message)s",
stream=sys.stderr,
force=True,
)
# Tame chatty libs by default
for noisy in ("urllib3", "github.Requester", "httpx", "httpcore"):
logging.getLogger(noisy).setLevel(logging.WARNING)
def bind(**ctx) -> None:
"""Bind key/value pairs to the current execution context.
Example: ``bind(job_id=..., repo=...)`` — every subsequent log entry in the
same coroutine/thread will include these fields.
"""
structlog.contextvars.bind_contextvars(**ctx)
def unbind(*keys: str) -> None:
structlog.contextvars.unbind_contextvars(*keys)
def get_logger(name: str | None = None) -> structlog.stdlib.BoundLogger:
return structlog.get_logger(name)