mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-06 02:23:35 +00:00
Merge pull request #22122 from BerriAI/litellm_ui_spend_logs_duration
[Feature] UI - Logs: Use backend request_duration_ms and make Duration sortable
This commit is contained in:
+1
-1
@@ -23,7 +23,7 @@ const createLogEntry = (overrides: Partial<LogEntry> = {}): LogEntry =>
|
||||
startTime: "2025-11-14T00:00:00Z",
|
||||
endTime: "2025-11-14T00:00:01Z",
|
||||
cache_hit: "miss",
|
||||
duration: 1,
|
||||
request_duration_ms: 1000,
|
||||
messages: [{ role: "user", content: "hello" }],
|
||||
response: { choices: [{ message: { content: "hi" } }] },
|
||||
metadata: { status: "success" },
|
||||
|
||||
@@ -283,7 +283,7 @@ function MetricsSection({ logEntry, metadata }: { logEntry: LogEntry; metadata:
|
||||
/>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Cost">${formatNumberWithCommas(logEntry.spend || 0, 8)}</Descriptions.Item>
|
||||
<Descriptions.Item label="Duration">{logEntry.duration?.toFixed(3)} s</Descriptions.Item>
|
||||
<Descriptions.Item label="Duration">{logEntry.request_duration_ms != null ? (logEntry.request_duration_ms / 1000).toFixed(3) : "-"} s</Descriptions.Item>
|
||||
|
||||
{hasCacheActivity && (
|
||||
<>
|
||||
|
||||
@@ -47,8 +47,8 @@ interface TraceEventRowProps {
|
||||
function TraceEventRow({ row, isSelected, onClick }: TraceEventRowProps) {
|
||||
const isMcp = MCP_CALL_TYPES.includes(row.call_type);
|
||||
const durationValue =
|
||||
row.duration != null
|
||||
? row.duration.toFixed(3)
|
||||
row.request_duration_ms != null
|
||||
? (row.request_duration_ms / 1000).toFixed(3)
|
||||
: row.startTime && row.endTime
|
||||
? ((Date.parse(row.endTime) - Date.parse(row.startTime)) / 1000).toFixed(3)
|
||||
: "-";
|
||||
@@ -125,7 +125,7 @@ export function LogDetailsDrawer({
|
||||
return allSessionLogs
|
||||
.map((row) => ({
|
||||
...row,
|
||||
duration: (Date.parse(row.endTime) - Date.parse(row.startTime)) / 1000,
|
||||
request_duration_ms: row.request_duration_ms ?? (Date.parse(row.endTime) - Date.parse(row.startTime)),
|
||||
}))
|
||||
.sort((a, b) => {
|
||||
const aIsMcp = MCP_CALL_TYPES.includes(a.call_type) ? 1 : 0;
|
||||
|
||||
@@ -21,7 +21,7 @@ const baseLogEntry: LogEntry = {
|
||||
startTime: "2025-11-14T00:00:00Z",
|
||||
endTime: "2025-11-14T00:00:00Z",
|
||||
cache_hit: "miss",
|
||||
duration: 1,
|
||||
request_duration_ms: 1000,
|
||||
messages: [{ role: "user", content: "hello" }],
|
||||
response: { status: "ok" },
|
||||
metadata: {
|
||||
|
||||
@@ -14,6 +14,7 @@ export const LOGS_SORT_FIELD_MAP = {
|
||||
startTime: "startTime",
|
||||
spend: "spend",
|
||||
total_tokens: "total_tokens",
|
||||
request_duration_ms: "request_duration_ms",
|
||||
} as const;
|
||||
|
||||
export type LogsSortField = keyof typeof LOGS_SORT_FIELD_MAP;
|
||||
@@ -61,7 +62,7 @@ export type LogEntry = {
|
||||
proxy_server_request?: string | any[] | Record<string, any>;
|
||||
session_id?: string;
|
||||
status?: string;
|
||||
duration?: number;
|
||||
request_duration_ms?: number;
|
||||
session_total_count?: number;
|
||||
session_total_spend?: number;
|
||||
mcp_tool_call_count?: number;
|
||||
@@ -231,13 +232,28 @@ export const createColumns = (sortProps?: LogsSortProps): ColumnDef<LogEntry>[]
|
||||
},
|
||||
},
|
||||
{
|
||||
header: "Duration (s)",
|
||||
accessorKey: "duration",
|
||||
cell: (info: any) => (
|
||||
<Tooltip title={String(info.getValue() || "-")}>
|
||||
<span className="max-w-[15ch] truncate block">{String(info.getValue() || "-")}</span>
|
||||
</Tooltip>
|
||||
),
|
||||
header: sortProps
|
||||
? () => (
|
||||
<SortableHeader
|
||||
label="Duration (s)"
|
||||
field="request_duration_ms"
|
||||
sortBy={sortProps.sortBy}
|
||||
sortOrder={sortProps.sortOrder}
|
||||
onSortChange={sortProps.onSortChange}
|
||||
/>
|
||||
)
|
||||
: "Duration (s)",
|
||||
accessorKey: "request_duration_ms",
|
||||
cell: (info: any) => {
|
||||
const ms = info.getValue();
|
||||
if (ms == null) return <span>-</span>;
|
||||
const seconds = (ms / 1000).toFixed(2);
|
||||
return (
|
||||
<Tooltip title={`${ms}ms`}>
|
||||
<span className="max-w-[15ch] truncate block">{seconds}</span>
|
||||
</Tooltip>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
header: "Team Name",
|
||||
|
||||
@@ -55,7 +55,7 @@ const baseLogEntry: LogEntry = {
|
||||
startTime: "2025-11-14T00:00:00Z",
|
||||
endTime: "2025-11-14T00:00:00Z",
|
||||
cache_hit: "miss",
|
||||
duration: 1,
|
||||
request_duration_ms: 1000,
|
||||
messages: [{ role: "user", content: "hello" }],
|
||||
response: { status: "ok" },
|
||||
metadata: {
|
||||
|
||||
@@ -341,7 +341,7 @@ export default function SpendLogsTable({
|
||||
const sessionComposition = log.session_id ? sessionCompositionById[log.session_id] : undefined;
|
||||
return {
|
||||
...log,
|
||||
duration: (Date.parse(log.endTime) - Date.parse(log.startTime)) / 1000,
|
||||
request_duration_ms: log.request_duration_ms,
|
||||
session_llm_count: sessionComposition?.llm ?? undefined,
|
||||
session_mcp_count: sessionComposition?.mcp ?? undefined,
|
||||
onKeyHashClick: (keyHash: string) => setSelectedKeyIdInfoView(keyHash),
|
||||
@@ -943,7 +943,7 @@ export function RequestViewer({ row, onOpenSettings }: { row: Row<LogEntry>; onO
|
||||
</div>
|
||||
<div className="flex">
|
||||
<span className="font-medium w-1/3">Duration:</span>
|
||||
<span>{row.original.duration} s.</span>
|
||||
<span>{row.original.request_duration_ms != null ? (row.original.request_duration_ms / 1000).toFixed(3) : "-"} s.</span>
|
||||
</div>
|
||||
{row.original.metadata?.litellm_overhead_time_ms !== undefined && (
|
||||
<div className="flex">
|
||||
|
||||
Reference in New Issue
Block a user