feat(ui): optimization type filter scoping cost savings KPIs, charts, and recent requests

This commit is contained in:
Tin Chi Lo 2026-07-18 00:17:19 -07:00
parent 1eaad862f0
commit a6474f7354
2 changed files with 272 additions and 61 deletions

View file

@ -1,5 +1,6 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as networking from "@/components/networking";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
@ -16,6 +17,12 @@ function renderView() {
);
}
async function clickFilter(name: string) {
const radio = screen.getByRole("radio", { name });
const label = radio.closest("label");
await userEvent.click(label ?? radio);
}
beforeAll(() => {
if (typeof window !== "undefined" && !window.ResizeObserver) {
window.ResizeObserver = class ResizeObserver {
@ -86,6 +93,42 @@ const RECENT_RESPONSE: networking.RecentOptimizedRequestsResponse = {
scanned_requests: 42,
};
const MIXED_RECENT_RESPONSE: networking.RecentOptimizedRequestsResponse = {
requests: [
{
request_id: "req_cache_only",
start_time: "2026-07-15T12:00:00+00:00",
model: "claude-x",
total_tokens: 1000,
optimizations: ["caching"],
original_cost: 0.04,
optimized_cost: 0.03,
savings: 0.01,
},
{
request_id: "req_compress_only",
start_time: "2026-07-15T12:01:00+00:00",
model: "claude-y",
total_tokens: 2000,
optimizations: ["compression"],
original_cost: 0.08,
optimized_cost: 0.05,
savings: 0.03,
},
{
request_id: "req_both",
start_time: "2026-07-15T12:02:00+00:00",
model: "claude-z",
total_tokens: 3000,
optimizations: ["caching", "compression"],
original_cost: 0.12,
optimized_cost: 0.07,
savings: 0.05,
},
],
scanned_requests: 99,
};
describe("formatUsd", () => {
it("formats zero, cents, and sub-cent values", () => {
expect(formatUsd(0)).toBe("$0");
@ -158,4 +201,83 @@ describe("CostSavingsView", () => {
expect(screen.getByText(/No optimized requests in this window/)).toBeInTheDocument();
});
});
it("filters the recent requests table by optimization type", async () => {
vi.mocked(networking.costSavingsRecentRequestsCall).mockResolvedValue(MIXED_RECENT_RESPONSE);
renderView();
await waitFor(() => {
expect(screen.getByText("req_both")).toBeInTheDocument();
});
expect(screen.getByText("req_cache_only")).toBeInTheDocument();
expect(screen.getByText("req_compress_only")).toBeInTheDocument();
await clickFilter("Compression");
expect(screen.queryByText("req_cache_only")).not.toBeInTheDocument();
expect(screen.getByText("req_compress_only")).toBeInTheDocument();
expect(screen.getByText("req_both")).toBeInTheDocument();
await clickFilter("Caching");
expect(screen.getByText("req_cache_only")).toBeInTheDocument();
expect(screen.queryByText("req_compress_only")).not.toBeInTheDocument();
expect(screen.getByText("req_both")).toBeInTheDocument();
});
it("shows a type-specific empty state when the filter excludes every request", async () => {
vi.mocked(networking.costSavingsRecentRequestsCall).mockResolvedValue({
requests: [
{
request_id: "req_cache_only",
start_time: "2026-07-15T12:00:00+00:00",
model: "claude-x",
total_tokens: 1000,
optimizations: ["caching"],
original_cost: 0.04,
optimized_cost: 0.03,
savings: 0.01,
},
],
scanned_requests: 7,
});
renderView();
await waitFor(() => {
expect(screen.getByText("req_cache_only")).toBeInTheDocument();
});
await clickFilter("Compression");
expect(screen.queryByText("req_cache_only")).not.toBeInTheDocument();
expect(screen.getByText("No compression requests in this window.")).toBeInTheDocument();
});
it("scopes the KPI cards and charts to the selected optimization type", async () => {
renderView();
await waitFor(() => {
expect(screen.getAllByText("$2.00").length).toBeGreaterThan(0);
});
expect(screen.getByText("Savings Distribution")).toBeInTheDocument();
await clickFilter("Compression");
expect(screen.queryByText("Total Savings")).not.toBeInTheDocument();
expect(screen.queryByText("Caching Savings")).not.toBeInTheDocument();
expect(screen.getByText("Compression Savings")).toBeInTheDocument();
expect(screen.getAllByText("$0.50").length).toBeGreaterThan(0);
expect(screen.getByText("Tokens Compressed Away")).toBeInTheDocument();
expect(screen.getByText("250")).toBeInTheDocument();
expect(screen.queryByText("Savings Distribution")).not.toBeInTheDocument();
await clickFilter("Caching");
expect(screen.getByText("Caching Savings")).toBeInTheDocument();
expect(screen.queryByText("Compression Savings")).not.toBeInTheDocument();
expect(screen.getByText("Cached Tokens Read")).toBeInTheDocument();
expect(screen.getByText("1,000")).toBeInTheDocument();
await clickFilter("All");
expect(screen.getByText("Total Savings")).toBeInTheDocument();
expect(screen.getByText("Savings Distribution")).toBeInTheDocument();
});
});

View file

@ -1,9 +1,9 @@
"use client";
import { useQuery } from "@tanstack/react-query";
import { Alert, Card, Table, Tag, Typography } from "antd";
import { Alert, Card, Segmented, Table, Tag, Typography } from "antd";
import type { ColumnsType } from "antd/es/table";
import { ComponentProps, useState } from "react";
import { ComponentProps, useMemo, useState } from "react";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import { MetricCard } from "@/components/GuardrailsMonitor/MetricCard";
import AdvancedDatePicker from "@/components/shared/advanced_date_picker";
@ -15,18 +15,32 @@ import {
costSavingsActivityCall,
costSavingsRecentRequestsCall,
OptimizedRequestSummary,
RecentOptimizedRequestsResponse,
} from "@/components/networking";
type DateRangeValue = ComponentProps<typeof AdvancedDatePicker>["value"];
const SERIES_CATEGORIES = ["Caching", "Compression"] as const;
const SERIES_COLORS: readonly ChartColor[] = ["emerald", "blue"];
const SERIES = [
{ key: "caching", name: "Caching", color: "emerald" },
{ key: "compression", name: "Compression", color: "blue" },
] as const;
const SERIES_CATEGORIES = SERIES.map((series) => series.name);
const SERIES_COLORS: readonly ChartColor[] = SERIES.map((series) => series.color);
const OPTIMIZATION_TAG_COLOR: Record<CostOptimizationType, string> = {
caching: "green",
compression: "blue",
};
type OptimizationFilter = "all" | CostOptimizationType;
const OPTIMIZATION_FILTER_OPTIONS: readonly { label: string; value: OptimizationFilter }[] = [
{ label: "All", value: "all" },
{ label: "Caching", value: "caching" },
{ label: "Compression", value: "compression" },
];
export function formatUsd(value: number): string {
if (value === 0) return "$0";
const sign = value < 0 ? "-" : "";
@ -97,9 +111,41 @@ const RECENT_REQUEST_COLUMNS: ColumnsType<OptimizedRequestSummary> = [
interface SavingsKpiGridProps {
totals: CostSavingsMetrics | undefined;
filter: OptimizationFilter;
}
function SavingsKpiGrid({ totals }: SavingsKpiGridProps) {
const FILTERED_KPI_CONTENT = {
caching: {
savingsLabel: "Caching Savings",
savingsColor: "text-emerald-600",
tokensLabel: "Cached Tokens Read",
savingsOf: (totals: CostSavingsMetrics | undefined) => totals?.cache_savings ?? 0,
tokensOf: (totals: CostSavingsMetrics | undefined) => totals?.cache_read_input_tokens ?? 0,
},
compression: {
savingsLabel: "Compression Savings",
savingsColor: "text-blue-600",
tokensLabel: "Tokens Compressed Away",
savingsOf: (totals: CostSavingsMetrics | undefined) => totals?.compression_savings ?? 0,
tokensOf: (totals: CostSavingsMetrics | undefined) => totals?.compression_saved_tokens ?? 0,
},
} as const;
function SavingsKpiGrid({ totals, filter }: SavingsKpiGridProps) {
if (filter !== "all") {
const content = FILTERED_KPI_CONTENT[filter];
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mb-6">
<MetricCard
label={content.savingsLabel}
value={formatUsd(content.savingsOf(totals))}
valueColor={content.savingsColor}
/>
<MetricCard label={content.tokensLabel} value={content.tokensOf(totals).toLocaleString()} />
<MetricCard label="Total Spend" value={formatUsd(totals?.spend ?? 0)} />
</div>
);
}
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
<MetricCard label="Total Savings" value={formatUsd(totals?.total_savings ?? 0)} valueColor="text-green-600" />
@ -120,9 +166,58 @@ function SavingsKpiGrid({ totals }: SavingsKpiGridProps) {
);
}
interface RecentOptimizedRequestsCardProps {
data: RecentOptimizedRequestsResponse | undefined;
isLoading: boolean;
optimizationFilter: OptimizationFilter;
}
function RecentOptimizedRequestsCard({ data, isLoading, optimizationFilter }: RecentOptimizedRequestsCardProps) {
const requests = data?.requests;
const filteredRequests = useMemo(() => {
if (!requests) return [];
if (optimizationFilter === "all") return requests;
return requests.filter((request) => request.optimizations.includes(optimizationFilter));
}, [requests, optimizationFilter]);
return (
<Card className="border border-gray-200 rounded-lg" styles={{ body: { padding: 0 } }}>
<div className="p-6 pb-4">
<Typography.Title level={5} className="mb-0!">
Recent Optimized Requests
</Typography.Title>
<Typography.Text type="secondary">
Latest requests that benefited from caching or compression
{data ? ` (scanned last ${data.scanned_requests} requests in range)` : ""}
</Typography.Text>
</div>
{isLoading ? (
<div className="p-6">
<ChartLoader />
</div>
) : (
<Table
columns={RECENT_REQUEST_COLUMNS}
dataSource={filteredRequests}
rowKey="request_id"
pagination={false}
size="middle"
locale={{
emptyText:
optimizationFilter === "all"
? "No optimized requests in this window. Savings appear here once prompt caching or prompt compression kicks in."
: `No ${optimizationFilter} requests in this window.`,
}}
/>
)}
</Card>
);
}
export default function CostSavingsView() {
const { accessToken } = useAuthorized();
const [dateValue, setDateValue] = useState<DateRangeValue>(defaultDateRange);
const [optimizationFilter, setOptimizationFilter] = useState<OptimizationFilter>("all");
const startTime = dateValue.from;
const endTime = dateValue.to;
@ -142,6 +237,9 @@ export default function CostSavingsView() {
const totals = activityQuery.data?.totals;
const unpricedModels = activityQuery.data?.unpriced_models ?? [];
const visibleSeries = SERIES.filter((series) => optimizationFilter === "all" || series.key === optimizationFilter);
const visibleCategories = visibleSeries.map((series) => series.name);
const visibleColors: readonly ChartColor[] = visibleSeries.map((series) => series.color);
const chartData =
activityQuery.data?.results.map((day) => ({
date: day.date,
@ -154,7 +252,6 @@ export default function CostSavingsView() {
{ name: "Compression", value: totals.compression_savings },
]
: [];
const recentRequests = recentQuery.data?.requests ?? [];
return (
<div className="w-full p-8">
@ -165,7 +262,14 @@ export default function CostSavingsView() {
</Typography.Title>
<Typography.Text type="secondary">Savings from prompt caching and prompt compression</Typography.Text>
</div>
<AdvancedDatePicker value={dateValue} onValueChange={setDateValue} label="" showTimeRange={false} />
<div className="flex items-end gap-4">
<Segmented<OptimizationFilter>
options={[...OPTIMIZATION_FILTER_OPTIONS]}
value={optimizationFilter}
onChange={setOptimizationFilter}
/>
<AdvancedDatePicker value={dateValue} onValueChange={setDateValue} label="" showTimeRange={false} />
</div>
</div>
{unpricedModels.length > 0 && (
@ -178,10 +282,16 @@ export default function CostSavingsView() {
/>
)}
<SavingsKpiGrid totals={totals} />
<SavingsKpiGrid totals={totals} filter={optimizationFilter} />
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 mb-6">
<Card className="lg:col-span-2 border border-gray-200 rounded-lg">
<Card
className={
optimizationFilter === "all"
? "lg:col-span-2 border border-gray-200 rounded-lg"
: "lg:col-span-3 border border-gray-200 rounded-lg"
}
>
<Typography.Title level={5} className="mb-0!">
Savings Over Time
</Typography.Title>
@ -193,65 +303,44 @@ export default function CostSavingsView() {
className="mt-4"
data={chartData}
index="date"
categories={SERIES_CATEGORIES}
colors={SERIES_COLORS}
categories={visibleCategories}
colors={visibleColors}
valueFormatter={formatUsd}
yAxisWidth={80}
/>
)}
</Card>
<Card className="border border-gray-200 rounded-lg">
<Typography.Title level={5} className="mb-0!">
Savings Distribution
</Typography.Title>
<Typography.Text type="secondary">By optimization type</Typography.Text>
{activityQuery.isLoading ? (
<ChartLoader />
) : (
<>
<DonutChart
className="mt-4 h-60"
data={donutData}
index="name"
category="value"
colors={SERIES_COLORS}
valueFormatter={formatUsd}
showLabel
/>
<CustomLegend categories={SERIES_CATEGORIES} colors={SERIES_COLORS} />
</>
)}
</Card>
{optimizationFilter === "all" && (
<Card className="border border-gray-200 rounded-lg">
<Typography.Title level={5} className="mb-0!">
Savings Distribution
</Typography.Title>
<Typography.Text type="secondary">By optimization type</Typography.Text>
{activityQuery.isLoading ? (
<ChartLoader />
) : (
<>
<DonutChart
className="mt-4 h-60"
data={donutData}
index="name"
category="value"
colors={SERIES_COLORS}
valueFormatter={formatUsd}
showLabel
/>
<CustomLegend categories={SERIES_CATEGORIES} colors={SERIES_COLORS} />
</>
)}
</Card>
)}
</div>
<Card className="border border-gray-200 rounded-lg" styles={{ body: { padding: 0 } }}>
<div className="p-6 pb-4">
<Typography.Title level={5} className="mb-0!">
Recent Optimized Requests
</Typography.Title>
<Typography.Text type="secondary">
Latest requests that benefited from caching or compression
{recentQuery.data ? ` (scanned last ${recentQuery.data.scanned_requests} requests in range)` : ""}
</Typography.Text>
</div>
{recentQuery.isLoading ? (
<div className="p-6">
<ChartLoader />
</div>
) : (
<Table
columns={RECENT_REQUEST_COLUMNS}
dataSource={recentRequests}
rowKey="request_id"
pagination={false}
size="middle"
locale={{
emptyText:
"No optimized requests in this window. Savings appear here once prompt caching or prompt compression kicks in.",
}}
/>
)}
</Card>
<RecentOptimizedRequestsCard
data={recentQuery.data}
isLoading={recentQuery.isLoading}
optimizationFilter={optimizationFilter}
/>
</div>
);
}