Fix usage logging dedupe and reduce stats churn

- batch console log buffer events and support batched SSE log messages
- debounce usage stats update/pending events to reduce UI/runtime churn
- avoid awaiting request-success bookkeeping before returning provider responses
- deduplicate identical usage writes in usageHistory/daily aggregates
- reduce default logger verbosity from DEBUG to INFO (overridable via LOG_LEVEL)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Mink Nguyen
2026-06-26 10:22:20 +07:00
committed by decolua
co-authored by Cursor
parent ec096d2add
commit 0d21668917
7 changed files with 107 additions and 10 deletions
@@ -47,6 +47,11 @@ export default function ConsoleLogClient() {
const next = [...prev, msg.line];
return next.length > CONSOLE_LOG_CONFIG.maxLines ? next.slice(-CONSOLE_LOG_CONFIG.maxLines) : next;
});
} else if (msg.type === "lines") {
setLogs((prev) => {
const next = [...prev, ...msg.lines];
return next.length > CONSOLE_LOG_CONFIG.maxLines ? next.slice(-CONSOLE_LOG_CONFIG.maxLines) : next;
});
} else if (msg.type === "clear") {
setLogs([]);
}
@@ -7,13 +7,14 @@ initConsoleLogCapture();
export async function GET(request) {
const encoder = new TextEncoder();
const emitter = getConsoleEmitter();
const state = { closed: false, send: null, sendClear: null, keepalive: null };
const state = { closed: false, send: null, sendLines: null, sendClear: null, keepalive: null };
// Idempotent: safe to call from request.signal abort, cancel(), or enqueue failure.
const cleanup = () => {
if (state.closed) return;
state.closed = true;
if (state.send) emitter.off("line", state.send);
if (state.sendLines) emitter.off("lines", state.sendLines);
if (state.sendClear) emitter.off("clear", state.sendClear);
if (state.keepalive) clearInterval(state.keepalive);
};
@@ -40,6 +41,15 @@ export async function GET(request) {
}
};
state.sendLines = (lines) => {
if (state.closed || !Array.isArray(lines) || lines.length === 0) return;
try {
controller.enqueue(encoder.encode(`data: ${JSON.stringify({ type: "lines", lines })}\n\n`));
} catch {
cleanup();
}
};
// Notify client when cleared
state.sendClear = () => {
if (state.closed) return;
@@ -51,6 +61,7 @@ export async function GET(request) {
};
emitter.on("line", state.send);
emitter.on("lines", state.sendLines);
emitter.on("clear", state.sendClear);
// Keepalive ping every 25s