feat(debug): App-Crash-Reporting via RVS — Logs in der Diagnostic-UI
Stefan ist unterwegs, ADB-Zugriff nicht moeglich. Loesung: die App
loggt ihre eigenen Crashes via RVS, Bridge sammelt sie in
/shared/logs/app.log, Diagnostic-Server liefert sie als JSON.
Damit braucht's keinen ADB mehr — Crashes sind sofort vom Browser
(oder Claude per curl) lesbar.
Komponenten:
1. App components/ErrorBoundary.tsx
- React-ErrorBoundary fuer kritische Sections
- componentDidCatch → reportAppError (RVS-Send)
- UI zeigt Error-Box statt White-Screen + Reset-Button
2. App services/logger.ts
- reportAppError(scope, message, stack) → rvs.send('app_log', ...)
- installGlobalCrashReporter() haengt sich an ErrorUtils.setGlobalHandler
UND HermesInternal.enablePromiseRejectionTracker — fangt sowohl
ungefangene Errors als auch unhandled Promise-Rejections
- Konsole bleibt parallel aktiv (damit ADB im Dev-Build weiter
was sieht)
3. App App.tsx: installGlobalCrashReporter() im useEffect zusammen
mit initLogger.
4. App ChatScreen.tsx:
- Inbox-Modal mit ErrorBoundary umschlossen (scope: InboxModal,
onReset schliesst Modal)
- MemoryDetailModal mit ErrorBoundary umschlossen
- DetailModal wird nur noch konditional gerendert (memoryDetailId
!= null) statt immer visible-toggle — vermeidet potentielles
Modal-Stacking-Problem
5. RVS server.js: ALLOWED_TYPES += "app_log"
6. Bridge aria_bridge.py:
- elif msg_type == "app_log": haengt eine Zeile an
/shared/logs/app.log (JSONL, jedes Item {ts, platform, level,
scope, message, stack})
- Plus log.info Hinweis fuer das normale Bridge-Log
7. Diagnostic server.js:
- GET /api/app-log[?limit=N] → letzte N Eintraege als JSON
- POST /api/app-log/clear → log-Datei loeschen
Workflow zum Debuggen des Inbox-Crashes:
Stefan rebuilded App → drueckt Inbox → ErrorBoundary fangt den
Crash (oder Global-Handler bei ungefangenem Error) → reportAppError
→ RVS → Bridge schreibt nach /shared/logs/app.log → Stefan
oder Claude rufen GET /api/app-log auf → sehen Stacktrace.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1824,6 +1824,29 @@ class ARIABridge:
|
||||
logger.warning("[rvs] delete_message fehlgeschlagen: %s", result.get("error"))
|
||||
return
|
||||
|
||||
elif msg_type == "app_log":
|
||||
# App schickt Crash/Error/Info-Log via RVS — wir schreiben das
|
||||
# in /shared/logs/app.log (JSONL) damit Diagnostic + Claude
|
||||
# mitlesen koennen, auch ohne ADB-Zugriff aufs Handy.
|
||||
try:
|
||||
log_dir = Path("/shared/logs")
|
||||
log_dir.mkdir(parents=True, exist_ok=True)
|
||||
line = {
|
||||
"ts": payload.get("ts") or int(time.time() * 1000),
|
||||
"platform": payload.get("platform", "?"),
|
||||
"level": payload.get("level", "info"),
|
||||
"scope": payload.get("scope", ""),
|
||||
"message": payload.get("message", ""),
|
||||
"stack": payload.get("stack", ""),
|
||||
}
|
||||
with (log_dir / "app.log").open("a", encoding="utf-8") as f:
|
||||
f.write(json.dumps(line, ensure_ascii=False) + "\n")
|
||||
logger.info("[app-log] %s %s: %s",
|
||||
line["level"], line["scope"], line["message"][:120])
|
||||
except Exception as exc:
|
||||
logger.warning("[app-log] schreiben fehlgeschlagen: %s", exc)
|
||||
return
|
||||
|
||||
elif msg_type == "brain_request":
|
||||
# Generischer RVS-Proxy fuer die Brain-HTTP-API.
|
||||
# payload: {requestId, method, path, body?, bodyBase64?, contentType?}
|
||||
|
||||
Reference in New Issue
Block a user