From 005234c953b293eeff561734ca5e71ecd4ac8da0 Mon Sep 17 00:00:00 2001 From: Roland Tannous Date: Mon, 25 May 2026 15:25:11 +0400 Subject: [PATCH] Studio: route RAG parent-process loggers through structlog core/rag/db.py, vector_store.py, tool.py, bm25.py, and reranker.py all run only in the FastAPI parent process. Switch their loggers from Python stdlib to studio's structlog get_logger so their output shows up in the same JSON stream as the rest of the backend (the request_completed / RAG search lines). embeddings.py and ingestion.py stay on stdlib because they execute inside the mp.spawn ingestion subprocess, which doesn't inherit the parent's structlog configuration. --- studio/backend/core/rag/bm25.py | 4 ++-- studio/backend/core/rag/db.py | 6 +++--- studio/backend/core/rag/reranker.py | 4 ++-- studio/backend/core/rag/tool.py | 5 +++-- studio/backend/core/rag/vector_store.py | 5 +++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/studio/backend/core/rag/bm25.py b/studio/backend/core/rag/bm25.py index c3da6806d6..28b991d168 100644 --- a/studio/backend/core/rag/bm25.py +++ b/studio/backend/core/rag/bm25.py @@ -17,15 +17,15 @@ A scope is ``kb_`` or ``thread_``. Each scope stores: from __future__ import annotations import json -import logging import shutil import threading from pathlib import Path from typing import Any +from loggers import get_logger from utils.paths.storage_roots import ensure_dir, rag_bm25_root -logger = logging.getLogger(__name__) +logger = get_logger(__name__) _load_lock = threading.Lock() _cache: dict[str, tuple[Any, list[str]]] = {} diff --git a/studio/backend/core/rag/db.py b/studio/backend/core/rag/db.py index 4fbd238843..1bb05c5fbd 100644 --- a/studio/backend/core/rag/db.py +++ b/studio/backend/core/rag/db.py @@ -11,14 +11,14 @@ to the RAG code path only — chat code keeps its plain sqlite handle. from __future__ import annotations -import logging import sqlite3 import threading from pathlib import Path +from loggers import get_logger from utils.paths.storage_roots import ensure_dir, rag_root -logger = logging.getLogger(__name__) +logger = get_logger(__name__) _conn: sqlite3.Connection | None = None _conn_lock = threading.Lock() @@ -96,7 +96,7 @@ def get_rag_connection() -> sqlite3.Connection: _load_sqlite_vec(conn) _ensure_schema(conn) _conn = conn - logger.info("RAG vector store: opened %s", rag_db_path()) + logger.info("RAG vector store opened", path = str(rag_db_path())) return _conn diff --git a/studio/backend/core/rag/reranker.py b/studio/backend/core/rag/reranker.py index 45fc3bb812..1496b2c271 100644 --- a/studio/backend/core/rag/reranker.py +++ b/studio/backend/core/rag/reranker.py @@ -17,15 +17,15 @@ replacing the import in ``_load``. from __future__ import annotations import gc -import logging import threading from typing import Any +from loggers import get_logger from utils.rag.config import RAG_RERANK_BATCH_SIZE, RAG_RERANKER_MODEL from .retrieval import Hit -logger = logging.getLogger(__name__) +logger = get_logger(__name__) _lock = threading.Lock() _model: Any | None = None diff --git a/studio/backend/core/rag/tool.py b/studio/backend/core/rag/tool.py index 8bd05ce8c9..5ec1f039ef 100644 --- a/studio/backend/core/rag/tool.py +++ b/studio/backend/core/rag/tool.py @@ -16,10 +16,11 @@ LLM doesn't need to know about KB UUIDs. from __future__ import annotations -import logging from typing import Any -logger = logging.getLogger(__name__) +from loggers import get_logger + +logger = get_logger(__name__) SEARCH_KNOWLEDGE_BASE_TOOL = { diff --git a/studio/backend/core/rag/vector_store.py b/studio/backend/core/rag/vector_store.py index 9517179715..64b1725c45 100644 --- a/studio/backend/core/rag/vector_store.py +++ b/studio/backend/core/rag/vector_store.py @@ -20,10 +20,11 @@ scope, so dims within a scope are always consistent. from __future__ import annotations import json -import logging from typing import Iterable -logger = logging.getLogger(__name__) +from loggers import get_logger + +logger = get_logger(__name__) def kb_scope(kb_id: str) -> str: