Skip to content

Commit d5cd0c6

Browse files
authored
fix(logs): live duration shows ∅ for in-flight requests on page refresh (#434)
## Problem The live duration calculator in the Logs page showed **Duration: ∅** for in-flight requests after a page refresh, even though it worked correctly for requests arriving via the SSE event stream. ## Root Cause Two issues compounded: 1. **Backend**: The REST API response coerced `durationMs: null` → `0` via `?? 0` in `usage-storage.ts`. The DB correctly stores `null` for pending requests, but the API response lost that signal. 2. **Frontend**: The live duration check used `log.durationMs != null` to decide whether to use the stored value or compute live. When `durationMs` was `0` (from the backend coercion), `0 != null` is `true`, so `formatMs(0)` was called — which returns `'∅'`. This only manifested on page refresh (REST API path). For SSE-arrived requests, `durationMs` was `undefined` (not in the partial record), so `!= null` correctly fell through to the live calculation. ## Changes - **Backend** (`usage-storage.ts`): Stop coercing `durationMs` null→0 in REST API response; let `null` flow through - **Frontend** (`api.ts`): Change `durationMs` type from `number` to `number | null` to reflect reality - **Frontend** (`Logs.tsx`): Use `!= null && > 0` guard so both `null` and `0` fall through to `Date.now() - startTime` - **Frontend** (`useModels.ts`, `useProviderForm.tsx`): Add null guards on `reduce` calls for the new nullable type
1 parent 041937c commit d5cd0c6

5 files changed

Lines changed: 11 additions & 7 deletions

File tree

packages/backend/src/services/usage-storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ export class UsageStorageService extends EventEmitter {
654654
costSource: row.costSource,
655655
costMetadata: row.costMetadata,
656656
startTime: row.startTime,
657-
durationMs: row.durationMs ?? 0,
657+
durationMs: row.durationMs,
658658
isStreamed: !!row.isStreamed,
659659
responseStatus: row.responseStatus ?? '',
660660
ttftMs: row.ttftMs,

packages/frontend/src/hooks/useModels.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ export const useModels = () => {
169169

170170
const allSuccess = results.every((r) => r.success);
171171
const firstError = results.find((r) => !r.success);
172-
const totalDuration = results.reduce((sum, r) => sum + r.durationMs, 0);
172+
const totalDuration = results.reduce((sum, r) => sum + (r.durationMs || 0), 0);
173173
const avgDuration = Math.round(totalDuration / results.length);
174174

175175
setTestStates((prev) => ({

packages/frontend/src/hooks/useProviderForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ export function useProviderForm() {
384384
);
385385
const allSuccess = results.every((r) => r.success);
386386
const firstError = results.find((r) => !r.success);
387-
const totalDuration = results.reduce((sum, r) => sum + r.durationMs, 0);
387+
const totalDuration = results.reduce((sum, r) => sum + (r.durationMs || 0), 0);
388388
const avgDuration = Math.round(totalDuration / results.length);
389389
setTestStates((prev) => ({
390390
...prev,

packages/frontend/src/lib/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ export interface UsageRecord {
461461
costSource?: string;
462462
costMetadata?: string;
463463
startTime: number;
464-
durationMs: number;
464+
durationMs: number | null;
465465
isStreamed: boolean;
466466
responseStatus: string;
467467
ttftMs?: number;
@@ -2241,7 +2241,7 @@ export const api = {
22412241
): Promise<{
22422242
success: boolean;
22432243
error?: string;
2244-
durationMs: number;
2244+
durationMs: number | null;
22452245
response?: string;
22462246
apiType?: string;
22472247
}> => {

packages/frontend/src/pages/Logs.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,9 @@ export const Logs = () => {
654654
? progressMapRef.current.get(log.requestId)
655655
: undefined;
656656
const liveDuration = formatMs(
657-
log.durationMs != null ? log.durationMs : Date.now() - log.startTime
657+
log.durationMs != null && log.durationMs > 0
658+
? log.durationMs
659+
: Date.now() - log.startTime
658660
);
659661
if (progress) {
660662
return (
@@ -1240,7 +1242,9 @@ export const Logs = () => {
12401242
? progressMapRef.current.get(log.requestId)
12411243
: undefined;
12421244
const liveDuration = formatMs(
1243-
log.durationMs != null ? log.durationMs : Date.now() - log.startTime
1245+
log.durationMs != null && log.durationMs > 0
1246+
? log.durationMs
1247+
: Date.now() - log.startTime
12441248
);
12451249
if (progress) {
12461250
return (

0 commit comments

Comments
 (0)