feat(desktop): in-app Diagnostics — bounded log capture, verbose toggle, scrubbed export (#180) - #274
Merged
Merged
Conversation
…le, scrubbed export (#180) The client had NO logging at all (no seam, no error handlers, empty catches) — when something broke in the field there was nothing to attach to a bug report. - DiagnosticsService: app-scoped bounded ring buffer (4k lines, capped messages, in-memory only until export). Warnings/errors/lifecycle always captured; an opt-in persisted VERBOSE toggle (off by default) adds HTTP request traces and media_kit/mpv player logs. Safe to leave on — bounded by construction. - Capture-time scrubbing: JWT shapes, Bearer values, token/password/secret query params and JSON fields are redacted BEFORE storage (nothing token-shaped ever sits in the buffer), plus a second pass over the assembled export. Server identity recorded as host:port only. - Global error funnels in main(): FlutterError.onError (chained) + PlatformDispatcher.onError. - HTTP: TimeoutClient.send is the single choke point — logs method + bare path + status + duration only (never query strings, headers, or bodies); failures always, routine traffic verbose-only. - Player hooks at the live tile, maximized pane, and playback panes: error stream always, mpv log stream verbose-only. - Settings -> Diagnostics pane: verbose toggle, 'Export logs…' (native save dialog via the picker guard), 'Copy to clipboard', line count. Scope: desktop client only — the Android share-sheet export and the server- side admin diagnostics bundle from #180 are follow-ups. Part of #180 Signed-off-by: badbread <badbread@users.noreply.github.com>
Signed-off-by: badbread <badbread@users.noreply.github.com>
Signed-off-by: badbread <badbread@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Desktop half of #180. Context that motivated doing this now: today's LPR black-screen mystery died unexplained precisely because the client keeps no logs — recon confirmed the desktop app had zero logging: no seam, no
FlutterError.onError, emptycatch (_) {}everywhere. This turns "something broke, no idea why" into an attachable file.What
DiagnosticsService(new): app-scoped bounded ring buffer (4k lines, capped message length, memory-only until export — nothing written to disk unasked). Warnings/errors/lifecycle always captured; a persisted verbose toggle (off by default) adds HTTP traces + mpv player logs. Bounded by construction, so it's safe to leave on while reproducing.Bearervalues,token/password/secret/api_keyquery params and JSON fields are redacted before storage — nothing token-shaped ever even sits in the buffer — plus a second pass over the assembled export. Server identity is recorded ashost:portonly. Every redaction shape is pinned by unit tests (test/diagnostics_scrub_test.dart, 5/5 green on the build box).main():FlutterError.onError(chained to the default) +PlatformDispatcher.onError.TimeoutClient.send): method + bare path + status + duration only — never query strings (?token=), headers, or bodies. Failures always; routine traffic verbose-only.stream.erroralways; mpv's own log stream verbose-only. This is exactly the evidence that was missing for the LPR incident.Scope
Desktop only. The Android share-sheet export and the server-side admin diagnostics bundle from #180 are follow-ups — the issue stays open to track them.
Verify
flutter analyzeclean;flutter test test/diagnostics_scrub_test.dart5/5.eyJ/Bearer/token=and find only[REDACTED].Part of #180 (leave open for Android + server bundle).