From 2f82ea999734d7e200fafa8c22283f0aee27b63f Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Fri, 30 Jan 2026 18:33:01 -0800 Subject: [PATCH] address feedback --- .../LogDetailsDrawer/DrawerHeader.tsx | 52 ++++--- .../LogDetailsDrawer/LogDetailsDrawer.tsx | 128 +++++------------- 2 files changed, 57 insertions(+), 123 deletions(-) diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/DrawerHeader.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/DrawerHeader.tsx index 6b3f7fdaa5b..25fcdf953e9 100644 --- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/DrawerHeader.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/DrawerHeader.tsx @@ -1,5 +1,5 @@ -import { Button, Tag, Tooltip, Typography } from "antd"; -import { CloseOutlined, CopyOutlined, UpOutlined, DownOutlined } from "@ant-design/icons"; +import { Button, Space, Tag, Tooltip, Typography } from "antd"; +import { CloseOutlined, UpOutlined, DownOutlined } from "@ant-design/icons"; import moment from "moment"; import { LogEntry } from "../columns"; import { getProviderLogoAndName } from "../../provider_info_helpers"; @@ -20,7 +20,6 @@ const { Text } = Typography; interface DrawerHeaderProps { log: LogEntry; onClose: () => void; - onCopyRequestId: () => void; onPrevious: () => void; onNext: () => void; statusLabel: string; @@ -35,7 +34,6 @@ interface DrawerHeaderProps { export function DrawerHeader({ log, onClose, - onCopyRequestId, onPrevious, onNext, statusLabel, @@ -61,7 +59,7 @@ export function DrawerHeader({ {/* Row 1: Request ID + Actions */}
- +
@@ -84,7 +82,7 @@ function ModelProviderSection({ providerName?: string; }) { return ( -
+ {providerLogo && ( )} -
+ {model} {providerName && ( - + {providerName} )} -
-
+ + ); } /** - * Request ID display with copy button + * Request ID display with copy functionality */ -function RequestIdSection({ requestId, onCopy }: { requestId: string; onCopy: () => void }) { +function RequestIdSection({ requestId }: { requestId: string }) { return ( -
+
{requestId} - -
); } @@ -161,7 +158,7 @@ function NavigationSection({ }; return ( -
+ }> - -
-
+
); } @@ -195,13 +189,17 @@ function StatusBar({ environment: string; }) { return ( -
+ {statusLabel} Env: {environment} - - {moment(log.startTime).format("MMM D, YYYY h:mm:ss A")} - ({moment(log.startTime).fromNow()}) - -
+ + + {moment(log.startTime).format("MMM D, YYYY h:mm:ss A")} + + + ({moment(log.startTime).fromNow()}) + + + ); } diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailsDrawer.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailsDrawer.tsx index 733cccdf1c9..775ad1a190b 100644 --- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailsDrawer.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/LogDetailsDrawer.tsx @@ -1,6 +1,5 @@ import { useState } from "react"; -import { Drawer, Typography, Button, Descriptions, Card, Tag, Tabs, Alert, message } from "antd"; -import { CopyOutlined } from "@ant-design/icons"; +import { Drawer, Typography, Space, Descriptions, Card, Tag, Tabs, Alert } from "antd"; import { Accordion, AccordionHeader, AccordionBody } from "@tremor/react"; import moment from "moment"; import { LogEntry } from "../columns"; @@ -13,8 +12,16 @@ import { TruncatedValue } from "./TruncatedValue"; import { TokenFlow } from "./TokenFlow"; import { JsonViewer } from "./JsonViewer"; import { DrawerHeader } from "./DrawerHeader"; -import { copyToClipboard } from "./clipboardUtils"; import { useKeyboardNavigation } from "./useKeyboardNavigation"; +import { + formatData, + checkHasMessages, + checkHasResponse, + normalizeGuardrailEntries, + calculateTotalMaskedEntities, + getGuardrailLabel, + checkHasVectorStoreData, +} from "./utils"; import { DRAWER_WIDTH, DRAWER_CONTENT_PADDING, @@ -25,7 +32,7 @@ import { FONT_SIZE_SMALL, FONT_FAMILY_MONO, SPACING_XLARGE, - MESSAGE_REQUEST_ID_COPIED, + SPACING_MEDIUM, } from "./constants"; const { Text } = Typography; @@ -94,11 +101,6 @@ export function LogDetailsDrawer({ const statusColor = metadata.status === "failure" ? ("error" as const) : ("success" as const); const environment = metadata?.user_api_key_team_alias || "default"; - const handleCopyRequestId = () => { - navigator.clipboard.writeText(logEntry.request_id); - message.success(MESSAGE_REQUEST_ID_COPIED); - }; - const getRawRequest = () => { return formatData(logEntry.proxy_server_request || logEntry.messages); }; @@ -135,7 +137,6 @@ export function LogDetailsDrawer({ copyToClipboard(JSON.stringify(data, null, 2), label)} getRawRequest={getRawRequest} getFormattedResponse={getFormattedResponse} /> @@ -214,7 +214,7 @@ export function LogDetailsDrawer({ {/* Metadata Card - Only show if there's metadata */} {logEntry.metadata && Object.keys(logEntry.metadata).length > 0 && ( - copyToClipboard(data, "Metadata")} /> + )} {/* Bottom spacing for scroll area */} @@ -251,27 +251,27 @@ function TagsSection({ tags }: { tags: Record }) { Tags -
+ {Object.entries(tags).map(([key, value]) => ( {key}: {String(value)} ))} -
+
); } function GuardrailLabel({ label, maskedCount }: { label: string; maskedCount: number }) { return ( - <> + {label} {maskedCount > 0 && ( - + {maskedCount} masked )} - + ); } @@ -334,23 +334,20 @@ function MetricsSection({ logEntry, metadata }: { logEntry: LogEntry; metadata: interface RequestResponseSectionProps { hasResponse: boolean; - onCopy: (data: any, label: string) => void; getRawRequest: () => any; getFormattedResponse: () => any; } function RequestResponseSection({ hasResponse, - onCopy, getRawRequest, getFormattedResponse, }: RequestResponseSectionProps) { const [activeTab, setActiveTab] = useState(TAB_REQUEST); - const handleCopy = () => { + const getCopyText = () => { const data = activeTab === TAB_REQUEST ? getRawRequest() : getFormattedResponse(); - const label = activeTab === TAB_REQUEST ? "Request" : "Response"; - onCopy(data, label); + return JSON.stringify(data, null, 2); }; return ( @@ -365,15 +362,13 @@ function RequestResponseSection({ activeKey={activeTab} onChange={(key) => setActiveTab(key as typeof TAB_REQUEST | typeof TAB_RESPONSE)} tabBarExtraContent={ - + /> } items={[ { @@ -409,7 +404,7 @@ function RequestResponseSection({ ); } -function MetadataSection({ metadata, onCopy }: { metadata: Record; onCopy: (data: string) => void }) { +function MetadataSection({ metadata }: { metadata: Record }) { return (
; bordered={false} style={{ marginBottom: 0 }} extra={ - + } >
;
   );
 }
 
-// ============================================================================
-// Helper Functions
-// ============================================================================
-
-function formatData(input: any) {
-  if (typeof input === "string") {
-    try {
-      return JSON.parse(input);
-    } catch {
-      return input;
-    }
-  }
-  return input;
-}
-
-function checkHasMessages(messages: any): boolean {
-  if (!messages) return false;
-  if (Array.isArray(messages)) return messages.length > 0;
-  if (typeof messages === "object") return Object.keys(messages).length > 0;
-  return false;
-}
-
-function checkHasResponse(response: any): boolean {
-  if (!response) return false;
-  return Object.keys(formatData(response)).length > 0;
-}
-
-function normalizeGuardrailEntries(guardrailInfo: any): any[] {
-  if (Array.isArray(guardrailInfo)) return guardrailInfo;
-  if (guardrailInfo) return [guardrailInfo];
-  return [];
-}
-
-function calculateTotalMaskedEntities(entries: any[]): number {
-  return entries.reduce((sum, entry) => {
-    const maskedCounts = entry?.masked_entity_count;
-    if (!maskedCounts) return sum;
-    return (
-      sum +
-      Object.values(maskedCounts).reduce((acc, count) => (typeof count === "number" ? acc + count : acc), 0)
-    );
-  }, 0);
-}
-
-function getGuardrailLabel(entries: any[]): string {
-  if (entries.length === 0) return "-";
-  if (entries.length === 1) return entries[0]?.guardrail_name ?? "-";
-  return `${entries.length} guardrails`;
-}
-
-function checkHasVectorStoreData(metadata: Record): boolean {
-  return (
-    metadata.vector_store_request_metadata &&
-    Array.isArray(metadata.vector_store_request_metadata) &&
-    metadata.vector_store_request_metadata.length > 0
-  );
-}