Spaces:
Sleeping
Sleeping
| """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) | |