diff --git a/ui/litellm-dashboard/src/components/per_user_usage.tsx b/ui/litellm-dashboard/src/components/per_user_usage.tsx index 1d074b8a1d0..7c3e3396e62 100644 --- a/ui/litellm-dashboard/src/components/per_user_usage.tsx +++ b/ui/litellm-dashboard/src/components/per_user_usage.tsx @@ -51,6 +51,8 @@ const PerUserUsage: React.FC = ({ selectedTags, formatAbbreviatedNumber, }) => { + // Maximum number of user agent categories to show in charts to prevent color palette overflow + const MAX_USER_AGENTS = 8; const [perUserData, setPerUserData] = useState({ results: [], total_count: 0, @@ -188,6 +190,18 @@ const PerUserUsage: React.FC = ({ { + // Get top user agents by frequency first + const userAgentCounts = new Map(); + perUserData.results.forEach((item: PerUserMetrics) => { + const agent = item.user_agent || "Unknown"; + userAgentCounts.set(agent, (userAgentCounts.get(agent) || 0) + 1); + }); + + const topUserAgents = Array.from(userAgentCounts.entries()) + .sort(([, a], [, b]) => b - a) + .slice(0, MAX_USER_AGENTS) + .map(([agent]) => agent); + // Categorize users by successful request count and user agent const categories = { "1-9 requests": { range: [1, 9], agents: {} as Record }, @@ -198,34 +212,30 @@ const PerUserUsage: React.FC = ({ "100K+ requests": { range: [100000, Infinity], agents: {} as Record }, }; - // Count users in each category by user agent + // Count users in each category by user agent (only for top user agents) perUserData.results.forEach((item: PerUserMetrics) => { const successCount = item.successful_requests; const userAgent = item.user_agent || "Unknown"; - Object.entries(categories).forEach(([categoryName, category]) => { - if (successCount >= category.range[0] && successCount <= category.range[1]) { - if (!category.agents[userAgent]) { - category.agents[userAgent] = 0; + // Only process if this is one of the top user agents + if (topUserAgents.includes(userAgent)) { + Object.entries(categories).forEach(([categoryName, category]) => { + if (successCount >= category.range[0] && successCount <= category.range[1]) { + if (!category.agents[userAgent]) { + category.agents[userAgent] = 0; + } + category.agents[userAgent]++; } - category.agents[userAgent]++; - } - }); + }); + } }); - // Get all unique user agents - const allUserAgents = new Set(); - Object.values(categories).forEach(category => { - Object.keys(category.agents).forEach(agent => allUserAgents.add(agent)); - }); - const userAgentsList = Array.from(allUserAgents).sort(); - // Convert to chart data format for stacked bar chart return Object.entries(categories).map(([categoryName, category]) => { const dataPoint: Record = { category: categoryName }; - // Add count for each user agent - userAgentsList.forEach(agent => { + // Add count for each top user agent + topUserAgents.forEach(agent => { dataPoint[agent] = category.agents[agent] || 0; }); @@ -234,12 +244,18 @@ const PerUserUsage: React.FC = ({ })()} index="category" categories={(() => { - // Get all unique user agents for the chart categories - const allUserAgents = new Set(); + // Count user agents by frequency and get top ones + const userAgentCounts = new Map(); perUserData.results.forEach((item: PerUserMetrics) => { - allUserAgents.add(item.user_agent || "Unknown"); + const agent = item.user_agent || "Unknown"; + userAgentCounts.set(agent, (userAgentCounts.get(agent) || 0) + 1); }); - return Array.from(allUserAgents).sort(); + + // Sort by frequency (most common first) and limit to top MAX_USER_AGENTS + return Array.from(userAgentCounts.entries()) + .sort(([, a], [, b]) => b - a) + .slice(0, MAX_USER_AGENTS) + .map(([agent]) => agent); })()} colors={["blue", "green", "orange", "red", "purple", "yellow", "pink", "indigo"]} valueFormatter={(value: number) => `${value} users`} diff --git a/ui/litellm-dashboard/src/components/user_agent_activity.tsx b/ui/litellm-dashboard/src/components/user_agent_activity.tsx index 139bf1e8dc8..a7157762bd5 100644 --- a/ui/litellm-dashboard/src/components/user_agent_activity.tsx +++ b/ui/litellm-dashboard/src/components/user_agent_activity.tsx @@ -74,6 +74,9 @@ const UserAgentActivity: React.FC = ({ accessToken, userRole, }) => { + // Maximum number of categories to show in charts to prevent color palette overflow + const MAX_CATEGORIES = 10; + // Separate state for each endpoint const [dauData, setDauData] = useState({ results: [] }); const [wauData, setWauData] = useState({ results: [] }); @@ -265,9 +268,9 @@ const UserAgentActivity: React.FC = ({ .map(([tag]) => tag); }; - const allDauTags = getAllTagsForData(dauData.results); - const allWauTags = getAllTagsForData(wauData.results); - const allMauTags = getAllTagsForData(mauData.results); + const allDauTags = getAllTagsForData(dauData.results).slice(0, MAX_CATEGORIES); + const allWauTags = getAllTagsForData(wauData.results).slice(0, MAX_CATEGORIES); + const allMauTags = getAllTagsForData(mauData.results).slice(0, MAX_CATEGORIES); // Prepare daily chart data (DAU) - always show last 7 days const generateDailyChartData = () => {