| 1 | # Reading quality and problem reports |
| 2 | |
| 3 | What Calls logs about calls, and how to find it (spec §15.26, Paul's ruling |
| 4 | of 2026-10-03). The log is the only place these live: nothing is in the |
| 5 | database. CARLOS keeps an app's log for **seven days** (or 50 MiB of |
| 6 | compressed log per app per box, whichever comes first), so look within the |
| 7 | week. |
| 8 | |
| 9 | ## The lines |
| 10 | |
| 11 | Both kinds are JSON lines, so `carlos logs --field k=v` can filter on their |
| 12 | top-level members (it reads fields only from JSON lines; `--grep` matches the |
| 13 | `msg` of a JSON line and nothing else). |
| 14 | |
| 15 | - `calls: quality` (INFO), one per client every 30 s in a call and one at |
| 16 | leave (`final: true`). Top level: `call` (the call tag, shared by everyone |
| 17 | in one call), `peer` (this participation's tag), `app` (web, mac, iphone, |
| 18 | ipad), `version`, `browser`, `browserVersion`, `os`, `osVersion`, |
| 19 | `final`, `seconds`, `remotes`, and the headlines `relay`, `maxLossPct`, |
| 20 | `maxRtt`, `freezes`, `reconnecting`. `report` holds the rest: `devices` |
| 21 | (kinds, never names), `events`, and `peers`, one per remote peer named by |
| 22 | its tag, with `path`, `rtt`, `out`, `in` and `events`. |
| 23 | - `calls: problem report` (WARN), when someone presses Send in Report a |
| 24 | problem: `ref` (what they were shown), `call`, `peer`, the client fields, |
| 25 | `live` (still in the call, or within ten minutes after), `note` and |
| 26 | `parts`. |
| 27 | - `calls: problem report diagnostics` (WARN): the diagnostics text in |
| 28 | `parts` lines, each with `ref`, `part`, `of` and `text`. |
| 29 | |
| 30 | Tags are random. They cannot be turned back into a meeting or a person, and |
| 31 | nothing else in the log can be matched to them. The way from "the call at |
| 32 | 15:40" to a tag is the time. |
| 33 | |
| 34 | ## In the console |
| 35 | |
| 36 | The Carloku console's log view for the app (account `oficina`, app `calls`): |
| 37 | filter the message for `calls: quality` or `calls: problem report`, then by |
| 38 | `call` once you have a tag. |
| 39 | |
| 40 | ## With carlos |
| 41 | |
| 42 | # Every report in the last two hours |
| 43 | carlos logs --app calls --account oficina --since 2h -n 5000 --grep '^calls: (quality|problem report)' |
| 44 | |
| 45 | # One call, every line from every person in it |
| 46 | carlos logs --app calls --account oficina --since 24h -n 5000 --field call=3k2jq7m4xw5zt6ab |
| 47 | |
| 48 | # A problem report someone quoted, with its diagnostics |
| 49 | carlos logs --app calls --account oficina --since 7d -n 5000 --field ref=K7Q2M9PD |
| 50 | |
| 51 | # Every problem report this week |
| 52 | carlos logs --app calls --account oficina --since 7d --grep '^calls: problem report$' |
| 53 | |
| 54 | # Reports from the Mac app, or from one version of it |
| 55 | carlos logs --app calls --account oficina --since 24h --grep '^calls: quality$' --field app=mac |
| 56 | carlos logs --app calls --account oficina --since 24h --grep '^calls: quality$' --field app=mac --field version=0.4.9 |
| 57 | |
| 58 | # Windows where media went through the relay |
| 59 | carlos logs --app calls --account oficina --since 24h --grep '^calls: quality$' --field relay=true |
| 60 | |
| 61 | # A window of time, in UTC (carlos prints and reads UTC) |
| 62 | carlos logs --app calls --account oficina --since 2026-10-03T14:30:00Z --until 2026-10-03T15:00:00Z --grep '^calls: quality$' |
| 63 | |
| 64 | `-n` is at most 5,000 lines; a 30-second cadence is about 120 lines an hour |
| 65 | per person, so narrow `--since` for a busy week. |
| 66 | |
| 67 | ## The summary |
| 68 | |
| 69 | `cmd/quality-summary` turns those lines into an account of each call: |
| 70 | |
| 71 | go run ./cmd/quality-summary --since 3h # every call in the last three hours |
| 72 | go run ./cmd/quality-summary --since 24h --at 15:40 # the call at 15:40, Europe/Dublin, today |
| 73 | go run ./cmd/quality-summary --call 3k2jq7m4xw5zt6ab --since 24h |
| 74 | go run ./cmd/quality-summary --problem K7Q2M9PD --since 7d |
| 75 | carlos logs --app calls --account oficina --since 2h -n 5000 | go run ./cmd/quality-summary |
| 76 | |
| 77 | With nothing piped in it runs `carlos logs` itself. It prints, per call: |
| 78 | |
| 79 | Call callcallcallcall 2026-10-03 15:41:00 – 15:41:30 Europe/Dublin (30s), 2 people, 1 problem report(s) |
| 80 | People |
| 81 | aaaaaa mac 0.4.9 macos 26.0.1 2 reports (input bluetooth, output built-in) |
| 82 | bbbbbb web de04e2d chrome 141.0 on windows 10.0 1 reports |
| 83 | Connections (what the first heard from the second) |
| 84 | aaaaaa ← bbbbbb worst loss 10.0% (video), worst RTT 48 ms, freezes 2 (1.5 s), audio concealed 1.00%, path host→host udp, relay 50% |
| 85 | bbbbbb ← aaaaaa worst loss 0.0%, worst RTT 180 ms, freezes 0 (0.0 s), path relay→srflx tls, relay 100% |
| 86 | Events |
| 87 | 15:41:00 aaaaaa: "Reconnecting to bbbbbb…" (4.2 s) |
| 88 | 15:41:05 bbbbbb: "aaaaaa can't hear you yet" (3.0 s) |
| 89 | 15:41:30 aaaaaa left (final report) |
| 90 | Problem K7Q2M9PD at 15:41:20 from aaaaaa (mac): "video froze" |
| 91 | |
| 92 | "Worst loss" is the worst 30-second window's inbound packet loss, of audio, |
| 93 | camera or screen; "relay" is the share of windows whose path went through the |
| 94 | relay; "audio concealed" is the share of received audio the receiver had to |
| 95 | make up. |
| 96 | |
| 97 | ## Turning it off |
| 98 | |
| 99 | `carlos env set --app calls --account oficina CALLS_QUALITY_REPORTS=off`, |
| 100 | then `carlos restart` (which drops live calls), stops the automatic reports: |
| 101 | the endpoint answers 204 and clients stop sending for that call. Report a |
| 102 | problem keeps working. `carlos env unset --app calls --account oficina |
| 103 | CALLS_QUALITY_REPORTS` and a restart turn them back on. |
| 104 | |