# Reading quality and problem reports

What Calls logs about calls, and how to find it (spec §15.26, Paul's ruling
of 2026-10-03). The log is the only place these live: nothing is in the
database. CARLOS keeps an app's log for **seven days** (or 50 MiB of
compressed log per app per box, whichever comes first), so look within the
week.

## The lines

Both kinds are JSON lines, so `carlos logs --field k=v` can filter on their
top-level members (it reads fields only from JSON lines; `--grep` matches the
`msg` of a JSON line and nothing else).

- `calls: quality` (INFO), one per client every 30 s in a call and one at
  leave (`final: true`). Top level: `call` (the call tag, shared by everyone
  in one call), `peer` (this participation's tag), `app` (web, mac, iphone,
  ipad), `version`, `browser`, `browserVersion`, `os`, `osVersion`,
  `final`, `seconds`, `remotes`, and the headlines `relay`, `maxLossPct`,
  `maxRtt`, `freezes`, `reconnecting`. `report` holds the rest: `devices`
  (kinds, never names), `events`, and `peers`, one per remote peer named by
  its tag, with `path`, `rtt`, `out`, `in` and `events`.
- `calls: problem report` (WARN), when someone presses Send in Report a
  problem: `ref` (what they were shown), `call`, `peer`, the client fields,
  `live` (still in the call, or within ten minutes after), `note` and
  `parts`.
- `calls: problem report diagnostics` (WARN): the diagnostics text in
  `parts` lines, each with `ref`, `part`, `of` and `text`.

Tags are random. They cannot be turned back into a meeting or a person, and
nothing else in the log can be matched to them. The way from "the call at
15:40" to a tag is the time.

## In the console

The Carloku console's log view for the app (account `oficina`, app `calls`):
filter the message for `calls: quality` or `calls: problem report`, then by
`call` once you have a tag.

## With carlos

    # Every report in the last two hours
    carlos logs --app calls --account oficina --since 2h -n 5000 --grep '^calls: (quality|problem report)'

    # One call, every line from every person in it
    carlos logs --app calls --account oficina --since 24h -n 5000 --field call=3k2jq7m4xw5zt6ab

    # A problem report someone quoted, with its diagnostics
    carlos logs --app calls --account oficina --since 7d -n 5000 --field ref=K7Q2M9PD

    # Every problem report this week
    carlos logs --app calls --account oficina --since 7d --grep '^calls: problem report$'

    # Reports from the Mac app, or from one version of it
    carlos logs --app calls --account oficina --since 24h --grep '^calls: quality$' --field app=mac
    carlos logs --app calls --account oficina --since 24h --grep '^calls: quality$' --field app=mac --field version=0.4.9

    # Windows where media went through the relay
    carlos logs --app calls --account oficina --since 24h --grep '^calls: quality$' --field relay=true

    # A window of time, in UTC (carlos prints and reads UTC)
    carlos logs --app calls --account oficina --since 2026-10-03T14:30:00Z --until 2026-10-03T15:00:00Z --grep '^calls: quality$'

`-n` is at most 5,000 lines; a 30-second cadence is about 120 lines an hour
per person, so narrow `--since` for a busy week.

## The summary

`cmd/quality-summary` turns those lines into an account of each call:

    go run ./cmd/quality-summary --since 3h            # every call in the last three hours
    go run ./cmd/quality-summary --since 24h --at 15:40 # the call at 15:40, Europe/Dublin, today
    go run ./cmd/quality-summary --call 3k2jq7m4xw5zt6ab --since 24h
    go run ./cmd/quality-summary --problem K7Q2M9PD --since 7d
    carlos logs --app calls --account oficina --since 2h -n 5000 | go run ./cmd/quality-summary

With nothing piped in it runs `carlos logs` itself. It prints, per call:

    Call callcallcallcall  2026-10-03 15:41:00 – 15:41:30 Europe/Dublin (30s), 2 people, 1 problem report(s)
      People
        aaaaaa  mac 0.4.9  macos 26.0.1  2 reports  (input bluetooth, output built-in)
        bbbbbb  web de04e2d  chrome 141.0 on windows 10.0  1 reports
      Connections (what the first heard from the second)
        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%
        bbbbbb ← aaaaaa  worst loss 0.0%, worst RTT 180 ms, freezes 0 (0.0 s), path relay→srflx tls, relay 100%
      Events
        15:41:00  aaaaaa: "Reconnecting to bbbbbb…" (4.2 s)
        15:41:05  bbbbbb: "aaaaaa can't hear you yet" (3.0 s)
        15:41:30  aaaaaa left (final report)
      Problem K7Q2M9PD at 15:41:20 from aaaaaa (mac): "video froze"

"Worst loss" is the worst 30-second window's inbound packet loss, of audio,
camera or screen; "relay" is the share of windows whose path went through the
relay; "audio concealed" is the share of received audio the receiver had to
make up.

## Turning it off

`carlos env set --app calls --account oficina CALLS_QUALITY_REPORTS=off`,
then `carlos restart` (which drops live calls), stops the automatic reports:
the endpoint answers 204 and clients stop sending for that call. Report a
problem keeps working. `carlos env unset --app calls --account oficina
CALLS_QUALITY_REPORTS` and a restart turn them back on.
