feat(frontend): add execution ID filter to platform cost admin page

This commit is contained in:
majdyz
2026-04-15 16:00:25 +07:00
parent 661fffe133
commit aa2d2d7371
5 changed files with 57 additions and 4 deletions

View File

@@ -43,6 +43,7 @@ async def get_cost_dashboard(
model: str | None = Query(None),
block_name: str | None = Query(None),
tracking_type: str | None = Query(None),
graph_exec_id: str | None = Query(None),
):
logger.info("Admin %s fetching platform cost dashboard", admin_user_id)
return await get_platform_cost_dashboard(
@@ -53,6 +54,7 @@ async def get_cost_dashboard(
model=model,
block_name=block_name,
tracking_type=tracking_type,
graph_exec_id=graph_exec_id,
)
@@ -72,6 +74,7 @@ async def get_cost_logs(
model: str | None = Query(None),
block_name: str | None = Query(None),
tracking_type: str | None = Query(None),
graph_exec_id: str | None = Query(None),
):
logger.info("Admin %s fetching platform cost logs", admin_user_id)
logs, total = await get_platform_cost_logs(
@@ -84,6 +87,7 @@ async def get_cost_logs(
model=model,
block_name=block_name,
tracking_type=tracking_type,
graph_exec_id=graph_exec_id,
)
total_pages = (total + page_size - 1) // page_size
return PlatformCostLogsResponse(
@@ -117,6 +121,7 @@ async def export_cost_logs(
model: str | None = Query(None),
block_name: str | None = Query(None),
tracking_type: str | None = Query(None),
graph_exec_id: str | None = Query(None),
):
logger.info("Admin %s exporting platform cost logs", admin_user_id)
logs, truncated = await get_platform_cost_logs_for_export(
@@ -127,6 +132,7 @@ async def export_cost_logs(
model=model,
block_name=block_name,
tracking_type=tracking_type,
graph_exec_id=graph_exec_id,
)
return PlatformCostExportResponse(
logs=logs,

View File

@@ -215,6 +215,7 @@ def _build_prisma_where(
model: str | None = None,
block_name: str | None = None,
tracking_type: str | None = None,
graph_exec_id: str | None = None,
) -> PlatformCostLogWhereInput:
"""Build a Prisma WhereInput for PlatformCostLog filters."""
where: PlatformCostLogWhereInput = {}
@@ -242,6 +243,9 @@ def _build_prisma_where(
if tracking_type:
where["trackingType"] = tracking_type
if graph_exec_id:
where["graphExecId"] = graph_exec_id
return where
@@ -314,6 +318,7 @@ async def get_platform_cost_dashboard(
model: str | None = None,
block_name: str | None = None,
tracking_type: str | None = None,
graph_exec_id: str | None = None,
) -> PlatformCostDashboard:
"""Aggregate platform cost logs for the admin dashboard.
@@ -330,7 +335,7 @@ async def get_platform_cost_dashboard(
start = datetime.now(timezone.utc) - timedelta(days=DEFAULT_DASHBOARD_DAYS)
where = _build_prisma_where(
start, end, provider, user_id, model, block_name, tracking_type
start, end, provider, user_id, model, block_name, tracking_type, graph_exec_id
)
# For per-user tracking-type breakdown we intentionally omit the
@@ -338,7 +343,14 @@ async def get_platform_cost_dashboard(
# This ensures cost_bearing_request_count is correct even when the caller
# is filtering the main view by a different tracking_type.
where_no_tracking_type = _build_prisma_where(
start, end, provider, user_id, model, block_name, tracking_type=None
start,
end,
provider,
user_id,
model,
block_name,
tracking_type=None,
graph_exec_id=graph_exec_id,
)
sum_fields = {
@@ -647,12 +659,13 @@ async def get_platform_cost_logs(
model: str | None = None,
block_name: str | None = None,
tracking_type: str | None = None,
graph_exec_id: str | None = None,
) -> tuple[list[CostLogRow], int]:
if start is None:
start = datetime.now(tz=timezone.utc) - timedelta(days=DEFAULT_DASHBOARD_DAYS)
where = _build_prisma_where(
start, end, provider, user_id, model, block_name, tracking_type
start, end, provider, user_id, model, block_name, tracking_type, graph_exec_id
)
offset = (page - 1) * page_size
@@ -702,6 +715,7 @@ async def get_platform_cost_logs_for_export(
model: str | None = None,
block_name: str | None = None,
tracking_type: str | None = None,
graph_exec_id: str | None = None,
) -> tuple[list[CostLogRow], bool]:
"""Return all matching rows up to EXPORT_MAX_ROWS.
@@ -712,7 +726,7 @@ async def get_platform_cost_logs_for_export(
start = datetime.now(tz=timezone.utc) - timedelta(days=DEFAULT_DASHBOARD_DAYS)
where = _build_prisma_where(
start, end, provider, user_id, model, block_name, tracking_type
start, end, provider, user_id, model, block_name, tracking_type, graph_exec_id
)
rows = await PrismaLog.prisma().find_many(

View File

@@ -19,6 +19,7 @@ interface Props {
model?: string;
block_name?: string;
tracking_type?: string;
graph_exec_id?: string;
page?: string;
tab?: string;
};
@@ -47,6 +48,8 @@ export function PlatformCostContent({ searchParams }: Props) {
setBlockInput,
typeInput,
setTypeInput,
executionIdInput,
setExecutionIdInput,
rateOverrides,
handleRateOverride,
updateUrl,
@@ -235,6 +238,22 @@ export function PlatformCostContent({ searchParams }: Props) {
onChange={(e) => setTypeInput(e.target.value)}
/>
</div>
<div className="flex flex-col gap-1">
<label
htmlFor="execution-id-filter"
className="text-sm text-muted-foreground"
>
Execution ID
</label>
<input
id="execution-id-filter"
type="text"
placeholder="Filter by execution"
className="rounded border px-3 py-1.5 text-sm"
value={executionIdInput}
onChange={(e) => setExecutionIdInput(e.target.value)}
/>
</div>
<button
onClick={handleFilter}
className="rounded bg-primary px-4 py-1.5 text-sm text-primary-foreground hover:bg-primary/90"
@@ -250,6 +269,7 @@ export function PlatformCostContent({ searchParams }: Props) {
setModelInput("");
setBlockInput("");
setTypeInput("");
setExecutionIdInput("");
updateUrl({
start: "",
end: "",
@@ -258,6 +278,7 @@ export function PlatformCostContent({ searchParams }: Props) {
model: "",
block_name: "",
tracking_type: "",
graph_exec_id: "",
page: "1",
});
}}

View File

@@ -23,6 +23,7 @@ interface InitialSearchParams {
model?: string;
block_name?: string;
tracking_type?: string;
graph_exec_id?: string;
page?: string;
tab?: string;
}
@@ -43,6 +44,8 @@ export function usePlatformCostContent(searchParams: InitialSearchParams) {
urlParams.get("block_name") || searchParams.block_name || "";
const typeFilter =
urlParams.get("tracking_type") || searchParams.tracking_type || "";
const executionIdFilter =
urlParams.get("graph_exec_id") || searchParams.graph_exec_id || "";
const [startInput, setStartInput] = useState(toLocalInput(startDate));
const [endInput, setEndInput] = useState(toLocalInput(endDate));
@@ -51,6 +54,7 @@ export function usePlatformCostContent(searchParams: InitialSearchParams) {
const [modelInput, setModelInput] = useState(modelFilter);
const [blockInput, setBlockInput] = useState(blockFilter);
const [typeInput, setTypeInput] = useState(typeFilter);
const [executionIdInput, setExecutionIdInput] = useState(executionIdFilter);
const [rateOverrides, setRateOverrides] = useState<Record<string, number>>(
{},
);
@@ -67,6 +71,7 @@ export function usePlatformCostContent(searchParams: InitialSearchParams) {
model: modelFilter || undefined,
block_name: blockFilter || undefined,
tracking_type: typeFilter || undefined,
graph_exec_id: executionIdFilter || undefined,
};
const {
@@ -115,6 +120,7 @@ export function usePlatformCostContent(searchParams: InitialSearchParams) {
model: modelInput,
block_name: blockInput,
tracking_type: typeInput,
graph_exec_id: executionIdInput,
page: "1",
});
}
@@ -185,6 +191,8 @@ export function usePlatformCostContent(searchParams: InitialSearchParams) {
setBlockInput,
typeInput,
setTypeInput,
executionIdInput,
setExecutionIdInput,
rateOverrides,
handleRateOverride,
updateUrl,

View File

@@ -7,6 +7,10 @@ type SearchParams = {
end?: string;
provider?: string;
user_id?: string;
model?: string;
block_name?: string;
tracking_type?: string;
graph_exec_id?: string;
page?: string;
tab?: string;
};