From 7eb2f81d9ebec95ca9f6d84ccb044e657ca5b7b0 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Sat, 28 Feb 2026 15:27:22 -0800 Subject: [PATCH] ui(perf): show all response headers, highlight x-litellm-overhead row --- .../PerformanceDashboardView.tsx | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/ui/litellm-dashboard/src/components/PerformanceDashboard/PerformanceDashboardView.tsx b/ui/litellm-dashboard/src/components/PerformanceDashboard/PerformanceDashboardView.tsx index f6a63a54e3a..7a641670cb8 100644 --- a/ui/litellm-dashboard/src/components/PerformanceDashboard/PerformanceDashboardView.tsx +++ b/ui/litellm-dashboard/src/components/PerformanceDashboard/PerformanceDashboardView.tsx @@ -33,7 +33,7 @@ interface TestResult { proxyTotalMs: number; // proxy-measured total (x-litellm-response-duration-ms) or fallback to wallMs model: string; responseText: string; - headers: Record; + allHeaders: Record; // all response headers } function formatTime(d: Date): string { @@ -57,11 +57,11 @@ async function runTestRequest(accessToken: string, model: string, messages: { ro }); const wallMs = Date.now() - start; const responseText = await resp.text(); - // Capture headers first via forEach (most reliable cross-browser method for custom headers) - const captured: Record = {}; - resp.headers.forEach((v, k) => { if (k.startsWith("x-litellm")) captured[k] = v; }); + // Capture ALL headers via forEach (most reliable cross-browser method for custom headers) + const allHeaders: Record = {}; + resp.headers.forEach((v, k) => { allHeaders[k] = v; }); // Read overhead from captured map — forEach and get() can behave differently for exposed headers - const overheadRaw = captured["x-litellm-overhead-duration-ms"] ?? null; + const overheadRaw = allHeaders["x-litellm-overhead-duration-ms"] ?? null; const overheadParsed = overheadRaw && overheadRaw !== "None" ? parseFloat(overheadRaw) : NaN; const responseDurationRaw = captured["x-litellm-response-duration-ms"] ?? null; const responseDurationParsed = responseDurationRaw && responseDurationRaw !== "None" ? parseFloat(responseDurationRaw) : NaN; @@ -74,7 +74,7 @@ async function runTestRequest(accessToken: string, model: string, messages: { ro proxyTotalMs, model, responseText, - headers: captured, + allHeaders, }; } @@ -547,20 +547,45 @@ export default function PerformanceDashboardView() { )} - {/* x-litellm headers */} - {Object.keys(testResult.headers).length > 0 && ( + {/* Response headers */} + {Object.keys(testResult.allHeaders).length > 0 && (
-

LiteLLM Headers

- - - {Object.entries(testResult.headers).map(([k, v]) => ( - - - +

Response Headers

+
+
{k}{v}
+ + + + - ))} - -
HeaderValue
+ + + {Object.entries(testResult.allHeaders) + .sort(([a], [b]) => { + // x-litellm headers first + const aLitellm = a.startsWith("x-litellm"); + const bLitellm = b.startsWith("x-litellm"); + if (aLitellm && !bLitellm) return -1; + if (!aLitellm && bLitellm) return 1; + return a.localeCompare(b); + }) + .map(([k, v]) => { + const isLitellm = k.startsWith("x-litellm"); + const isOverhead = k === "x-litellm-overhead-duration-ms"; + return ( + + + {k} + + + {v} + + + ); + })} + + +
)}