From 51dee73a5d3e4b35045c656b573f32b7aebf2a06 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 31 May 2026 06:09:03 +0100 Subject: [PATCH] perf: cache log timestamp formatters --- src/logging/timestamps.ts | 48 +++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/src/logging/timestamps.ts b/src/logging/timestamps.ts index df78ee55cf1..44f292d29b3 100644 --- a/src/logging/timestamps.ts +++ b/src/logging/timestamps.ts @@ -1,10 +1,21 @@ +const validTimeZoneCache = new Map(); +const timestampFormatterCache = new Map(); +let hostTimeZone: string | undefined; + export function isValidTimeZone(tz: string): boolean { + const cached = validTimeZoneCache.get(tz); + if (cached !== undefined) { + return cached; + } + let valid = false; try { new Intl.DateTimeFormat("en", { timeZone: tz }).format(); - return true; + valid = true; } catch { - return false; + valid = false; } + validTimeZoneCache.set(tz, valid); + return valid; } type TimestampStyle = "short" | "medium" | "long"; @@ -18,7 +29,7 @@ function resolveEffectiveTimeZone(timeZone?: string): string { const explicit = timeZone ?? process.env.TZ; return explicit && isValidTimeZone(explicit) ? explicit - : Intl.DateTimeFormat().resolvedOptions().timeZone; + : (hostTimeZone ??= Intl.DateTimeFormat().resolvedOptions().timeZone); } function formatOffset(offsetRaw: string): string { @@ -26,18 +37,25 @@ function formatOffset(offsetRaw: string): string { } function getTimestampParts(date: Date, timeZone?: string) { - const fmt = new Intl.DateTimeFormat("en", { - timeZone: resolveEffectiveTimeZone(timeZone), - year: "numeric", - month: "2-digit", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - second: "2-digit", - hour12: false, - fractionalSecondDigits: 3 as 1 | 2 | 3, - timeZoneName: "longOffset", - }); + const effectiveTimeZone = resolveEffectiveTimeZone(timeZone); + let fmt = timestampFormatterCache.get(effectiveTimeZone); + if (!fmt) { + // Log timestamps are formatted on hot paths; Intl construction is much + // costlier than formatToParts, while timezone rules remain process-stable. + fmt = new Intl.DateTimeFormat("en", { + timeZone: effectiveTimeZone, + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + hour12: false, + fractionalSecondDigits: 3 as 1 | 2 | 3, + timeZoneName: "longOffset", + }); + timestampFormatterCache.set(effectiveTimeZone, fmt); + } const parts = Object.fromEntries(fmt.formatToParts(date).map((part) => [part.type, part.value])); return {