instance-2 / docqa /docxextract /logging.py
validops-east-3's picture
Deploy 72701a1d9ec33b1842d0a516ffdee753aaa754a9
efff1ff verified
Raw History Blame Contribute Delete
1.92 kB
"""Structured JSON logging with request correlation."""
from __future__ import annotations
import logging
import sys
import time
import uuid
from contextvars import ContextVar
from typing import Any
_request_id: ContextVar[str] = ContextVar("request_id", default="-")
class JsonFormatter(logging.Formatter):
def format(self, record: logging.LogRecord) -> str:
import json
payload: dict[str, Any] = {
"ts": time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(record.created))
+ f".{int(record.msecs):03d}Z",
"level": record.levelname,
"logger": record.name,
"msg": record.getMessage(),
"request_id": _request_id.get(),
}
for key in ("document_id", "latency_ms", "status", "n_keys", "detail"):
val = getattr(record, key, None)
if val is not None:
payload[key] = val
if record.exc_info:
payload["exc"] = self.formatException(record.exc_info)
return json.dumps(payload, ensure_ascii=False)
def configure_logging(level: str = "INFO", json_output: bool = True) -> None:
root = logging.getLogger()
root.handlers.clear()
handler = logging.StreamHandler(sys.stdout)
if json_output:
handler.setFormatter(JsonFormatter())
else:
handler.setFormatter(
logging.Formatter("%(asctime)s %(levelname)-7s %(name)s | %(message)s")
)
root.addHandler(handler)
root.setLevel(level.upper())
# uvicorn duplicates access logs through its own handlers.
for noisy in ("uvicorn.access", "uvicorn.error"):
logging.getLogger(noisy).handlers.clear()
logging.getLogger(noisy).propagate = True
def new_request_id() -> str:
rid = uuid.uuid4().hex[:16]
_request_id.set(rid)
return rid
def get_logger(name: str) -> logging.Logger:
return logging.getLogger(name)