Spaces:
Running
Running
| import logging | |
| import sys | |
| import contextvars | |
| from uuid import uuid4 | |
| # Zmienna kontekstowa definiująca unikalne ID zapytania HTTP (lub tła) | |
| request_id_ctx_var: contextvars.ContextVar[str] = contextvars.ContextVar( | |
| "request_id", default="SYSTEM" | |
| ) | |
| class RequestIDFilter(logging.Filter): | |
| """ | |
| Filtr wstrzykujący contextvar (RequestID) do rekordu logów. | |
| """ | |
| def filter(self, record): | |
| record.request_id = request_id_ctx_var.get() | |
| return True | |
| def setup_logging(): | |
| """ | |
| Konfiguruje główny logger aplikacji tak, aby: | |
| - używał StreamHandler (stdout) pod kontener (np. Render/Docker) | |
| - dodawał ustrukturyzowany prefiks: [Data] [Poziom] [RequestID: ...] Wiadomość. | |
| """ | |
| logger = logging.getLogger("DotacjeAI") | |
| logger.setLevel(logging.INFO) | |
| # Zapobiega duplikacji, gdy powtarzamy użycie skryptu gunicorn/uvicorn | |
| if logger.handlers: | |
| logger.handlers.clear() | |
| handler = logging.StreamHandler(sys.stdout) | |
| handler.setLevel(logging.INFO) | |
| # Format zadeklarowany we wdrożeniu (DEPLOYMENT.md) | |
| formatter = logging.Formatter( | |
| fmt="[%(asctime)s] [%(levelname)s] [RequestID: %(request_id)s] %(message)s", | |
| datefmt="%Y-%m-%d %H:%M:%S", | |
| ) | |
| handler.setFormatter(formatter) | |
| # Dodajemy filtr wyciągający zmienne kontekstowe | |
| filter_req_id = RequestIDFilter() | |
| handler.addFilter(filter_req_id) | |
| logger.addFilter(filter_req_id) | |
| logger.addHandler(handler) | |
| # Przechwytuj uvicorn i langserve logi w naszym stylu | |
| logging.getLogger("uvicorn.access").addFilter(filter_req_id) | |
| return logger | |
| def set_request_id(req_id: str | None = None) -> str: | |
| """Ustawia request ID w zmiennej kontekstowej dla bieżącego cyklu asynchronicznego.""" | |
| new_id = req_id or f"req_{uuid4().hex[:8]}" | |
| request_id_ctx_var.set(new_id) | |
| return new_id | |