ba762f6d60
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
76 lines
5.8 KiB
Markdown
76 lines
5.8 KiB
Markdown
# felhom.eu — task reports
|
|
|
|
> **Overwrite** this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md); the scripts history lives in [scripts/CHANGELOG.md](scripts/CHANGELOG.md).
|
|
|
|
## TASK — hub v0.43.0: remote app-log diagnostics (copyable issues + context + on-demand log tails) — 2026-07-10
|
|
|
|
**Pairs with controller v0.111.0.** Deployed via GitOps (image 0.43.0, manifest bump, ArgoCD hard-refresh
|
|
+ sync): **Synced/Healthy**, rollout complete, clean startup log. Motivated live: Peti's CWA issue was
|
|
tooltip-only unreadable and context-free, with no remote way to see the app's logs.
|
|
|
|
### What shipped (Parts A, C, D-hub, F, G, H of the spec)
|
|
|
|
- **A — readable/copyable issues** (`app_detail.html`): Known Issues rows click-to-expand — full message
|
|
in a wrapping monospace `<pre>` + Copy button (clipboard API + execCommand fallback); fingerprint,
|
|
severity, first/last seen, and the explicit affected-customers list (linked) in the body. Tooltip
|
|
truncation killed.
|
|
- **C — context store/render** (`store/telemetry.go`): additive `context` + `context_customer` columns;
|
|
`upsertAppIssue` stores context on INSERT, adopts a later one ONLY while the stored one is empty
|
|
(**first capture wins**). Rendered as "Context around first occurrence — from <customer>", copyable.
|
|
Nil-safe with pre-v0.111 reports.
|
|
- **D — on-demand log tail (pull-based, hub half)**: per-app **Request log tail** button on the customer
|
|
page (+ "tail pending" badge) → `log_tail_requests` (one per (customer,app), re-click refreshes) + a
|
|
customer-visible `log_tail_requested` event (transparency). Report ACK advertises
|
|
`log_tail_requests: [app…]` (same additive omit-when-empty pattern as escrow); the arriving
|
|
`log_tails` are stored in `app_log_tails` (transient, last 2 per app), request **cleared in the same
|
|
tx (consume-once)**. Ordered viewer with line numbers (`log_tail.html`) + Download .log; reads are
|
|
customer-scoped (cross-customer → 404). NO hub→controller push channel.
|
|
- **F — bug fix**: the 24h/7d/30d selector now filters Known Issues too — `GetAppIssues` gained the same
|
|
`since` cutoff the Memory Trend uses (it previously had NO time filter at all).
|
|
- **G — deletion → dismissal.** **Diagnosis recorded (spec asked a/b):** the delete handler was NOT
|
|
broken — `DeleteAppIssues`/`ByIDs` execute correct SQL. Deletion is futile because the controller
|
|
re-scans a rolling 15-minute log window every report and re-upserts any still-occurring fingerprint
|
|
with a fresh scan-time `last_seen` minutes later → cause **(b)**. Implemented `dismissed_at`:
|
|
Dismiss Selected/All, dismissed rows out of the default view ("Show dismissed" toggle shows them
|
|
dimmed + badged), and un-dismiss ONLY on `excluded.last_seen > dismissed_at` (a re-sent old window
|
|
stays hidden; a genuinely new occurrence resurfaces — recurrence is never silently swallowed).
|
|
- **H — per-customer scoping**: `?customer=<id>` filters Known Issues by `affected_customers`
|
|
membership (header: "filtered: <customer>"; period links carry the filter); the customer page's App
|
|
Telemetry rows link to that filtered view (the drill-down). Fleet view unchanged; count column
|
|
labeled "Occurrences (all customers)" (per-customer counts noted as a future refinement, not built).
|
|
|
|
### Tests + red-proofs (all four failed exactly as designed; restored green)
|
|
|
|
- **G:** dismissal guard replaced with unconditional clear → `old-window re-report RESURRECTED the
|
|
dismissed issue` → FAIL.
|
|
- **F:** range predicate neutered → `10d-old issue visible in the 24h view` → FAIL.
|
|
- **C:** first-capture-wins CASE replaced with overwrite → `empty-context upsert clobbered the stored
|
|
context: []string(nil)` → FAIL.
|
|
- **D consume-once:** request-DELETE removed from `SaveAppLogTail` → store test AND the API ACK
|
|
round-trip both FAILED (`request survived fulfillment — the controller would ship tails every cycle`).
|
|
- Non-hollow coverage: late-context adoption; warn-no-context; occurrence counting; tail
|
|
request/refresh/fulfill/prune-to-2/cross-customer-scoping; ACK omit-when-empty baseline + full
|
|
round-trip; render tests (expanded row incl. full message + context + provenance + dismiss controls +
|
|
"filtered:" header; customer page request button/pending badge/tails section via the REAL handler;
|
|
ordered tail view + text/plain attachment download + cross-customer 404).
|
|
|
|
### Live validation (demo, operator-free legs)
|
|
|
|
Synthetic error injected into the demo controller container's log stream (neighbor lines +
|
|
`password=hunter2` + an `ERROR: … LC0111 …` line). On the next report cycle (14:22:34Z, 3.7KB vs the
|
|
2.5KB baseline) the hub DB showed the row in `app_log_issues`: severity `error`,
|
|
`context_customer=demo-felhom`, and an **exactly-ordered 11-line context** containing
|
|
`diag: connecting with password=[REDACTED] to fake backend` — **live proof the secret never left the
|
|
box** and that capture/wire/store all work end-to-end. (Method: report-cycle → `/api/v1/report` ingest →
|
|
hub DB read via kubectl cp; DB copy deleted after. The UI click-path is render-tested — the hub operator
|
|
password is Viktor-only, CC cannot log in.)
|
|
|
|
### Operator follow-up (1 click)
|
|
|
|
- **Live tail round-trip:** on `hub.felhom.eu/customers/demo-felhom` → App Telemetry →
|
|
**Request log tail** on the `felhom-controller` row; the ordered tail + Download .log appears within
|
|
≤2 report cycles (≤30 min), and the "tail pending" badge clears (consume-once). The mechanism is
|
|
fully red-proof-tested on both repos; only the click itself is operator-gated.
|
|
- Per spec: do NOT request tails from Peti's box in this task — Viktor's call once he's read this.
|
|
Peti's CWA issues are now fully readable (full message + context) on the next report cycles.
|