File size: 1,873 Bytes
afd56bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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