# SonicForge Client Logs API — client gửi log hành động (MIDI/mastering/drag # errors) qua POST /api/v1/logs. Không lưu DB — in ra server log (uvicorn # console). Public: log không chứa dữ liệu nhạy (client tự quyết định). import logging from typing import Any, Optional from fastapi import APIRouter from pydantic import BaseModel router = APIRouter() _logger = logging.getLogger("sonicforge.client_logs") class ClientLogEntry(BaseModel): category: str = "GENERAL" level: str = "info" message: str = "" data: Optional[dict[str, Any]] = None url: Optional[str] = None ts: Optional[str] = None @router.post("") async def post_client_log(entry: ClientLogEntry): """Ghi log từ client vào server log (fire-and-forget, luôn 200).""" tag = f"[ClientLog][{entry.category}][{entry.level}]" line = f"{tag} {entry.message}" if entry.data: line += f" {entry.data}" if entry.ts: line += f" (ts={entry.ts})" if entry.url: line += f" url={entry.url}" if entry.level == "error": _logger.error(line) elif entry.level == "warn": _logger.warning(line) else: _logger.info(line) return {"ok": True}