diff --git a/gui/src/pages/Logs.tsx b/gui/src/pages/Logs.tsx index 554884137..83a5de3bd 100644 --- a/gui/src/pages/Logs.tsx +++ b/gui/src/pages/Logs.tsx @@ -280,12 +280,12 @@ function statusColor(status: number): string { return "var(--amber)"; } -function formatLogTimestamp(ts: number, localeTag?: string): string { - return new Date(ts).toLocaleTimeString(localeTag); +function formatLogTimestamp(ts: number, localeTag?: string, timeZone?: string): string { + return new Date(ts).toLocaleTimeString(localeTag, timeZone ? { timeZone } : undefined); } -function formatLogDateTime(ts: number, localeTag?: string): string { - return new Date(ts).toLocaleString(localeTag); +function formatLogDateTime(ts: number, localeTag?: string, timeZone?: string): string { + return new Date(ts).toLocaleString(localeTag, timeZone ? { timeZone } : undefined); } function modelTitle(log: LogEntry): string { @@ -333,6 +333,7 @@ export default function Logs({ apiBase }: { apiBase: string }) { const { t, locale } = useI18n(); const cachedLogs = readSessionListCache(logsCacheKey(apiBase)); const [logs, setLogs] = useState(() => cachedLogs ?? []); + const [serverTimeZone, setServerTimeZone] = useState(); const [loading, setLoading] = useState(() => !(cachedLogs && cachedLogs.length > 0)); const [error, setError] = useState(null); const [autoRefresh, setAutoRefresh] = useState(true); @@ -370,8 +371,11 @@ export default function Logs({ apiBase }: { apiBase: string }) { try { const res = await fetch(`${apiBase}/api/logs?limit=2000`); if (!res.ok) throw new Error(`${res.status} ${res.statusText}`.trim()); - const body = await res.json() as LogEntry[] | { logs?: LogEntry[] }; + const body = await res.json() as LogEntry[] | { logs?: LogEntry[]; timeZone?: string }; const next = Array.isArray(body) ? body : (body.logs ?? []); + if (!Array.isArray(body) && typeof body.timeZone === "string" && body.timeZone.trim()) { + setServerTimeZone(body.timeZone.trim()); + } setLogs(next); writeSessionListCache(logsCacheKey(apiBase), next); setError(null); @@ -592,7 +596,7 @@ export default function Logs({ apiBase }: { apiBase: string }) { data-index={virtualRow.index} ref={rowVirtualizer.measureElement} > - {formatLogTimestamp(log.timestamp, localeTag)} + {formatLogTimestamp(log.timestamp, localeTag, serverTimeZone)} {(() => { const tokenTotal = displayContextTokenTotal(log); @@ -679,6 +683,7 @@ export default function Logs({ apiBase }: { apiBase: string }) { detailInfo={detailInfo} localeCode={locale} localeTag={localeTag} + serverTimeZone={serverTimeZone} t={t} onClose={() => setDetail(null)} onFilterConversation={id => { @@ -704,12 +709,13 @@ function useModalDialog(open: boolean) { } function LogDetailDialog({ - detail, detailInfo, localeCode, localeTag, t, onClose, onFilterConversation, + detail, detailInfo, localeCode, localeTag, serverTimeZone, t, onClose, onFilterConversation, }: { detail: LogEntry; detailInfo: ReturnType | null; localeCode: string; localeTag?: string; + serverTimeZone?: string; t: TFn; onClose: () => void; onFilterConversation?: (conversationId: string) => void; @@ -751,7 +757,7 @@ function LogDetailDialog({

{t("logs.detail.section.basic")}

- {t("logs.col.time")}{formatLogDateTime(detail.timestamp, localeTag)} + {t("logs.col.time")}{formatLogDateTime(detail.timestamp, localeTag, serverTimeZone)} {t("logs.col.request")} {detail.requestId ?? "\u2014"} diff --git a/src/server/management/config-routes.ts b/src/server/management/config-routes.ts index 3801ca849..be02055d3 100644 --- a/src/server/management/config-routes.ts +++ b/src/server/management/config-routes.ts @@ -110,6 +110,7 @@ export async function handleConfigRoutes(ctx: ManagementContext): Promise