import moment from "moment"; import { useQuery } from "@tanstack/react-query"; import { useState, useRef, useEffect } from "react"; import { uiSpendLogsCall } from "../networking"; import { DataTable } from "./table"; import { columns, LogEntry } from "./columns"; import { Row } from "@tanstack/react-table"; interface SpendLogsTableProps { accessToken: string | null; token: string | null; userRole: string | null; userID: string | null; } interface PaginatedResponse { data: LogEntry[]; total: number; page: number; page_size: number; total_pages: number; } export default function SpendLogsTable({ accessToken, token, userRole, userID, }: SpendLogsTableProps) { const [searchTerm, setSearchTerm] = useState(""); const [showFilters, setShowFilters] = useState(false); const [showColumnDropdown, setShowColumnDropdown] = useState(false); const [currentPage, setCurrentPage] = useState(1); const [pageSize] = useState(50); const dropdownRef = useRef(null); const filtersRef = useRef(null); const quickSelectRef = useRef(null); // New state variables for Start and End Time const [startTime, setStartTime] = useState( moment().subtract(24, "hours").format("YYYY-MM-DDTHH:mm") ); const [endTime, setEndTime] = useState( moment().format("YYYY-MM-DDTHH:mm") ); // Add these new state variables at the top with other useState declarations const [isCustomDate, setIsCustomDate] = useState(false); const [quickSelectOpen, setQuickSelectOpen] = useState(false); const [tempTeamId, setTempTeamId] = useState(""); const [tempKeyHash, setTempKeyHash] = useState(""); const [selectedTeamId, setSelectedTeamId] = useState(""); const [selectedKeyHash, setSelectedKeyHash] = useState(""); const [selectedFilter, setSelectedFilter] = useState("Team ID"); // Close dropdown when clicking outside useEffect(() => { function handleClickOutside(event: MouseEvent) { if ( dropdownRef.current && !dropdownRef.current.contains(event.target as Node) ) { setShowColumnDropdown(false); } if ( filtersRef.current && !filtersRef.current.contains(event.target as Node) ) { setShowFilters(false); } if ( quickSelectRef.current && !quickSelectRef.current.contains(event.target as Node) ) { setQuickSelectOpen(false); } } document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, []); const logs = useQuery({ queryKey: [ "logs", "table", currentPage, pageSize, startTime, endTime, selectedTeamId, selectedKeyHash, ], queryFn: async () => { if (!accessToken || !token || !userRole || !userID) { console.log("Missing required auth parameters"); return { data: [], total: 0, page: 1, page_size: pageSize, total_pages: 0, }; } // Convert times to UTC before formatting const formattedStartTime = moment(startTime).utc().format("YYYY-MM-DD HH:mm:ss"); const formattedEndTime = isCustomDate ? moment(endTime).utc().format("YYYY-MM-DD HH:mm:ss") : moment().utc().format("YYYY-MM-DD HH:mm:ss"); return await uiSpendLogsCall( accessToken, selectedKeyHash || undefined, selectedTeamId || undefined, undefined, formattedStartTime, formattedEndTime, currentPage, pageSize ); }, enabled: !!accessToken && !!token && !!userRole && !!userID, refetchInterval: 5000, refetchIntervalInBackground: true, }); if (!accessToken || !token || !userRole || !userID) { console.log( "got None values for one of accessToken, token, userRole, userID", ); return null; } const filteredData = logs.data?.data?.filter((log) => { const matchesSearch = !searchTerm || log.request_id.includes(searchTerm) || log.model.includes(searchTerm) || (log.user && log.user.includes(searchTerm)); // No need for additional filtering since we're now handling this in the API call return matchesSearch; }) || []; // Add this function to handle manual refresh const handleRefresh = () => { logs.refetch(); }; // Add this function to format the time range display const getTimeRangeDisplay = () => { if (isCustomDate) { return `${moment(startTime).format('MMM D, h:mm A')} - ${moment(endTime).format('MMM D, h:mm A')}`; } const now = moment(); const start = moment(startTime); const diffMinutes = now.diff(start, 'minutes'); if (diffMinutes <= 15) return 'Last 15 Minutes'; if (diffMinutes <= 60) return 'Last Hour'; const diffHours = now.diff(start, 'hours'); if (diffHours <= 4) return 'Last 4 Hours'; if (diffHours <= 24) return 'Last 24 Hours'; if (diffHours <= 168) return 'Last 7 Days'; return `${start.format('MMM D')} - ${now.format('MMM D')}`; }; return (

Request Logs

setSearchTerm(e.target.value)} />
{showFilters && (
Where
{showColumnDropdown && (
{["Team ID", "Key Hash"].map((option) => ( ))}
)}
{ if (selectedFilter === "Team ID") { setTempTeamId(e.target.value); } else { setTempKeyHash(e.target.value); } }} />
)}
{quickSelectOpen && (
{[ { label: "Last 15 Minutes", value: 15, unit: "minutes" }, { label: "Last Hour", value: 1, unit: "hours" }, { label: "Last 4 Hours", value: 4, unit: "hours" }, { label: "Last 24 Hours", value: 24, unit: "hours" }, { label: "Last 7 Days", value: 7, unit: "days" }, ].map((option) => ( ))}
)}
{isCustomDate && (
{ setStartTime(e.target.value); setCurrentPage(1); }} className="px-3 py-2 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
to
{ setEndTime(e.target.value); setCurrentPage(1); }} className="px-3 py-2 border rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
)}
Showing{" "} {logs.isLoading ? "..." : logs.data ? (currentPage - 1) * pageSize + 1 : 0}{" "} -{" "} {logs.isLoading ? "..." : logs.data ? Math.min(currentPage * pageSize, logs.data.total) : 0}{" "} of{" "} {logs.isLoading ? "..." : logs.data ? logs.data.total : 0}{" "} results
Page {logs.isLoading ? "..." : currentPage} of{" "} {logs.isLoading ? "..." : logs.data ? logs.data.total_pages : 1}
true} />
); } function RequestViewer({ row }: { row: Row }) { const formatData = (input: any) => { if (typeof input === "string") { try { return JSON.parse(input); } catch { return input; } } return input; }; return (
{/* Combined Info Card */}

Request Details

Request ID: {row.original.request_id}
Api Key: {row.original.api_key}
Team ID: {row.original.team_id}
Model: {row.original.model}
Api Base: {row.original.api_base}
Call Type: {row.original.call_type}
Spend: {row.original.spend}
Total Tokens: {row.original.total_tokens}
Prompt Tokens: {row.original.prompt_tokens}
Completion Tokens: {row.original.completion_tokens}
Start Time: {row.original.startTime}
End Time: {row.original.endTime}
Cache Hit: {row.original.cache_hit}
Cache Key: {row.original.cache_key}
{row?.original?.requester_ip_address && (
Request IP Address: {row?.original?.requester_ip_address}
)}
{/* Request Card */}

Request Tags

          {JSON.stringify(formatData(row.original.request_tags), null, 2)}
        
{/* Request Card */}

Request

{/*
*/}
          {JSON.stringify(formatData(row.original.messages), null, 2)}
        
{/* Response Card */}

Response

{/* */}
          {JSON.stringify(formatData(row.original.response), null, 2)}
        
{/* Metadata Card */} {row.original.metadata && Object.keys(row.original.metadata).length > 0 && (

Metadata

{/*
*/}
              {JSON.stringify(row.original.metadata, null, 2)}
            
)}
); }