# Anonymous crash reporter

---

---

---

---

---

## Table of contents

<!-- toc -->
- [Android](#android)
- [Backend](#backend)
- [Report files](#report-files)
<!-- /toc -->

**Documentation index:** [README.md](README.md)

---

## Android

- **Main process:** `CrashReporter.install()` — any uncaught Java exception (cast or idle UI) → `files/crash_reports/pending/crash_yyyyMMdd_HHmmss.json` (same stamp as `session_*.json`). Active cast session stats are flushed with `globals.reason: "crash"` when applicable.
- **Runtime context:** every report includes `runtime_context` (foreground activity, `CastActiveState`, last `session_*.json` name) and `scenario` (`cast_session` vs `app_runtime`).
- **Watcher process:** `CrashWatcherService` in `:crashwatcher` — reads `settings.json` → `crash`, uploads pending reports (JSON body gzip-compressed), ingests native stub files.
- **Native:** `crash_hook.c` (unwind + `dladdr`) writes stubs to `crash_reports/native/`; watcher converts to schema v1 JSON.
- **User toggle:** Settings drawer → **Send anonymous crash logs** (`AppPreferences.send_anonymous_crash_logs`, default on).

Deploy tuning via app-private `files/settings.json` (see `examples/settings.json`):

```json
"crash": {
  "enabled": "true",
  "upload_url": "https://f0xx.org/app/androidcast_project/crashes/api/upload.php",
  "prune_after_upload": "true",
  "upload_interval": "5m",
  "max_pending": 32
}
```

## Backend

PHP console and ingest API: `examples/crash_reporter/backend/` — see [README](../examples/crash_reporter/backend/README.md).  
Production nginx/hosts: [INFRA.md](INFRA.md).

Roadmap: `examples/crash_reporter/ROADMAP.md`.

## Report files

| Pattern | Example |
|---------|---------|
| Pending crash JSON | `crash_20260520_153045.json` |
| Session stats (compare) | `session_send_20260520_120000.json` |

JSON fields: `schema_version`, `report_id`, `report_file`, `generated_at_epoch_ms`, `scenario`, `runtime_context`, optional `session_context`, `java` / `native`, `device`, `app`, `build`, `fingerprint`.
