/* Copyright (C) 2023-2026 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import { useQuery } from '@tanstack/react-query' import { Gauge, HeartPulse, Timer } from 'lucide-react' import { useMemo } from 'react' import { useTranslation } from 'react-i18next' import { Skeleton } from '@/components/ui/skeleton' import { getPerfMetricsSummary } from '@/features/performance-metrics/api' import { formatLatency, formatThroughput, formatUptimePct, getSuccessRateDotClass, getSuccessRateTextClass, } from '@/features/performance-metrics/lib/format' import type { PerfModelSummary } from '@/features/performance-metrics/types' import { cn } from '@/lib/utils' const PERFORMANCE_WINDOW_HOURS = 24 const TOP_MODEL_LIMIT = 6 type WeightedMetric = 'avg_latency_ms' | 'avg_tps' | 'success_rate' type PerformanceSummary = { totalRequests: number avgLatencyMs: number avgTps: number successRate: number } function simpleAverage( rows: PerfModelSummary[], metric: WeightedMetric, isValid: (value: number) => boolean ): number { let total = 0 let count = 0 for (const row of rows) { const value = Number(row[metric]) if (!isValid(value)) continue total += value count++ } return count > 0 ? total / count : NaN } function buildPerformanceSummary(rows: PerfModelSummary[]): PerformanceSummary { return { totalRequests: rows.length, avgLatencyMs: Math.round( simpleAverage( rows, 'avg_latency_ms', (value) => Number.isFinite(value) && value > 0 ) ), avgTps: simpleAverage( rows, 'avg_tps', (value) => Number.isFinite(value) && value > 0 ), successRate: simpleAverage(rows, 'success_rate', Number.isFinite), } } export function PerformanceOverview() { const { t } = useTranslation() const metricsQuery = useQuery({ queryKey: ['perf-metrics-summary', PERFORMANCE_WINDOW_HOURS], queryFn: () => getPerfMetricsSummary(PERFORMANCE_WINDOW_HOURS), staleTime: 60 * 1000, retry: false, }) const models = useMemo( () => metricsQuery.data?.data.models ?? [], [metricsQuery.data] ) const summary = useMemo(() => buildPerformanceSummary(models), [models]) const topModels = useMemo(() => models.slice(0, TOP_MODEL_LIMIT), [models]) const loading = metricsQuery.isLoading const hasData = models.length > 0 if (!loading && !hasData) { return (
{t('No performance data available')}
) } return (
{/* Title */}
{/* Separator */}
{/* 3 KPI inline metrics */} {loading ? (
{Array.from({ length: 3 }).map((_, i) => (
))}
) : (
)} {/* Separator */}
{/* Top models inline badges */} {!loading && hasData && (
{topModels.map((model) => ( ))}
)}
) } function InlineMetric(props: { icon: React.ComponentType<{ className?: string }> label: string value: string valueClassName?: string }) { const Icon = props.icon return (
) } function ModelBadge(props: { model: PerfModelSummary }) { const model = props.model return ( {model.model_name} ) }