From 2c85df349948b9579bbb2b350457dd1e50c0019f Mon Sep 17 00:00:00 2001 From: duffyduck Date: Thu, 14 May 2026 15:59:06 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20tools/fetch-app-logs.sh=20=E2=80=94=20?= =?UTF-8?q?App-Crash-Logs=20von=20der=20VM=20holen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stefan ist unterwegs, ADB nicht moeglich. Dieses Script ist die andere Haelfte des Crash-Reportings (commit 21a315c hat die App-Seite + Bridge- Endpoint gebaut): Nutzung: tools/fetch-app-logs.sh # 200 letzte Eintraege tools/fetch-app-logs.sh --limit 50 tools/fetch-app-logs.sh --watch # alle 5s pollen + Diff ausgeben tools/fetch-app-logs.sh --clear # Log auf VM nach Abholen leeren Liest $ARIA_DIAG_URL aus .claude/aria-vm.env, ruft GET /api/app-log. Speichert komplette JSON-Response in .aria-debug/app-log-.json (gitignored). Stdout zeigt kompakt: Uhrzeit, Level, Scope, Message, erste 8 Stack-Frames pro Eintrag. .gitignore: .aria-debug/ ist komplett ausgeschlossen (Crashes koennen private Daten enthalten). tools/README.md: kurze Doku des Workflows. Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 4 ++ tools/README.md | 34 +++++++++++++ tools/fetch-app-logs.sh | 105 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 tools/README.md create mode 100755 tools/fetch-app-logs.sh diff --git a/.gitignore b/.gitignore index 66c8d45..d8c541f 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,10 @@ aria-data/brain-import/* !aria-data/brain-import/.gitkeep !aria-data/brain-import/README.md +# .aria-debug/ — App-Crash-Logs die tools/fetch-app-logs.sh hier ablegt. +# Komplett lokal, enthaelt potentiell private Stacktraces / Daten. +.aria-debug/ + # ── ARIAs Gedächtnis (Vector-DB, Skills, Models) ── # Backup via Diagnostic → Gehirn-Export (tar.gz), nicht via Git. aria-data/brain/data/ diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000..4b61629 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,34 @@ +# tools/ + +Hilfsskripte für die Dev-Maschine. Brauchen `.claude/aria-vm.env` (aus +`.example` kopieren + lokale VM-IP eintragen). + +## fetch-app-logs.sh + +Holt App-Crash-Logs von der VM und speichert sie unter `.aria-debug/` +(gitignored). Die App schickt JS-Errors und ungefangene Promise- +Rejections via RVS an die Bridge — Bridge sammelt in +`/shared/logs/app.log`, Diagnostic-Server gibt sie via +`GET /api/app-log` raus. + +```bash +tools/fetch-app-logs.sh # 200 neueste Eintraege +tools/fetch-app-logs.sh --limit 50 # weniger +tools/fetch-app-logs.sh --watch # alle 5s pollen, neue rausgeben +tools/fetch-app-logs.sh --clear # nach Abholen Log auf VM leeren +``` + +Ausgabe enthaelt pro Eintrag: Uhrzeit, Level (error/warn/info), Scope +(z.B. `ChatScreen.InboxModal` oder `global-fatal`), Message, und die +ersten ~8 Stack-Frames. Die kompletten Daten liegen als JSON in +`.aria-debug/app-log-.json`. + +Workflow nach einem Crash: + +1. App rebuilden mit Crash-Reporting (passiert automatisch ab dem + `21a315c`-Commit) +2. Crash in der App ausloesen +3. `tools/fetch-app-logs.sh` auf der Dev-Maschine +4. Stacktrace lesen / Claude geben +5. Fix bauen +6. `tools/fetch-app-logs.sh --clear` damit der Log wieder sauber ist diff --git a/tools/fetch-app-logs.sh b/tools/fetch-app-logs.sh new file mode 100755 index 0000000..e2b78ea --- /dev/null +++ b/tools/fetch-app-logs.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash +# fetch-app-logs.sh — App-Crash-Logs von der VM holen +# +# Nutzt .claude/aria-vm.env als Quelle fuer $ARIA_DIAG_URL und ruft +# GET /api/app-log?limit=N. Speichert die Roh-Response unter +# .aria-debug/app-log-.json und gibt eine kompakte +# Zusammenfassung auf stdout aus (letzte Eintraege mit Stack-Trace). +# +# Verwendung: +# tools/fetch-app-logs.sh # Default limit=200 +# tools/fetch-app-logs.sh --limit 50 # nur 50 holen +# tools/fetch-app-logs.sh --clear # nach Abholen Log loeschen +# tools/fetch-app-logs.sh --watch # alle 5s pollen, neue Eintraege ausgeben + +set -euo pipefail + +LIMIT=200 +CLEAR=0 +WATCH=0 +while [[ $# -gt 0 ]]; do + case "$1" in + --limit) LIMIT="$2"; shift 2 ;; + --limit=*) LIMIT="${1#*=}"; shift ;; + --clear) CLEAR=1; shift ;; + --watch) WATCH=1; shift ;; + -h|--help) + sed -n '1,/^set/p' "$0" | sed '$d' | sed 's/^# \{0,1\}//' + exit 0 ;; + *) echo "Unbekannte Option: $1" >&2; exit 1 ;; + esac +done + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +ENV_FILE="$ROOT/.claude/aria-vm.env" +OUT_DIR="$ROOT/.aria-debug" + +if [[ ! -f "$ENV_FILE" ]]; then + echo "FEHLER: $ENV_FILE nicht vorhanden. Aus .example kopieren und IP anpassen." >&2 + exit 1 +fi + +# shellcheck disable=SC1090 +source "$ENV_FILE" + +if [[ -z "${ARIA_DIAG_URL:-}" ]]; then + echo "FEHLER: ARIA_DIAG_URL nicht gesetzt in $ENV_FILE" >&2 + exit 1 +fi + +mkdir -p "$OUT_DIR" + +fetch_once() { + local ts json file + ts="$(date +%Y%m%d_%H%M%S)" + json="$(curl -s --max-time 10 "${ARIA_DIAG_URL%/}/api/app-log?limit=$LIMIT")" || { + echo "FEHLER: curl gegen $ARIA_DIAG_URL fehlgeschlagen" >&2 + return 1 + } + file="$OUT_DIR/app-log-$ts.json" + echo "$json" > "$file" + python3 - "$file" <<'PY' +import json, sys +from pathlib import Path +data = json.loads(Path(sys.argv[1]).read_text()) +entries = data.get("entries") or [] +print(f"=== {len(entries)} Eintrag{'e' if len(entries)!=1 else ''} (gespeichert unter {sys.argv[1]}) ===") +for e in entries[-20:]: + ts = e.get("ts") or 0 + from datetime import datetime + when = datetime.fromtimestamp(ts/1000).strftime("%H:%M:%S") if ts else "?" + lvl = e.get("level","?") + scope = e.get("scope","?") + msg = (e.get("message") or "").splitlines()[0][:200] + print(f"\n[{when}] {lvl:5} {scope}: {msg}") + stack = (e.get("stack") or "").strip() + if stack: + for line in stack.splitlines()[:8]: + print(f" {line}") + if len(stack.splitlines()) > 8: + print(f" ... ({len(stack.splitlines())-8} weitere Zeilen — siehe JSON)") +PY + return 0 +} + +if [[ "$WATCH" == "1" ]]; then + echo "Watching $ARIA_DIAG_URL/api/app-log — Ctrl+C zum Beenden" + SEEN="" + while true; do + cur=$(curl -s --max-time 10 "${ARIA_DIAG_URL%/}/api/app-log?limit=$LIMIT") || cur="" + hash=$(echo "$cur" | md5sum | awk '{print $1}') + if [[ "$hash" != "$SEEN" && -n "$cur" ]]; then + SEEN="$hash" + fetch_once + fi + sleep 5 + done +else + fetch_once +fi + +if [[ "$CLEAR" == "1" ]]; then + echo + echo "→ Log auf der VM leeren..." + curl -s --max-time 5 -X POST "${ARIA_DIAG_URL%/}/api/app-log/clear" | python3 -m json.tool || true +fi