Files
2026-04-27 20:50:07 +03:00

47 lines
1.8 KiB
Python

import logging
import sys
from contextvars import ContextVar
# Храним trace_id текущего потока/корутины.
TRACE_ID: ContextVar[str] = ContextVar("trace_id", default="-")
class TraceIdFilter(logging.Filter):
# Добавляет trace_id в каждую запись лога для сквозной трассировки.
def filter(self, record: logging.LogRecord) -> bool:
record.trace_id = TRACE_ID.get()
return True
def set_trace_id(trace_id: str) -> None:
TRACE_ID.set(trace_id)
def setup_logging(level: str = "INFO", log_file: str | None = None) -> None:
# stdout — основной поток для `docker logs`, Docker Desktop и compose logs.
# stderr в PowerShell часто выглядит как NativeCommandError, хотя это обычные логи.
handlers: list[logging.Handler] = [logging.StreamHandler(sys.stdout)]
if log_file:
handlers.append(logging.FileHandler(log_file, encoding="utf-8"))
trace_filter = TraceIdFilter()
for handler in handlers:
handler.addFilter(trace_filter)
handler.setLevel(getattr(logging, level.upper(), logging.INFO))
root = logging.getLogger()
root.setLevel(getattr(logging, level.upper(), logging.INFO))
# Убираем старые хендлеры, чтобы не дублировать после fork.
for old_handler in list(root.handlers):
try:
old_handler.close()
except Exception:
pass
root.handlers.clear()
for handler in handlers:
root.addHandler(handler)
root.propagate = False
fmt = logging.Formatter(
"%(asctime)s | %(levelname)s | %(name)s | trace=%(trace_id)s | %(message)s"
)
for handler in root.handlers:
handler.setFormatter(fmt)