mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-11 14:22:48 +00:00
Top virtual keys show N select
This commit is contained in:
+19
-6
@@ -4,7 +4,7 @@ import KeyInfoView from "../../../templates/key_info_view";
|
||||
import { keyInfoV1Call } from "../../../networking";
|
||||
import { transformKeyInfo } from "../../../key_team_helpers/transform_key_info";
|
||||
import { DataTable } from "../../../view_logs/table";
|
||||
import { Tooltip } from "antd";
|
||||
import { Segmented, Tooltip } from "antd";
|
||||
import { Button } from "@tremor/react";
|
||||
import { formatNumberWithCommas } from "../../../../utils/dataUtils";
|
||||
import { TagUsage } from "../../types";
|
||||
@@ -15,9 +15,11 @@ interface TopKeyViewProps {
|
||||
topKeys: any[];
|
||||
teams: any[] | null;
|
||||
showTags?: boolean;
|
||||
topKeysLimit: number;
|
||||
setTopKeysLimit: (limit: number) => void;
|
||||
}
|
||||
|
||||
const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = false }) => {
|
||||
const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = false, topKeysLimit, setTopKeysLimit }) => {
|
||||
const { accessToken, userRole, userId: userID, premiumUser } = useAuthorized();
|
||||
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
||||
const [selectedKey, setSelectedKey] = useState<string | null>(null);
|
||||
@@ -178,7 +180,17 @@ const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = fals
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-4 flex justify-end items-center">
|
||||
<div className="mb-4 flex justify-between items-center">
|
||||
<Segmented
|
||||
options={[
|
||||
{ label: "5", value: 5 },
|
||||
{ label: "10", value: 10 },
|
||||
{ label: "25", value: 25 },
|
||||
{ label: "50", value: 50 },
|
||||
]}
|
||||
value={topKeysLimit}
|
||||
onChange={(value) => setTopKeysLimit(value as number)}
|
||||
/>
|
||||
<div className="flex space-x-2">
|
||||
<button
|
||||
onClick={() => setViewMode("table")}
|
||||
@@ -196,9 +208,10 @@ const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = fals
|
||||
</div>
|
||||
|
||||
{viewMode === "chart" ? (
|
||||
<div className="relative">
|
||||
<div className="relative max-h-[600px] overflow-y-auto">
|
||||
<BarChart
|
||||
className="mt-4 h-40 cursor-pointer hover:opacity-90"
|
||||
className="mt-4 cursor-pointer hover:opacity-90"
|
||||
style={{ height: topKeysLimit * 52 }}
|
||||
data={processedTopKeys}
|
||||
index="display_key_alias"
|
||||
categories={["spend"]}
|
||||
@@ -234,7 +247,7 @@ const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = fals
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="border rounded-lg overflow-hidden">
|
||||
<div className="border rounded-lg overflow-hidden max-h-[600px] overflow-y-auto">
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={topKeys}
|
||||
|
||||
@@ -95,6 +95,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
const [showCustomerBanner, setShowCustomerBanner] = useState(true);
|
||||
const [usageView, setUsageView] = useState<UsageOption>("global");
|
||||
const [showAgentBanner, setShowAgentBanner] = useState(true);
|
||||
const [topKeysLimit, setTopKeysLimit] = useState<number>(5);
|
||||
const getAllTags = async () => {
|
||||
if (!accessToken) {
|
||||
return;
|
||||
@@ -116,7 +117,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
const totalSpend = userSpendData.metadata?.total_spend || 0;
|
||||
|
||||
// Calculate top models from the breakdown data
|
||||
const getTopModels = () => {
|
||||
const getTopModels = (limit: number = 5) => {
|
||||
const modelSpend: { [key: string]: MetricWithMetadata } = {};
|
||||
userSpendData.results.forEach((day) => {
|
||||
Object.entries(day.breakdown.models || {}).forEach(([model, metrics]) => {
|
||||
@@ -159,10 +160,10 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
tokens: metrics.metrics.total_tokens,
|
||||
}))
|
||||
.sort((a, b) => b.spend - a.spend)
|
||||
.slice(0, 5);
|
||||
.slice(0, limit);
|
||||
};
|
||||
|
||||
const getTopModelGroups = () => {
|
||||
const getTopModelGroups = (limit: number = 5) => {
|
||||
const modelGroupSpend: { [key: string]: MetricWithMetadata } = {};
|
||||
userSpendData.results.forEach((day) => {
|
||||
Object.entries(day.breakdown.model_groups || {}).forEach(([modelGroup, metrics]) => {
|
||||
@@ -206,7 +207,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
tokens: metrics.metrics.total_tokens,
|
||||
}))
|
||||
.sort((a, b) => b.spend - a.spend)
|
||||
.slice(0, 5);
|
||||
.slice(0, limit);
|
||||
};
|
||||
|
||||
// Calculate provider spend from the breakdown data
|
||||
@@ -254,7 +255,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
};
|
||||
|
||||
// Calculate top API keys from the breakdown data
|
||||
const getTopKeys = () => {
|
||||
const getTopKeys = (limit: number = 5) => {
|
||||
const keySpend: { [key: string]: KeyMetricWithMetadata } = {};
|
||||
userSpendData.results.forEach((day) => {
|
||||
Object.entries(day.breakdown.api_keys || {}).forEach(([key, metrics]) => {
|
||||
@@ -300,7 +301,7 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
spend: metrics.metrics.spend,
|
||||
}))
|
||||
.sort((a, b) => b.spend - a.spend)
|
||||
.slice(0, 5);
|
||||
.slice(0, limit);
|
||||
};
|
||||
|
||||
const fetchUserSpendData = useCallback(async () => {
|
||||
@@ -576,7 +577,12 @@ const UsagePage: React.FC<UsagePageProps> = ({ teams, organizations }) => {
|
||||
<Col numColSpan={1}>
|
||||
<Card className="h-full">
|
||||
<Title>Top Virtual Keys</Title>
|
||||
<TopKeyView topKeys={getTopKeys()} teams={null} />
|
||||
<TopKeyView
|
||||
topKeys={getTopKeys(topKeysLimit)}
|
||||
teams={null}
|
||||
topKeysLimit={topKeysLimit}
|
||||
setTopKeysLimit={setTopKeysLimit}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user