(null);
- // ── Fetch pre-computed metrics from backend (with 5-min cache) ────────────
+ // ── Fetch pre-computed metrics from backend (with 5-min per-(days,limit) cache) ────────────
- const fetchMetrics = useCallback(async () => {
+ const fetchMetrics = useCallback(async (limit: number, days: number) => {
setLoading(true);
setError(null);
try {
- const res = await authenticatedFetch(api.metrics.platform(), getAccessToken);
+ const res = await authenticatedFetch(api.metrics.platform({ limit, days }), getAccessToken);
if (!res.ok) {
if (res.status === 403) {
@@ -216,9 +221,15 @@ export function SectionAgentMetrics() {
}
}, [getAccessToken, addNotification]);
+ // Refetch whenever the user picks a new sample size or window (both drive
+ // backend params, not a client-side slice). fetchMetrics is intentionally
+ // excluded from deps: getAccessToken's identity churns on every MSAL
+ // accounts refresh which would otherwise re-fire the effect after each
+ // request and ping-pong the loading spinner.
useEffect(() => {
- fetchMetrics();
- }, [fetchMetrics]);
+ fetchMetrics(sampleSize, windowDays);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [sampleSize, windowDays]);
// ── Resolve agent version per session (pre-resolved by backend) ──
@@ -236,16 +247,17 @@ export function SectionAgentMetrics() {
return Array.from(versions).sort();
}, [sessionMetrics, resolveVersion]);
- // ── Filtered metrics based on sample size and version filter ────────────────
+ // ── Filtered metrics by version (sample-size cap is enforced server-side) ──
const filteredMetrics = useMemo(() => {
- // Sort by startedAt desc and take sampleSize most recent
- const sorted = [...sessionMetrics]
- .sort((a, b) => new Date(b.session.startedAt || 0).getTime() - new Date(a.session.startedAt || 0).getTime())
- .slice(0, sampleSize);
+ // Backend already returns the newest `limit` sessions in startedAt-desc order;
+ // re-sorting client-side is just defensive against repository-order drift.
+ const sorted = [...sessionMetrics].sort(
+ (a, b) => new Date(b.session.startedAt || 0).getTime() - new Date(a.session.startedAt || 0).getTime()
+ );
if (versionFilter === 'all') return sorted;
return sorted.filter((sm) => resolveVersion(sm) === versionFilter);
- }, [sessionMetrics, sampleSize, versionFilter, resolveVersion]);
+ }, [sessionMetrics, versionFilter, resolveVersion]);
// ── Aggregated stats across filtered sessions ──────────────────────────────
@@ -319,6 +331,19 @@ export function SectionAgentMetrics() {
)}
+
+
{availableVersions.length > 1 && (
<>
@@ -347,7 +374,7 @@ export function SectionAgentMetrics() {
>
)}