diff --git a/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx b/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx index 3aa2091400c..c913b150311 100644 --- a/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx +++ b/apps/studio/components/interfaces/Functions/EdgeFunctionsListItem.tsx @@ -3,12 +3,19 @@ import { useParams } from 'common/hooks' import dayjs from 'dayjs' import { Check, Copy } from 'lucide-react' import { useRouter } from 'next/router' -import { useState } from 'react' -import { copyToClipboard, TableCell, TableRow } from 'ui' -import { TimestampInfo } from 'ui-patterns' +import { useMemo, useState, type MouseEvent } from 'react' +import { cn, copyToClipboard, TableCell, TableRow } from 'ui' +import { ShimmeringLoader, TimestampInfo } from 'ui-patterns' +import { formatErrorRate } from './EdgeFunctionsListItem.utils' import { useProjectApiUrl } from '@/data/config/project-endpoint-query' -import type { EdgeFunctionsResponse } from '@/data/edge-functions/edge-functions-query' +import { useEdgeFunctionsLastHourStatsQuery } from '@/data/edge-functions/edge-functions-last-hour-stats-query' +import { + useEdgeFunctionsQuery, + type EdgeFunctionsResponse, +} from '@/data/edge-functions/edge-functions-query' +import { normalizeFunctionIds } from '@/data/edge-functions/keys' +import { usePHFlag } from '@/hooks/ui/useFlag' import { createNavigationHandler } from '@/lib/navigation' interface EdgeFunctionsListItemProps { @@ -20,6 +27,9 @@ export const EdgeFunctionsListItem = ({ function: item }: EdgeFunctionsListItemP const { ref } = useParams() const [isCopied, setIsCopied] = useState(false) + const showEdgeFunctionsRequestMetrics = usePHFlag('edgeFunctionsRequestMetrics') === true + const showLastHourStats = IS_PLATFORM && showEdgeFunctionsRequestMetrics + const { data: endpoint } = useProjectApiUrl({ projectRef: ref }) const functionUrl = `${endpoint}/functions/v1/${item.slug}` @@ -28,6 +38,24 @@ export const EdgeFunctionsListItem = ({ function: item }: EdgeFunctionsListItemP router ) + const { data: functions } = useEdgeFunctionsQuery({ projectRef: ref }) + const functionIds = useMemo(() => { + if (!showLastHourStats || !functions) return [] + return normalizeFunctionIds(functions.map((item) => item.id)) + }, [functions, showLastHourStats]) + + // [Joshen] We may be paginating the edge functions query in the future + // So this will eventually need to be a list of visibleFunctionIds instead + debounced + const { + data: lastHourStatsAll, + isPending: isStatsPending, + isError: isStatsError, + } = useEdgeFunctionsLastHourStatsQuery( + { projectRef: ref, functionIds }, + { enabled: showLastHourStats } + ) + const lastHourStats = lastHourStatsAll?.[item.id] + return ( { - function onCopy(value: any) { + onClick={(event: MouseEvent) => { + function onCopy(value: string) { setIsCopied(true) copyToClipboard(value) setTimeout(() => setIsCopied(false), 3000) @@ -86,7 +114,48 @@ export const EdgeFunctionsListItem = ({ function: item }: EdgeFunctionsListItemP label={dayjs(item.updated_at).fromNow()} /> - + {showLastHourStats && ( + <> + + {isStatsPending ? ( + + ) : isStatsError ? ( +

+ - +

+ ) : ( +

+ {lastHourStats !== undefined ? lastHourStats.requestsCount.toLocaleString() : '-'} +

+ )} +
+ + {isStatsPending ? ( + + ) : isStatsError ? ( +

+ - +

+ ) : lastHourStats !== undefined ? ( + = 1 + ? 'text-destructive' + : lastHourStats.errorRate > 0.1 + ? 'text-warning' + : 'text-foreground-light' + )} + > + {formatErrorRate(lastHourStats.errorRate)} + + ) : ( +

-

+ )} +
+ + )} +

{item.version}