import type { ColumnDef } from "@tanstack/react-table"; import React, { useState } from "react"; import { getProviderLogoAndName } from "../provider_info_helpers"; import { Tooltip } from "antd"; import { TimeCell } from "./time_cell"; import { Button, Badge } from "@tremor/react"; import { Eye, EyeOff} from "lucide-react" // Helper to get the appropriate logo URL const getLogoUrl = ( row: LogEntry, provider: string ) => { // Check if mcp_tool_call_metadata exists and contains mcp_server_logo_url if (row.metadata?.mcp_tool_call_metadata?.mcp_server_logo_url) { return row.metadata.mcp_tool_call_metadata.mcp_server_logo_url; } // Fall back to default provider logo return provider ? getProviderLogoAndName(provider).logo : ''; }; export type LogEntry = { request_id: string; api_key: string; team_id: string; model: string; model_id: string; api_base?: string; call_type: string; spend: number; total_tokens: number; prompt_tokens: number; completion_tokens: number; startTime: string; endTime: string; user?: string; end_user?: string; custom_llm_provider?: string; metadata?: Record; cache_hit: string; cache_key?: string; request_tags?: Record; requester_ip_address?: string; messages: string | any[] | Record; response: string | any[] | Record; proxy_server_request?: string | any[] | Record; session_id?: string; status?: string; onKeyHashClick?: (keyHash: string) => void; onSessionClick?: (sessionId: string) => void; }; export const columns: ColumnDef[] = [ { id: "expander", header: () => null, cell: ({ row }) => { // Convert the cell function to a React component to properly use hooks const ExpanderCell = () => { const [localExpanded, setLocalExpanded] = React.useState(row.getIsExpanded()); // Memoize the toggle handler to prevent unnecessary re-renders const toggleHandler = React.useCallback(() => { setLocalExpanded((prev) => !prev); row.getToggleExpandedHandler()(); }, [row]); return row.getCanExpand() ? ( ) : ( ); }; // Return the component return ; }, }, { header: "Time", accessorKey: "startTime", cell: (info: any) => , }, { header: "Status", accessorKey: "metadata.status", cell: (info: any) => { const status = info.getValue() || "Success"; const isSuccess = status.toLowerCase() !== "failure"; return ( {isSuccess ? "Success" : "Failure"} ); }, }, { header: "Session ID", accessorKey: "session_id", cell: (info: any) => { const value = String(info.getValue() || ""); const onSessionClick = info.row.original.onSessionClick; return ( ); }, }, { header: "Request ID", accessorKey: "request_id", cell: (info: any) => ( {String(info.getValue() || "")} ), }, { header: "Cost", accessorKey: "spend", cell: (info: any) => ( ${Number(info.getValue() || 0).toFixed(6)} ), }, { header: "Team Name", accessorKey: "metadata.user_api_key_team_alias", cell: (info: any) => ( {String(info.getValue() || "-")} ), }, { header: "Key Hash", accessorKey: "metadata.user_api_key", cell: (info: any) => { const value = String(info.getValue() || "-"); const onKeyHashClick = info.row.original.onKeyHashClick; return ( onKeyHashClick?.(value)} > {value} ); }, }, { header: "Key Name", accessorKey: "metadata.user_api_key_alias", cell: (info: any) => ( {String(info.getValue() || "-")} ), }, { header: "Model", accessorKey: "model", cell: (info: any) => { const row = info.row.original; const provider = row.custom_llm_provider; const modelName = String(info.getValue() || ""); return (
{provider && ( { const target = e.target as HTMLImageElement; target.style.display = 'none'; }} /> )} {modelName}
); }, }, { header: "Tokens", accessorKey: "total_tokens", cell: (info: any) => { const row = info.row.original; return ( {String(row.total_tokens || "0")} ({String(row.prompt_tokens || "0")}+ {String(row.completion_tokens || "0")}) ); }, }, { header: "Internal User", accessorKey: "user", cell: (info: any) => ( {String(info.getValue() || "-")} ), }, { header: "End User", accessorKey: "end_user", cell: (info: any) => ( {String(info.getValue() || "-")} ), }, { header: "Tags", accessorKey: "request_tags", cell: (info: any) => { const tags = info.getValue(); if (!tags || Object.keys(tags).length === 0) return "-"; const tagEntries = Object.entries(tags); const firstTag = tagEntries[0]; const remainingTags = tagEntries.slice(1); return (
{tagEntries.map(([key, value]) => ( {key}: {String(value)} ))}
} > {firstTag[0]}: {String(firstTag[1])} {remainingTags.length > 0 && ` +${remainingTags.length}`} ); }, }, ]; const formatMessage = (message: any): string => { if (!message) return "N/A"; if (typeof message === "string") return message; if (typeof message === "object") { // Handle the {text, type} object specifically if (message.text) return message.text; if (message.content) return message.content; return JSON.stringify(message); } return String(message); }; // Add this new component for displaying request/response with copy buttons export const RequestResponsePanel = ({ request, response }: { request: any; response: any }) => { const requestStr = typeof request === 'object' ? JSON.stringify(request, null, 2) : String(request || '{}'); const responseStr = typeof response === 'object' ? JSON.stringify(response, null, 2) : String(response || '{}'); const copyToClipboard = async (text: string) => { try { await navigator.clipboard.writeText(text); } catch (err) { console.error('Failed to copy text: ', err); } }; return (

Request

{requestStr}

Response

{responseStr}
); }; // New component for collapsible JSON display const CollapsibleJsonCell = ({ jsonData }: { jsonData: any }) => { const [isExpanded, setIsExpanded] = React.useState(false); const jsonString = JSON.stringify(jsonData, null, 2); if (!jsonData || Object.keys(jsonData).length === 0) { return -; } return (
{isExpanded && (
          {jsonString}
        
)}
); }; export type AuditLogEntry = { id: string; updated_at: string; changed_by: string; changed_by_api_key: string; action: string; table_name: string; object_id: string; before_value: Record; updated_values: Record; } const getActionBadge = (action: string) => { return ( {action} ) } export const auditLogColumns: ColumnDef[] = [ { id: "expander", header: () => null, cell: ({ row }) => { const ExpanderCell = () => { const [localExpanded, setLocalExpanded] = React.useState(row.getIsExpanded()); const toggleHandler = React.useCallback(() => { setLocalExpanded((prev) => !prev); row.getToggleExpandedHandler()(); }, [row]); return row.getCanExpand() ? ( ) : ( ); }; return ; }, }, { header: "Timestamp", accessorKey: "updated_at", cell: (info: any) => , }, { header: "Table Name", accessorKey: "table_name", cell: (info: any) => { const tableName = info.getValue(); let displayValue = tableName; switch (tableName) { case "LiteLLM_VerificationToken": displayValue = "Keys"; break; case "LiteLLM_TeamTable": displayValue = "Teams"; break; case "LiteLLM_OrganizationTable": displayValue = "Organizations"; break; case "LiteLLM_UserTable": displayValue = "Users"; break; case "LiteLLM_ProxyModelTable": displayValue = "Models"; break; default: displayValue = tableName; } return {displayValue}; }, }, { header: "Action", accessorKey: "action", cell: (info: any) => {getActionBadge(info.getValue())}, }, { header: "Changed By", accessorKey: "changed_by", cell: (info: any) => { const changedBy = info.row.original.changed_by; const apiKey = info.row.original.changed_by_api_key; return (
{changedBy}
{apiKey && ( // Only show API key if it exists
{/* Apply max-width and truncate */} {apiKey}
)}
); }, }, { header: "Affected Item ID", accessorKey: "object_id", cell: (props) => { const ObjectIdDisplay = () => { const objectId = props.getValue(); const [copied, setCopied] = useState(false); if (!objectId) return <>-; const handleCopy = async () => { try { await navigator.clipboard.writeText(String(objectId)); setCopied(true); setTimeout(() => setCopied(false), 1500); } catch (err) { console.error("Failed to copy object ID: ", err); } }; return ( {String(objectId)} ); }; return ; }, }, ]