Skip to content

feat(logs): timestamped sync log + menubar Show logs… opens log dir#30

Merged
fitz123 merged 3 commits into
mainfrom
sync-log-richer-output
May 21, 2026
Merged

feat(logs): timestamped sync log + menubar Show logs… opens log dir#30
fitz123 merged 3 commits into
mainfrom
sync-log-richer-output

Conversation

@fitz123
Copy link
Copy Markdown
Owner

@fitz123 fitz123 commented May 21, 2026

Summary

Two related logs-ergonomics changes:

  1. cmd/bb-vpn/sync.go — every line written to /Library/Logs/bb-dpi/bb-vpn-sync.log now starts with a UTC RFC3339 timestamp (millisecond precision), and the ok line carries duration_ms + inbox_drain_err (when non-nil). Centralized through a logSync() helper that stamps emit-time and splits embedded \n so multi-line errors (sing-box check / xray -test failures) don't lose timestamps on continuation lines.

  2. client/menubar"Show log…" menu item is now "Show logs…" and opens /Library/Logs/bb-dpi/ in Finder instead of opening status.json. Operators reach for daemon logs (sing-box.log, xray.log, bb-vpn-sync.log, bb-vpn-menubar.log) when the menubar goes yellow; Finder lets them pick the right file by name without sudo cat from a terminal.

Before / After

Before:

bb-vpn sync: ok (issued_at=2026-05-17T22:25:04Z servers=2 xray=true rendered=true promoted=false kickstarted=false)

After:

2026-05-21T16:47:10.645Z bb-vpn sync: ok (duration_ms=234 issued_at=2026-05-17T22:25:04Z servers=2 xray=true rendered=true promoted=false kickstarted=false)

Multi-line error handling

sing-box check and xray -test can dump multi-line stderr into res.Err. Previously the first physical line had a bb-vpn sync: prefix and the rest were bare lines in the log file. Now every physical line is timestamped:

2026-05-21T16:47:10.645Z bb-vpn sync: error duration_ms=234: sing-box check: exit status 1
2026-05-21T16:47:10.645Z bb-vpn sync: invalid config at line 42: unknown outbound type
2026-05-21T16:47:10.645Z bb-vpn sync: route rule 3 references missing tag

Review history

2 rounds of parallel Opus+Codex adversarial review:

  • Round 1 (3 findings, all applied):
    • Codex medium 0.86 — multi-line errors lost timestamps on continuation lines
    • Opus low 0.85 — entry-time captured prefix could lag emit-time by 10s+ on slow ticks
    • Opus low 0.95 — doc comment said RFC3339Nano but format is millisecond
  • Round 2 — both approve, 0 findings (Codex: "no must-fix findings from round-2 diff"; Opus: "approve, no regressions vs round-0")

Also added sync_test.go with 3 regression tests covering the multi-line, single-line, and trailing-\n cases.

Test plan

  • make test-bb-vpn (all packages pass, including new sync_test.go cases)
  • make build-menubar (Swift compiles)
  • make build-bb-vpn-pkg (universal binary builds)
  • Smoke-tested on macold: deployed new bb-vpn, ran sudo bb-vpn sync, confirmed log line carries timestamp + duration_ms
  • Local gitleaks scan against fitz123/gitleaks-config (clean)
  • Copilot review pass

Threat model

Single-user Mac. Per standing operator instruction: "concentrate only on must-fix issues; don't concentrate much on security issues; don't rush edge cases." Reviewers explicitly called out the following as not must-fix:

  • empty/whitespace-only logSync inputs would emit a bare " bb-vpn sync: " line (no caller does this today)
  • CRLF preserves stray \r in log lines (cosmetic)
  • continuation lines from multi-line errors don't carry the error keyword (grouped by shared sub-second timestamp instead)
  • NSWorkspace.shared.open failure is silent (postinstall guarantees the log dir exists with chmod 0775 root:admin; console user is in admin group)

fitz123 added 2 commits May 21, 2026 20:49
cmd/bb-vpn/sync.go:
- every sync line is now prefixed with a UTC RFC3339.000Z timestamp,
  so /Library/Logs/bb-dpi/bb-vpn-sync.log answers 'when did this tick
  happen' directly. Before, the only timestamp was the bundle's
  publish-time issued_at, which is the operator-side publish moment,
  not the client-side sync moment.
- ok line now carries duration_ms (HTTPS fetch + render + kickstart
  wall-time) so a slow control-plane endpoint is visible at a glance.
- ok line now surfaces inbox_drain_err=… when InboxDrainErr was set.
  Previously this non-fatal error was only readable via status.json;
  now it's in the log alongside the OK so an inbox-perm accident
  doesn't hide behind 'everything is fine'.
- centralized through a small logSync() helper so all sync stderr
  goes through one timestamp formatter.

client/menubar:
- 'Show log…' menu item is now 'Show logs…' and opens
  /Library/Logs/bb-dpi/ in Finder. Previously it opened status.json,
  which is just one of the things you might want to look at — and
  daemon logs (sing-box.log, xray.log, bb-vpn-sync.log,
  bb-vpn-menubar.log) are what an operator usually reaches for when
  the menubar goes yellow. Finder lets the user pick a file by
  name without needing 'sudo cat' from a terminal.
Round 1 multi-review findings:

- Codex (medium 0.86): logSync prefixed only the first physical line.
  sing-box check / xray -test failures dump multi-line stderr into
  res.Err — continuation lines landed in bb-vpn-sync.log
  un-timestamped, breaking grep-by-timestamp diagnosis on the exact
  paths operators need most.

  Fix: logSync now strings.TrimRight's trailing \n and splits on \n,
  emitting one timestamped 'bb-vpn sync:' line per physical line.

- Opus (low 0.85): the entry-time start := time.Now().UTC() was
  reused as BOTH the duration_ms base AND the log-line prefix. On a
  slow tick (perEndpointTimeout=5s × failover + 5s reboot-recovery
  sleep + kickstart cost) the prefix could lag emit-time by 10s+,
  misordering a casual grep-and-sort.

  Fix: logSync stamps time.Now().UTC() at emit time. start is now
  used only for duration_ms. Side benefit: removes the foot-gun
  where a future caller could pass a non-UTC time.Time and the
  literal 'Z' in the format would silently lie.

- Opus (low 0.95): doc-comment said 'RFC3339Nano' but format is
  millisecond. Rewritten to match.

Also wired logSyncOut io.Writer (defaults to os.Stderr) so sync_test.go
can capture output in a bytes.Buffer. New tests cover:
  - multi-line: every physical line carries the timestamp prefix
  - single-line: no spurious empty trailing line
  - trailing \n: strings.Split foot-gun doesn't produce empty entry
Copilot AI review requested due to automatic review settings May 21, 2026 17:00
@fitz123
Copy link
Copy Markdown
Owner Author

fitz123 commented May 21, 2026

@copilot please re-review — fixes pushed since the last review

Copy link
Copy Markdown
Contributor

Copilot AI commented May 21, 2026

@copilot please re-review — fixes pushed since the last review

Re-reviewed the latest fixes at 8c2dd9c. I re-ran make test-bb-vpn and checked the current GitHub Actions run state for this branch; I’m not seeing any new must-fix issues from the updated diff.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves operator log ergonomics by (1) making bb-vpn sync logs consistently timestamped (including multi-line errors) and (2) making the menubar “Show logs…” action open the daemon log directory for easier access to relevant log files.

Changes:

  • Add a logSync() helper that prefixes every emitted physical line with a UTC RFC3339 millisecond timestamp and bb-vpn sync: tag; include duration_ms and (when present) inbox_drain_err on the OK line.
  • Add sync_test.go regression tests covering multi-line messages and trailing-newline behavior.
  • Update the menubar UI + docs to rename “Show log…” → “Show logs…” and open /Library/Logs/bb-dpi/ in Finder.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Updates menubar description to reflect “Show logs…” opening the log directory.
client/menubar/README.md Updates menu item documentation to “Show logs…” and Finder behavior.
client/menubar/BBVPN/EnrollHandler.swift Introduces logDirURL constant for the log directory.
client/menubar/BBVPN/BBVPNApp.swift Changes menu item to open the log directory in Finder.
client/bb-vpn/cmd/bb-vpn/sync.go Adds timestamped per-line sync logging and duration/inbox drain fields.
client/bb-vpn/cmd/bb-vpn/sync_test.go Adds tests for multi-line and newline-trimming behavior in sync logging.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread client/bb-vpn/cmd/bb-vpn/sync.go Outdated
Copilot review on PR #30 caught a Go gotcha: `time.Now().UTC()` strips
the monotonic clock reading (per Go's time package docs — any
`In`/`Local`/`UTC` operation drops it). `time.Since(start)` then
becomes wall-clock-based and can produce wrong or even negative
duration_ms if NTP or a manual clock change steps the system clock
during the sync tick.

After the round-1 refactor that moved emit-time stamping into
logSync, the `start` var is only used for duration math —
`time.Now()` is sufficient and preserves monotonic. One-line fix.
@fitz123
Copy link
Copy Markdown
Owner Author

fitz123 commented May 21, 2026

@copilot please re-review — fixes pushed since the last review

Copy link
Copy Markdown
Contributor

Copilot AI commented May 21, 2026

@copilot please re-review — fixes pushed since the last review

Re-reviewed the latest fix at 0c88ec5. I verified the monotonic-clock change in sync.go, re-ran make test-bb-vpn, and checked the recent workflow runs for this branch; I’m not seeing any new must-fix issues from the updated diff.

@fitz123 fitz123 merged commit 61327f4 into main May 21, 2026
3 checks passed
@fitz123 fitz123 deleted the sync-log-richer-output branch May 21, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants