fix(logger): render log timestamps in local time instead of UTC - #1311
fix(logger): render log timestamps in local time instead of UTC#1311MathurAditya724 wants to merge 1 commit into
Conversation
The `[tag 6:28:59 AM]` log prefix (and every other Date display) is rendered by the runtime's notion of "local" time, which comes from ICU. The CLI ships as Node SEA binaries that frequently cannot resolve the OS timezone and silently fall back to UTC, so users saw timestamps hours off from their local clock even with correct OS settings. - Add `src/lib/timezone.ts`: at startup, detect the OS timezone (from /etc/timezone, the /etc/localtime symlink, or `tzutil` on Windows) and set `process.env.TZ` when the runtime fell back to UTC but the OS clock is elsewhere. Falls back to a fixed `Etc/GMT±N` offset zone when no IANA name is available. No-op when TZ is already set or the runtime resolved a real zone. - Override consola's reporter `formatDate` so the prefix derives local time from `getTimezoneOffset()` (robust against stale ICU state) and uses an unambiguous 24-hour `HH:MM:SS` format. - Wire `initTimezone()` into `startCli()` before any Date is formatted.
|
Codecov Results 📊❌ Patch coverage is 70.18%. Project has 5504 uncovered lines. Files with missing lines (3)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
- Coverage 81.58% 81.55% -0.03%
==========================================
Files 428 429 +1
Lines 29774 29831 +57
Branches 19511 19549 +38
==========================================
+ Hits 24289 24327 +38
- Misses 5485 5504 +19
- Partials 2032 2039 +7Generated by Codecov Action |
There was a problem hiding this comment.
took a pass through this — the approach is sound and CI is green. one doc nit:
formatLogTime JSDoc overstates ICU-independence. it says it derives local time "robust even if ICU state is stale" / "reflects the OS offset even in runtimes that cache a stale UTC formatter." but formatLogTime reads getTimezoneOffset(), which shares the exact same tz resolution as toLocaleTimeString() — in the broken UTC-fallback state getTimezoneOffset() returns 0 (that's the premise osReportsNonUtc() relies on), so formatLogTime would render UTC too. its correctness actually depends on initTimezone() having already set TZ so Node re-resolves the offset. worth rewording the comment so a future maintainer doesn't assume the function stands alone — the two fixes are coupled, not independent.
everything else checks out:
initTimezone()decision ladder (TZ-set → real-zone → genuine-UTC → repair) is right, and settingprocess.env.TZat runtime does make Node re-resolvegetTimezoneOffset()(verified).Etc/GMT±Nsign convention matchesgetTimezoneOffset()semantics (positive = west of UTC), and the offset-shift math informatLogTimeis correct.- reporter
formatDateoverride preserves the rest of consola's formatting. initTimezone()sits at the top ofstartCli(), the sole entry path, so nothing formats a Date before repair.
one heads-up, not a blocker: switching [tag 6:28:59 AM] → 24-hour [tag 06:28:59] is a format change beyond the timezone fix. it's disclosed in the description and the unambiguity is nice, just flagging it's a visible behavior change.
|
Jared, let's get the patch coverage above 80%. Also let's verify that the |
Log timestamps (the
[auth.login 6:28:59 AM]prefix) and other Date output were rendered in UTC instead of the user's local time. The CLI ships as Node SEA binaries that often can't resolve the OS timezone and silently fall back to UTC, so a user in US/Pacific saw timestamps hours off from their clock even with correct OS settings.The fix detects the OS timezone at startup and sets
process.env.TZwhen the runtime fell back to UTC, and overrides consola's reporterformatDateto derive local time fromgetTimezoneOffset()in an unambiguous 24-hour format (robust even if ICU state is stale).Testing
vitest run test/lib/timezone.test.ts test/lib/logger.test.ts test/lib/formatters— 975 passing (14 new timezone tests).TZunset in a UTC-fallback runtime, verified the log prefix andtoLocaleTimeString()render correct local time once repaired; confirmedinitTimezone()is a no-op whenTZis set or the machine is genuinely UTC.biome checkclean on changed files;tscclean on changed files (pre-existing generated-code errors unrelated).