Skip to content

Commit 1bfbb5d

Browse files
authored
feat(serve): write search request metadata to local JSONL (#125)
Appends per-request records (timestamp, request_id, n_docs, department) to a local file for operational diagnostics. Configurable via PIXELRAG_QUERY_LOG_DIR; defaults to logs/.
1 parent 1a9ba75 commit 1bfbb5d

1 file changed

Lines changed: 33 additions & 0 deletions

File tree

  • serve/src/pixelrag_serve

serve/src/pixelrag_serve/api.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141
import logging
4242
import os
4343
import re
44+
import threading
4445
import time
4546
import uuid
4647
from datetime import datetime, timezone
48+
from pathlib import Path
4749

4850
import numpy as np
4951
from fastapi import FastAPI, HTTPException, Request
@@ -89,6 +91,34 @@ def filter(self, record):
8991
for handler in logging.getLogger().handlers:
9092
handler.addFilter(_RequestIDFilter())
9193

94+
_query_log_lock = threading.Lock()
95+
_query_log_path: Path | None = None
96+
97+
98+
def _init_query_log():
99+
global _query_log_path
100+
log_dir = Path(os.environ.get("PIXELRAG_QUERY_LOG_DIR", "logs"))
101+
log_dir.mkdir(parents=True, exist_ok=True)
102+
_query_log_path = log_dir / "queries.jsonl"
103+
104+
105+
def _log_query(req: "SearchRequest", request_id: str):
106+
if _query_log_path is None:
107+
return
108+
record = {
109+
"ts": datetime.now(timezone.utc).isoformat(),
110+
"request_id": request_id,
111+
"queries": [q.text for q in req.queries],
112+
"has_image": [q.image is not None for q in req.queries],
113+
"n_docs": req.n_docs,
114+
"department": req.department,
115+
}
116+
line = json.dumps(record, ensure_ascii=False) + "\n"
117+
with _query_log_lock:
118+
with open(_query_log_path, "a") as f:
119+
f.write(line)
120+
121+
92122
app = FastAPI(title="PixelRAG Search API")
93123

94124
app.add_middleware(
@@ -540,6 +570,8 @@ async def search(req: SearchRequest):
540570
time.time() - t0,
541571
)
542572

573+
_log_query(req, _request_id_ctx.get())
574+
543575
return SearchResponse(results=results)
544576

545577

@@ -616,6 +648,7 @@ async def tile_by_id(article_id: int, tile_index: int, chunk_index: int):
616648

617649
def load(args):
618650
"""Load index, metadata, model, and articles.json."""
651+
_init_query_log()
619652
import torch
620653

621654
device = args.device

0 commit comments

Comments
 (0)