d78b668e31
Stefan-Anforderung: Background-Wake-Word-Pipeline klappt noch nicht, ADB nicht zur Hand → Debug via RVS-Log-Pipeline. Logger: - reportAppDebug(scope, message) analog zu reportAppError aber level=info, kein console.error, fuer Live-Diagnose Strategische Log-Punkte: - wakeword.ts: start() emits 'wake.start armed' - wakeword.ts: onWakeDetected emits 'wake.detect state=X' beim Native-Trigger-Empfang - ChatScreen.tsx wake-callback: 'wake.cb callback fired', 'wake.cb startRecording=X', 'wake.cb gong played' - backgroundAudio.ts: 'bg.start slot=X', 'bg.stop service stopped', 'bg.start.fail msg' wenn Service nicht hochkommt Abruf live via curl http://172.0.2.33:3001/api/app-log?lines=100 Damit kann Stefan nach APK-Build (mit allen Native-Fixes + Logger) im Background-Test exakt sehen wo es klemmt: - Kommt 'wake.detect' im Hintergrund an? (WakeLock-Frage) - Kommt 'wake.cb callback fired'? (JS-Bridge-Frage) - Geht 'bg.start slot=wake' durch? (Service-Start-Frage) APK neu bauen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
134 lines
4.4 KiB
TypeScript
134 lines
4.4 KiB
TypeScript
/**
|
|
* Verbose-Logging-Toggle: console.log laesst sich global stummschalten.
|
|
* console.warn/console.error bleiben immer an — Fehler will man immer sehen.
|
|
*
|
|
* Default: an (true). Toggle ueber Settings → Protokoll → Verbose Logging.
|
|
* Beim Start wird der gespeicherte Wert geladen, vorher loggen wir normal.
|
|
*/
|
|
|
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
import { Platform } from 'react-native';
|
|
import rvs from './rvs';
|
|
|
|
export const VERBOSE_LOGGING_KEY = 'aria_verbose_logging';
|
|
|
|
// Original-console.log retten, damit wir die Wrapper jederzeit wieder
|
|
// "scharf" stellen koennen (sonst waere ein Toggle-an nach -aus tot).
|
|
const originalLog = console.log.bind(console);
|
|
const noop = () => {};
|
|
|
|
let _verbose = true;
|
|
|
|
function applyState(): void {
|
|
console.log = _verbose ? originalLog : noop;
|
|
}
|
|
|
|
/** Wert aus AsyncStorage laden und anwenden. Beim App-Start aufrufen. */
|
|
export async function initLogger(): Promise<void> {
|
|
try {
|
|
const v = await AsyncStorage.getItem(VERBOSE_LOGGING_KEY);
|
|
_verbose = v !== 'false'; // default: true
|
|
} catch {}
|
|
applyState();
|
|
}
|
|
|
|
export function isVerboseLogging(): boolean {
|
|
return _verbose;
|
|
}
|
|
|
|
export function setVerboseLogging(verbose: boolean): void {
|
|
_verbose = verbose;
|
|
applyState();
|
|
AsyncStorage.setItem(VERBOSE_LOGGING_KEY, String(verbose)).catch(() => {});
|
|
}
|
|
|
|
// ─── App-Crash-Reporting via RVS ────────────────────────────────────
|
|
//
|
|
// Wenn die App crasht — egal ob React-Render-Fehler (ErrorBoundary) oder
|
|
// ungefangener JS-Error (ErrorUtils-Handler) — schicken wir den Crash
|
|
// als RVS-Message vom Typ "app_log" an die Bridge. Die schreibt in
|
|
// /shared/logs/app.log, sodass wir/Diagnostic die Crashes mitlesen
|
|
// koennen ohne ADB.
|
|
|
|
interface AppErrorEvent {
|
|
scope: string;
|
|
message: string;
|
|
stack?: string;
|
|
level?: 'error' | 'warn' | 'info';
|
|
}
|
|
|
|
let _reportingInstalled = false;
|
|
|
|
/** Schickt einen App-Fehler via RVS an die Bridge. */
|
|
export function reportAppError(ev: AppErrorEvent): void {
|
|
try {
|
|
rvs.send('app_log' as any, {
|
|
ts: Date.now(),
|
|
platform: Platform.OS,
|
|
level: ev.level || 'error',
|
|
scope: ev.scope,
|
|
message: ev.message,
|
|
stack: (ev.stack || '').slice(0, 8000),
|
|
});
|
|
} catch {
|
|
// RVS noch nicht connected — Fehler geht im console weiter.
|
|
}
|
|
// Plus lokal: console.error, damit Stefan's adb (wenn doch mal verfuegbar)
|
|
// den Crash sieht.
|
|
console.error(`[app-error scope=${ev.scope}]`, ev.message, '\n', ev.stack || '');
|
|
}
|
|
|
|
/** Schickt eine Debug-/Info-Message via RVS an die Bridge. Landet ebenfalls
|
|
* in /shared/logs/app.log — abrufbar via `curl /api/app-log?lines=N`.
|
|
* Im Gegensatz zu reportAppError: keine Stacktrace, level=info, kein
|
|
* console.error. Fuer Live-Diagnose im Hintergrund wenn ADB nicht da ist. */
|
|
export function reportAppDebug(scope: string, message: string): void {
|
|
try {
|
|
rvs.send('app_log' as any, {
|
|
ts: Date.now(),
|
|
platform: Platform.OS,
|
|
level: 'info',
|
|
scope,
|
|
message: String(message).slice(0, 2000),
|
|
});
|
|
} catch {}
|
|
}
|
|
|
|
/** Installiert einen globalen JS-Error-Handler der ungefangene Errors via
|
|
* RVS an die Bridge schickt. Beim App-Start aufrufen. */
|
|
export function installGlobalCrashReporter(): void {
|
|
if (_reportingInstalled) return;
|
|
_reportingInstalled = true;
|
|
try {
|
|
const g: any = global as any;
|
|
const prev = g.ErrorUtils?.getGlobalHandler?.();
|
|
g.ErrorUtils?.setGlobalHandler?.((err: any, isFatal: boolean) => {
|
|
reportAppError({
|
|
scope: isFatal ? 'global-fatal' : 'global-nonfatal',
|
|
message: (err && err.message) || String(err),
|
|
stack: err && err.stack,
|
|
});
|
|
// Original-Handler weiterhin aufrufen damit React-Native das System-
|
|
// Crash-Overlay zeigt (im Dev-Build) bzw. in Production sauber stirbt.
|
|
if (typeof prev === 'function') {
|
|
try { prev(err, isFatal); } catch {}
|
|
}
|
|
});
|
|
// unhandled Promise-Rejections — manche RN-Versionen haben das nicht
|
|
// automatisch im ErrorUtils.
|
|
g.HermesInternal?.enablePromiseRejectionTracker?.({
|
|
allRejections: true,
|
|
onUnhandled: (id: number, err: any) => {
|
|
reportAppError({
|
|
scope: 'promise-unhandled',
|
|
level: 'warn',
|
|
message: (err && err.message) || String(err),
|
|
stack: err && err.stack,
|
|
});
|
|
},
|
|
});
|
|
} catch {
|
|
// ErrorUtils nicht da → nix machen
|
|
}
|
|
}
|