import React, { useState, useEffect } from "react"; import { BarChart, Card, Title, Text, Grid, Col, DateRangePicker, DateRangePickerValue, Table, TableHead, TableRow, TableHeaderCell, TableBody, TableCell, DonutChart, TabPanel, TabGroup, TabList, Tab, TabPanels } from "@tremor/react"; import { Select } from 'antd'; import { ActivityMetrics, processActivityData } from './activity_metrics'; import { SpendMetrics, DailyData } from './usage/types'; import { tagDailyActivityCall, teamDailyActivityCall } from './networking'; interface EntityMetrics { metrics: { spend: number; prompt_tokens: number; completion_tokens: number; cache_read_input_tokens: number; cache_creation_input_tokens: number; total_tokens: number; successful_requests: number; failed_requests: number; api_requests: number; }; metadata: Record; } interface BreakdownMetrics { models: Record; providers: Record; api_keys: Record; entities: Record; } interface ExtendedDailyData extends DailyData { breakdown: BreakdownMetrics; } interface EntitySpendData { results: ExtendedDailyData[]; metadata: { total_spend: number; total_api_requests: number; total_successful_requests: number; total_failed_requests: number; total_tokens: number; }; } interface EntityUsageProps { accessToken: string | null; entityType: 'tag' | 'team'; entityId?: string | null; } const EntityUsage: React.FC = ({ accessToken, entityType, entityId }) => { const [spendData, setSpendData] = useState({ results: [], metadata: { total_spend: 0, total_api_requests: 0, total_successful_requests: 0, total_failed_requests: 0, total_tokens: 0 } }); const modelMetrics = processActivityData(spendData); const [selectedTags, setSelectedTags] = useState([]); const [dateValue, setDateValue] = useState({ from: new Date(Date.now() - 28 * 24 * 60 * 60 * 1000), to: new Date(), }); const fetchSpendData = async () => { if (!accessToken || !dateValue.from || !dateValue.to) return; const startTime = dateValue.from; const endTime = dateValue.to; if (entityType === 'tag') { const data = await tagDailyActivityCall( accessToken, startTime, endTime, 1, selectedTags.length > 0 ? selectedTags : null ); setSpendData(data); } else if (entityType === 'team') { const data = await teamDailyActivityCall( accessToken, startTime, endTime, 1, selectedTags.length > 0 ? selectedTags : null ); setSpendData(data); } else { throw new Error("Invalid entity type"); } }; useEffect(() => { fetchSpendData(); }, [accessToken, dateValue, entityId, selectedTags]); const getTopModels = () => { const modelSpend: { [key: string]: any } = {}; spendData.results.forEach(day => { Object.entries(day.breakdown.models || {}).forEach(([model, metrics]) => { if (!modelSpend[model]) { modelSpend[model] = { spend: 0, requests: 0, successful_requests: 0, failed_requests: 0, tokens: 0 }; } try { modelSpend[model].spend += metrics.metrics.spend; } catch (e) { console.log(`Error adding spend for ${model}: ${e}, got metrics: ${JSON.stringify(metrics)}`); } modelSpend[model].requests += metrics.metrics.api_requests; modelSpend[model].successful_requests += metrics.metrics.successful_requests; modelSpend[model].failed_requests += metrics.metrics.failed_requests; modelSpend[model].tokens += metrics.metrics.total_tokens; }); }); return Object.entries(modelSpend) .map(([model, metrics]) => ({ key: model, ...metrics })) .sort((a, b) => b.spend - a.spend) .slice(0, 5); }; const getTopApiKeys = () => { const apiKeySpend: { [key: string]: any } = {}; spendData.results.forEach(day => { Object.entries(day.breakdown.api_keys || {}).forEach(([key, metrics]) => { if (!apiKeySpend[key]) { apiKeySpend[key] = { key: key, spend: 0, requests: 0, successful_requests: 0, failed_requests: 0, tokens: 0 }; } apiKeySpend[key].spend += metrics.metrics.spend; apiKeySpend[key].requests += metrics.metrics.api_requests; apiKeySpend[key].successful_requests += metrics.metrics.successful_requests; apiKeySpend[key].failed_requests += metrics.metrics.failed_requests; apiKeySpend[key].tokens += metrics.metrics.total_tokens; }); }); return Object.values(apiKeySpend) .sort((a, b) => b.spend - a.spend) .slice(0, 5); }; const getProviderSpend = () => { const providerSpend: { [key: string]: any } = {}; spendData.results.forEach(day => { Object.entries(day.breakdown.providers || {}).forEach(([provider, metrics]) => { if (!providerSpend[provider]) { providerSpend[provider] = { provider, spend: 0, requests: 0, successful_requests: 0, failed_requests: 0, tokens: 0 }; } try { providerSpend[provider].spend += metrics.metrics.spend; providerSpend[provider].requests += metrics.metrics.api_requests; providerSpend[provider].successful_requests += metrics.metrics.successful_requests; providerSpend[provider].failed_requests += metrics.metrics.failed_requests; providerSpend[provider].tokens += metrics.metrics.total_tokens; } catch (e) { console.log(`Error processing provider ${provider}: ${e}`); } }); }); return Object.values(providerSpend) .filter(provider => provider.spend > 0) .sort((a, b) => b.spend - a.spend); }; const getAllTags = () => { const tags = new Set(); spendData.results.forEach(day => { Object.keys(day.breakdown.entities || {}).forEach(tag => { tags.add(tag); }); }); return Array.from(tags).map(tag => ({ label: tag, value: tag })); }; const filterDataByTags = (data: any[]) => { if (selectedTags.length === 0) return data; return data.filter(item => selectedTags.includes(item.entity)); }; const getEntityBreakdown = () => { const entitySpend: { [key: string]: any } = {}; spendData.results.forEach(day => { Object.entries(day.breakdown.entities || {}).forEach(([entity, data]) => { if (!entitySpend[entity]) { entitySpend[entity] = { entity, spend: 0, requests: 0, successful_requests: 0, failed_requests: 0, tokens: 0 }; } entitySpend[entity].spend += data.metrics.spend; entitySpend[entity].requests += data.metrics.api_requests; entitySpend[entity].successful_requests += data.metrics.successful_requests; entitySpend[entity].failed_requests += data.metrics.failed_requests; entitySpend[entity].tokens += data.metrics.total_tokens; }); }); const result = Object.values(entitySpend) .sort((a, b) => b.spend - a.spend); return filterDataByTags(result); }; return (
Select Time Range Filter by {entityType === 'tag' ? 'Tags' : 'Teams'}