import { ExternalLink } from 'lucide-react' import { useRouter } from 'next/router' import { Fragment, useMemo } from 'react' import { Badge, Button, Card, cn, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from 'ui' import { PageContainer } from 'ui-patterns/PageContainer' import { PageSection, PageSectionAside, PageSectionContent, PageSectionMeta, PageSectionSummary, PageSectionTitle, } from 'ui-patterns/PageSection' import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader' import { buildGroupAssistantPrompt, formatLogTimestamp, formatSingleLineMessage, getFunctionRuntimeLogsSql, getRecentErrorGroups, getRecentErrorGroupsBase, getRecentErrorInvocationsSql, getRelatedExecutionIds, getStatusBadgeVariant, toAlertError, type RecentErrorGroup, } from './EdgeFunctionRecentErrors.utils' import { SIDEBAR_KEYS } from '@/components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider' import { AiAssistantDropdown } from '@/components/ui/AiAssistantDropdown' import AlertError from '@/components/ui/AlertError' import useLogsQuery from '@/hooks/analytics/useLogsQuery' import { useAiAssistantStateSnapshot } from '@/state/ai-assistant-state' import { useSidebarManagerSnapshot } from '@/state/sidebar-manager-state' interface EdgeFunctionRecentErrorsProps { functionId?: string functionSlug?: string projectRef?: string isoTimestampStart?: string isoTimestampEnd?: string } export const EdgeFunctionRecentErrors = ({ functionId, functionSlug, projectRef, isoTimestampStart, isoTimestampEnd, }: EdgeFunctionRecentErrorsProps) => { const router = useRouter() const { openSidebar } = useSidebarManagerSnapshot() const aiAssistant = useAiAssistantStateSnapshot() const isQueryEnabled = Boolean(projectRef && functionId) const recentErrorInvocationsSql = useMemo( () => getRecentErrorInvocationsSql(functionId), [functionId] ) const { logData: recentErrorInvocations, isLoading: isLoadingRecentErrorInvocations, error: recentErrorInvocationsError, } = useLogsQuery( projectRef as string, { sql: recentErrorInvocationsSql, iso_timestamp_start: isoTimestampStart, iso_timestamp_end: isoTimestampEnd, }, isQueryEnabled ) const recentErrorGroupsBase = useMemo( () => getRecentErrorGroupsBase(recentErrorInvocations), [recentErrorInvocations] ) const relatedExecutionIds = useMemo( () => getRelatedExecutionIds(recentErrorGroupsBase), [recentErrorGroupsBase] ) const functionRuntimeLogsSql = useMemo( () => getFunctionRuntimeLogsSql({ functionId, executionIds: relatedExecutionIds }), [functionId, relatedExecutionIds] ) const { logData: functionRuntimeLogs, isLoading: isLoadingFunctionRuntimeLogs, error: functionRuntimeLogsError, } = useLogsQuery( projectRef as string, { sql: functionRuntimeLogsSql, iso_timestamp_start: isoTimestampStart, iso_timestamp_end: isoTimestampEnd, }, Boolean(projectRef && functionRuntimeLogsSql) ) const queryError = toAlertError(recentErrorInvocationsError) ?? toAlertError(functionRuntimeLogsError) const recentErrorGroups = useMemo( () => getRecentErrorGroups({ recentErrorGroupsBase, functionRuntimeLogs }), [functionRuntimeLogs, recentErrorGroupsBase] ) const handleOpenAssistant = (group: RecentErrorGroup) => { openSidebar(SIDEBAR_KEYS.AI_ASSISTANT) aiAssistant.newChat({ name: `Investigate ${functionSlug ?? 'error'}`, initialMessage: buildGroupAssistantPrompt(group, functionSlug), }) } return (
Recent Failed Invocations {recentErrorInvocationsError || functionRuntimeLogsError ? ( ) : isLoadingRecentErrorInvocations || isLoadingFunctionRuntimeLogs ? ( ) : recentErrorGroups.length === 0 ? (
Recent runtime errors will appear here when this function returns a 5xx response.
) : ( Error Count Last Seen Method Status Duration Assistant {recentErrorGroups.map((group) => ( {formatSingleLineMessage(group.message)} {group.count} {formatLogTimestamp(group.lastSeen, 'relative')} {group.lastMethod ?? '-'} {group.lastStatusCode ? ( {group.lastStatusCode} ) : ( Error )} {group.executionTime ?? '-'}
buildGroupAssistantPrompt(group, functionSlug)} onOpenAssistant={() => handleOpenAssistant(group)} />
{group.logs.length === 0 ? (
No related runtime logs found for this error group.
) : ( group.logs.map((log) => (
[{formatLogTimestamp(log.lastSeen, 'time')}] [ {log.level.toUpperCase()}] [{log.count}x]{' '} {formatSingleLineMessage(log.message)}
)) )}
))}
)}
) }