This commit is contained in:
Ishaan Jaffer 2026-01-30 15:44:49 -08:00
parent 5f07635310
commit 2014bcf9d8
2 changed files with 62 additions and 74 deletions

View file

@ -59,7 +59,7 @@ export const CostBreakdownViewer: React.FC<CostBreakdownViewerProps> = ({
} }
return ( return (
<div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden"> <div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden mb-6">
<Accordion> <Accordion>
<AccordionHeader className="p-4 border-b hover:bg-gray-50 transition-colors text-left"> <AccordionHeader className="p-4 border-b hover:bg-gray-50 transition-colors text-left">
<div className="flex items-center justify-between w-full"> <div className="flex items-center justify-between w-full">

View file

@ -1,6 +1,7 @@
import { useState } from "react"; import { useState } from "react";
import { Drawer, Typography, Button, Descriptions, Card, Tag, Tabs, Alert, message, Collapse } from "antd"; import { Drawer, Typography, Button, Descriptions, Card, Tag, Tabs, Alert, message } from "antd";
import { CopyOutlined, DownOutlined } from "@ant-design/icons"; import { CopyOutlined } from "@ant-design/icons";
import { Accordion, AccordionHeader, AccordionBody } from "@tremor/react";
import moment from "moment"; import moment from "moment";
import { LogEntry } from "../columns"; import { LogEntry } from "../columns";
import { formatNumberWithCommas } from "@/utils/dataUtils"; import { formatNumberWithCommas } from "@/utils/dataUtils";
@ -150,7 +151,7 @@ export function LogDetailsDrawer({
showIcon showIcon
message="Request Failed" message="Request Failed"
description={<ErrorDescription errorInfo={errorInfo} />} description={<ErrorDescription errorInfo={errorInfo} />}
style={{ marginBottom: SPACING_XLARGE }} className="mb-6"
/> />
)} )}
@ -160,7 +161,7 @@ export function LogDetailsDrawer({
)} )}
{/* Request Details Section */} {/* Request Details Section */}
<div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden" style={{ marginBottom: SPACING_XLARGE }}> <div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden mb-6">
<Card title="Request Details" size="small" bordered={false} style={{ marginBottom: 0 }}> <Card title="Request Details" size="small" bordered={false} style={{ marginBottom: 0 }}>
<Descriptions column={2} size="small"> <Descriptions column={2} size="small">
<Descriptions.Item label="Model">{logEntry.model}</Descriptions.Item> <Descriptions.Item label="Model">{logEntry.model}</Descriptions.Item>
@ -191,7 +192,11 @@ export function LogDetailsDrawer({
<CostBreakdownViewer costBreakdown={metadata?.cost_breakdown} totalSpend={logEntry.spend || 0} /> <CostBreakdownViewer costBreakdown={metadata?.cost_breakdown} totalSpend={logEntry.spend || 0} />
{/* Configuration Info Message - Show when data is missing */} {/* Configuration Info Message - Show when data is missing */}
<ConfigInfoMessage show={missingData} onOpenSettings={onOpenSettings} /> {missingData && (
<div className="mb-6">
<ConfigInfoMessage show={missingData} onOpenSettings={onOpenSettings} />
</div>
)}
{/* Request/Response JSON - Collapsible */} {/* Request/Response JSON - Collapsible */}
<RequestResponseSection <RequestResponseSection
@ -239,7 +244,7 @@ function ErrorDescription({ errorInfo }: { errorInfo: any }) {
function TagsSection({ tags }: { tags: Record<string, any> }) { function TagsSection({ tags }: { tags: Record<string, any> }) {
return ( return (
<div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden p-4" style={{ marginBottom: SPACING_XLARGE }}> <div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden p-4 mb-6">
<Text strong style={{ display: "block", marginBottom: 8, fontSize: 16 }}> <Text strong style={{ display: "block", marginBottom: 8, fontSize: 16 }}>
Tags Tags
</Text> </Text>
@ -274,7 +279,7 @@ function MetricsSection({ logEntry, metadata }: { logEntry: LogEntry; metadata:
metadata.additional_usage_values.cache_read_input_tokens > 0); metadata.additional_usage_values.cache_read_input_tokens > 0);
return ( return (
<div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden" style={{ marginBottom: SPACING_XLARGE }}> <div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden mb-6">
<Card title="Metrics" size="small" bordered={false} style={{ marginBottom: 0 }}> <Card title="Metrics" size="small" bordered={false} style={{ marginBottom: 0 }}>
<Descriptions column={2} size="small"> <Descriptions column={2} size="small">
<Descriptions.Item label="Tokens"> <Descriptions.Item label="Tokens">
@ -338,7 +343,6 @@ function RequestResponseSection({
getFormattedResponse, getFormattedResponse,
}: RequestResponseSectionProps) { }: RequestResponseSectionProps) {
const [activeTab, setActiveTab] = useState<typeof TAB_REQUEST | typeof TAB_RESPONSE>(TAB_REQUEST); const [activeTab, setActiveTab] = useState<typeof TAB_REQUEST | typeof TAB_RESPONSE>(TAB_REQUEST);
const [isOpen, setIsOpen] = useState<boolean>(true);
const handleCopy = () => { const handleCopy = () => {
const data = activeTab === TAB_REQUEST ? getRawRequest() : getFormattedResponse(); const data = activeTab === TAB_REQUEST ? getRawRequest() : getFormattedResponse();
@ -347,78 +351,62 @@ function RequestResponseSection({
}; };
return ( return (
<div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden" style={{ marginBottom: SPACING_XLARGE }}> <div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden mb-6">
<Collapse <Accordion>
activeKey={isOpen ? ["request-response"] : []} <AccordionHeader className="p-4 border-b hover:bg-gray-50 transition-colors text-left">
onChange={(keys) => setIsOpen(keys.includes("request-response"))} <h3 className="text-lg font-medium text-gray-900">Request & Response</h3>
expandIcon={({ isActive }) => <DownOutlined rotate={isActive ? 180 : 0} />} </AccordionHeader>
bordered={false} <AccordionBody className="px-0">
items={[ <Tabs
{ activeKey={activeTab}
key: "request-response", onChange={(key) => setActiveTab(key as typeof TAB_REQUEST | typeof TAB_RESPONSE)}
label: <span style={{ fontSize: 16, fontWeight: 500 }}>Request & Response</span>, tabBarExtraContent={
children: ( <Button
<Tabs type="text"
activeKey={activeTab} size="small"
onChange={(key) => setActiveTab(key as typeof TAB_REQUEST | typeof TAB_RESPONSE)} icon={<CopyOutlined />}
tabBarExtraContent={ onClick={handleCopy}
<Button disabled={activeTab === TAB_RESPONSE && !hasResponse}
type="text" >
size="small" Copy
icon={<CopyOutlined />} </Button>
onClick={handleCopy} }
disabled={activeTab === TAB_RESPONSE && !hasResponse} items={[
> {
Copy key: TAB_REQUEST,
</Button> label: "Request",
} children: (
items={[ <div style={{ padding: SPACING_XLARGE }}>
{ <JsonViewer data={getRawRequest()} mode="formatted" />
key: TAB_REQUEST, </div>
label: "Request", ),
children: ( },
<div style={{ paddingTop: SPACING_XLARGE }}> {
<JsonViewer data={getRawRequest()} mode="formatted" /> key: TAB_RESPONSE,
label: "Response",
children: (
<div style={{ padding: SPACING_XLARGE }}>
{hasResponse ? (
<JsonViewer data={getFormattedResponse()} mode="formatted" />
) : (
<div style={{ textAlign: "center", padding: 20, color: "#999", fontStyle: "italic" }}>
Response data not available
</div> </div>
), )}
}, </div>
{ ),
key: TAB_RESPONSE, },
label: "Response", ]}
children: ( />
<div style={{ paddingTop: SPACING_XLARGE }}> </AccordionBody>
{hasResponse ? ( </Accordion>
<JsonViewer data={getFormattedResponse()} mode="formatted" />
) : (
<div style={{ textAlign: "center", padding: 20, color: "#999", fontStyle: "italic" }}>
Response data not available
</div>
)}
</div>
),
},
]}
/>
),
},
]}
styles={{
header: {
padding: "16px",
borderBottom: "1px solid #f0f0f0",
},
body: {
padding: 0,
},
}}
/>
</div> </div>
); );
} }
function MetadataSection({ metadata, onCopy }: { metadata: Record<string, any>; onCopy: (data: string) => void }) { function MetadataSection({ metadata, onCopy }: { metadata: Record<string, any>; onCopy: (data: string) => void }) {
return ( return (
<div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden" style={{ marginBottom: SPACING_XLARGE }}> <div className="bg-white rounded-lg shadow w-full max-w-full overflow-hidden mb-6">
<Card <Card
title="Metadata" title="Metadata"
size="small" size="small"