more logs
This commit is contained in:
parent
f61801e855
commit
2715c56b4f
2 changed files with 105 additions and 0 deletions
|
|
@ -1,4 +1,46 @@
|
|||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App";
|
||||
|
||||
const backendBase =
|
||||
(import.meta.env.VITE_BACKEND_URL as string | undefined) ?? "http://localhost:8000";
|
||||
|
||||
const sendFrontLog = (message: string, level: "info" | "warn" | "error" = "info") => {
|
||||
fetch(`${backendBase}/logs`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ message, level, source: "frontend" }),
|
||||
}).catch(() => {});
|
||||
};
|
||||
|
||||
window.addEventListener("error", (event) => {
|
||||
const err = event.error instanceof Error ? event.error : null;
|
||||
const details = err?.stack || err?.message || String(event.message || "unknown error");
|
||||
sendFrontLog(`window.error: ${details}`, "error");
|
||||
});
|
||||
|
||||
window.addEventListener("unhandledrejection", (event) => {
|
||||
const reason = event.reason instanceof Error ? event.reason.stack || event.reason.message : String(event.reason);
|
||||
sendFrontLog(`unhandledrejection: ${reason}`, "error");
|
||||
});
|
||||
|
||||
const _consoleError = console.error.bind(console);
|
||||
console.error = (...args: unknown[]) => {
|
||||
try {
|
||||
sendFrontLog(`console.error: ${args.map(String).join(" ")}`, "error");
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
_consoleError(...args);
|
||||
};
|
||||
|
||||
const _consoleWarn = console.warn.bind(console);
|
||||
console.warn = (...args: unknown[]) => {
|
||||
try {
|
||||
sendFrontLog(`console.warn: ${args.map(String).join(" ")}`, "warn");
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
_consoleWarn(...args);
|
||||
};
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(<App />);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import uvicorn
|
||||
|
|
@ -12,19 +14,80 @@ def _env(name: str, default: str) -> str:
|
|||
return v if v is not None and v != "" else default
|
||||
|
||||
|
||||
class _TeeStream:
|
||||
def __init__(self, primary, secondary):
|
||||
self._primary = primary
|
||||
self._secondary = secondary
|
||||
|
||||
def write(self, data):
|
||||
try:
|
||||
self._primary.write(data)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self._secondary.write(data)
|
||||
except Exception:
|
||||
pass
|
||||
return len(data)
|
||||
|
||||
def flush(self):
|
||||
try:
|
||||
self._primary.flush()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
self._secondary.flush()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def isatty(self):
|
||||
try:
|
||||
return self._primary.isatty()
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _ensure_uvicorn_logs_to_file(log_path: Path) -> None:
|
||||
import logging
|
||||
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
file_handler = logging.FileHandler(log_path, encoding="utf-8")
|
||||
file_handler.setLevel(logging.INFO)
|
||||
file_handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s"))
|
||||
|
||||
for name in ("uvicorn", "uvicorn.error", "uvicorn.access"):
|
||||
logger = logging.getLogger(name)
|
||||
logger.setLevel(logging.INFO)
|
||||
if not any(
|
||||
isinstance(h, logging.FileHandler) and getattr(h, "baseFilename", None) == str(log_path)
|
||||
for h in logger.handlers
|
||||
):
|
||||
logger.addHandler(file_handler)
|
||||
logger.propagate = True
|
||||
|
||||
|
||||
def main(argv: Optional[list[str]] = None) -> int:
|
||||
parser = argparse.ArgumentParser(prog="gnss", description="GNSS Backend (FastAPI)")
|
||||
parser.add_argument("--host", default=_env("GNSS_HOST", "0.0.0.0"))
|
||||
parser.add_argument("--port", type=int, default=int(_env("GNSS_PORT", "8000")))
|
||||
parser.add_argument("--log-level", default=_env("GNSS_LOG_LEVEL", "info"))
|
||||
parser.add_argument("--log-file", default=_env("GNSS_BACKEND_LOG_FILE", "logs/backend.log"))
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
log_path = Path(args.log_file).expanduser()
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
backend_log_file = log_path.open("a", encoding="utf-8", buffering=1)
|
||||
sys.stdout = _TeeStream(sys.stdout, backend_log_file) # type: ignore[assignment]
|
||||
sys.stderr = _TeeStream(sys.stderr, backend_log_file) # type: ignore[assignment]
|
||||
_ensure_uvicorn_logs_to_file(log_path)
|
||||
|
||||
uvicorn.run(
|
||||
app,
|
||||
host=args.host,
|
||||
port=args.port,
|
||||
log_level=args.log_level,
|
||||
access_log=True,
|
||||
log_config=None,
|
||||
workers=1,
|
||||
)
|
||||
return 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue