From 29002b4f3bf19367cf31726772dee25ab038f534 Mon Sep 17 00:00:00 2001 From: Achintya Rajan Date: Fri, 10 Oct 2025 15:48:02 -0700 Subject: [PATCH] extracted ModelAnalyticsTab.tsx --- .../components/ModelAnalyticsTab.tsx | 316 ++++++++++++++++++ .../models-and-endpoints/model_dashboard.tsx | 275 ++------------- 2 files changed, 339 insertions(+), 252 deletions(-) create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/ModelAnalyticsTab.tsx diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/ModelAnalyticsTab.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/ModelAnalyticsTab.tsx new file mode 100644 index 00000000000..a7eac9e7663 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/ModelAnalyticsTab.tsx @@ -0,0 +1,316 @@ +import { + AreaChart, + BarChart, + Button, + Card, + Col, + DateRangePickerValue, + Grid, + Select, + SelectItem, + Subtitle, + Tab, + TabGroup, + Table, + TableBody, + TableCell, + TableHead, + TableHeaderCell, + TableRow, + TabList, + TabPanel, + TabPanels, + Text, + Title, +} from "@tremor/react"; +import UsageDatePicker from "@/components/shared/usage_date_picker"; +import { Popover } from "antd"; +import { FilterIcon } from "@heroicons/react/outline"; +import TimeToFirstToken from "@/components/model_metrics/time_to_first_token"; +import React, { ReactNode } from "react"; +import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; + +interface GlobalExceptionActivityData { + sum_num_rate_limit_exceptions: number; + daily_data: { date: string; num_rate_limit_exceptions: number }[]; +} + +interface ModelAnalyticsTabProps { + dateValue: DateRangePickerValue; + setDateValue: (dateValue: DateRangePickerValue) => void; + selectedModelGroup: string | null; + availableModelGroups: string[]; + FilterByContent: ReactNode; + setShowAdvancedFilters: (showAdvancedFilters: boolean) => void; + updateModelMetrics: ( + modelGroup: string | null, + startTime: Date | undefined, + endTime: Date | undefined, + ) => Promise; + modelMetrics: any[]; + modelMetricsCategories: any[]; + streamingModelMetrics: any[]; + streamingModelMetricsCategories: any[]; + customTooltip: any; + slowResponsesData: any[]; + modelExceptions: any[]; + globalExceptionData: GlobalExceptionActivityData; + allExceptions: any[]; + globalExceptionPerDeployment: any[]; +} + +const ModelAnalyticsTab = ({ + dateValue, + setDateValue, + selectedModelGroup, + availableModelGroups, + FilterByContent, + setShowAdvancedFilters, + updateModelMetrics, + modelMetrics, + modelMetricsCategories, + streamingModelMetrics, + streamingModelMetricsCategories, + customTooltip, + slowResponsesData, + modelExceptions, + globalExceptionData, + allExceptions, + globalExceptionPerDeployment, +}: ModelAnalyticsTabProps) => { + const { premiumUser } = useAuthorized(); + + return ( + + + + { + setDateValue(value); + updateModelMetrics(selectedModelGroup, value.from, value.to); + }} + /> + + + Select Model Group + + + + + + + + + + + + + + + Avg. Latency per Token + Time to first token + + + +

(seconds/token)

+ + average Latency for successfull requests divided by the total tokens + + {modelMetrics && modelMetricsCategories && ( + + )} +
+ + + +
+
+
+ + + + + + + Deployment + Success Responses + + Slow Responses

Success Responses taking 600+s

+
+
+
+ + {slowResponsesData.map((metric, idx) => ( + + {metric.api_base} + {metric.total_count} + {metric.slow_count} + + ))} + +
+
+ +
+ + + All Exceptions for {selectedModelGroup} + + + + + + + + All Up Rate Limit Errors (429) for {selectedModelGroup} + + + + Num Rate Limit Errors {globalExceptionData.sum_num_rate_limit_exceptions} + + console.log(v)} + /> + + + + + + {premiumUser ? ( + <> + {globalExceptionPerDeployment.map((globalActivity, index) => ( + + {globalActivity.api_base ? globalActivity.api_base : "Unknown API Base"} + + + + Num Rate Limit Errors (429) {globalActivity.sum_num_rate_limit_exceptions} + + console.log(v)} + /> + + + + ))} + + ) : ( + <> + {globalExceptionPerDeployment && + globalExceptionPerDeployment.length > 0 && + globalExceptionPerDeployment.slice(0, 1).map((globalActivity, index) => ( + + ✨ Rate Limit Errors by Deployment +

Upgrade to see exceptions for all deployments

+ + + {globalActivity.api_base} + + + + Num Rate Limit Errors {globalActivity.sum_num_rate_limit_exceptions} + + console.log(v)} + /> + + + +
+ ))} + + )} +
+
+ ); +}; + +export default ModelAnalyticsTab; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/model_dashboard.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/model_dashboard.tsx index 7c0244b256b..8bc58655ef2 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/model_dashboard.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/model_dashboard.tsx @@ -1,18 +1,5 @@ import React, { useState, useEffect, useRef } from "react"; -import { - Card, - Title, - Subtitle, - Table, - TableHead, - TableRow, - TableHeaderCell, - TableCell, - TableBody, - Text, - Grid, - Col, -} from "@tremor/react"; +import { Text, Grid, Col } from "@tremor/react"; import { CredentialItem, credentialListCall, CredentialsResponse } from "../../../components/networking"; import { handleAddModelSubmit } from "../../../components/add_model/handle_add_model_submit"; @@ -21,7 +8,6 @@ import CredentialsPanel from "@/components/model_add/credentials"; import { getDisplayModelName } from "../../../components/view_model/model_name_display"; import { TabPanel, TabPanels, TabGroup, TabList, Tab, Icon } from "@tremor/react"; import { Select, SelectItem, DateRangePickerValue } from "@tremor/react"; -import UsageDatePicker from "../../../components/shared/usage_date_picker"; import { modelInfoCall, modelCostMap, @@ -37,20 +23,16 @@ import { adminGlobalActivityExceptionsPerDeployment, allEndUsersCall, } from "../../../components/networking"; -import { BarChart, AreaChart } from "@tremor/react"; -import { Popover, Form, InputNumber } from "antd"; -import { Button } from "@tremor/react"; +import { Form } from "antd"; import { Typography } from "antd"; -import { RefreshIcon, FilterIcon } from "@heroicons/react/outline"; +import { RefreshIcon } from "@heroicons/react/outline"; import type { UploadProps } from "antd"; -import TimeToFirstToken from "../../../components/model_metrics/time_to_first_token"; import { Team } from "../../../components/key_team_helpers/key_list"; import TeamInfoView from "../../../components/team/team_info"; import { Providers, provider_map, getPlaceholder, getProviderModels } from "../../../components/provider_info_helpers"; import ModelInfoView from "../../../components/model_info_view"; import AddModelTab from "../../../components/add_model/add_model_tab"; -import PriceDataReload from "../../../components/price_data_reload"; import HealthCheckComponent from "../../../components/model_dashboard/HealthCheckComponent"; import PassThroughSettings from "../../../components/pass_through_settings"; import ModelGroupAliasSettings from "../../../components/model_group_alias_settings"; @@ -59,6 +41,7 @@ import NotificationsManager from "../../../components/molecules/notifications_ma import AllModelsTab from "@/app/(dashboard)/models-and-endpoints/components/AllModelsTab"; import PriceDataManagementTab from "@/app/(dashboard)/models-and-endpoints/components/PriceDataManagementTab"; import ModelRetrySettingsTab from "@/app/(dashboard)/models-and-endpoints/components/ModelRetrySettingsTab"; +import ModelAnalyticsTab from "@/app/(dashboard)/models-and-endpoints/components/ModelAnalyticsTab"; interface ModelDashboardProps { accessToken: string | null; @@ -1040,237 +1023,25 @@ const ModelsAndEndpointsView: React.FC = ({ setSelectedModelId={setSelectedModelId} /> - - - - { - setDateValue(value); - updateModelMetrics(selectedModelGroup, value.from, value.to); - }} - /> - - - Select Model Group - - - - - - - - - - - - - - - Avg. Latency per Token - Time to first token - - - -

(seconds/token)

- - average Latency for successfull requests divided by the total tokens - - {modelMetrics && modelMetricsCategories && ( - - )} -
- - - -
-
-
- - - - - - - Deployment - Success Responses - - Slow Responses

Success Responses taking 600+s

-
-
-
- - {slowResponsesData.map((metric, idx) => ( - - {metric.api_base} - {metric.total_count} - {metric.slow_count} - - ))} - -
-
- -
- - - All Exceptions for {selectedModelGroup} - - - - - - - - All Up Rate Limit Errors (429) for {selectedModelGroup} - - - - Num Rate Limit Errors {globalExceptionData.sum_num_rate_limit_exceptions} - - console.log(v)} - /> - - - - - - {premiumUser ? ( - <> - {globalExceptionPerDeployment.map((globalActivity, index) => ( - - {globalActivity.api_base ? globalActivity.api_base : "Unknown API Base"} - - - - Num Rate Limit Errors (429) {globalActivity.sum_num_rate_limit_exceptions} - - console.log(v)} - /> - - - - ))} - - ) : ( - <> - {globalExceptionPerDeployment && - globalExceptionPerDeployment.length > 0 && - globalExceptionPerDeployment.slice(0, 1).map((globalActivity, index) => ( - - ✨ Rate Limit Errors by Deployment -

- Upgrade to see exceptions for all deployments -

- - - {globalActivity.api_base} - - - - Num Rate Limit Errors {globalActivity.sum_num_rate_limit_exceptions} - - console.log(v)} - /> - - - -
- ))} - - )} -
-
+