| # ============================================================ | |
| # FILE: src/logging_utils.py | |
| # ============================================================ | |
| # PURPOSE: | |
| # Save structured logs for RAG runs. | |
| # | |
| # WHY LOGGING MATTERS: | |
| # Production AI systems need observability. | |
| # | |
| # Useful fields: | |
| # - user question | |
| # - generated answer | |
| # - retrieved sources | |
| # - model name | |
| # - prompt version | |
| # - latency | |
| # - errors | |
| # | |
| # AI ENGINEER PRODUCTION TIP: | |
| # Be careful with sensitive data. | |
| # Do not log private user data unless necessary and protected. | |
| # ============================================================ | |
| import json | |
| import time | |
| from pathlib import Path | |
| from typing import Any, Dict | |
| def write_jsonl_event(logs_folder: Path, event: Dict[str, Any]) -> Path: | |
| """ | |
| Append one JSON event to a JSONL file. | |
| JSONL format: | |
| - one JSON object per line | |
| - easy to append | |
| - easy to load later | |
| """ | |
| logs_folder.mkdir(parents=True, exist_ok=True) | |
| log_path = logs_folder / "rag_events.jsonl" | |
| event_with_timestamp = { | |
| "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), | |
| **event, | |
| } | |
| with log_path.open("a", encoding="utf-8") as file: | |
| file.write(json.dumps(event_with_timestamp, ensure_ascii=False) + "\n") | |
| return log_path | |
| def save_json_output(outputs_folder: Path, data: Dict[str, Any], file_name: str) -> Path: | |
| """ | |
| Save a full RAG result as a JSON file. | |
| """ | |
| outputs_folder.mkdir(parents=True, exist_ok=True) | |
| output_path = outputs_folder / file_name | |
| with output_path.open("w", encoding="utf-8") as file: | |
| json.dump(data, file, indent=2, ensure_ascii=False) | |
| return output_path |