mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
<img width="1575" height="1134" alt="image" src="https://github.com/user-attachments/assets/994b1113-717f-44a2-89a4-13bc0182db20" /> Attempts to improve our edge function overview pages to provide stronger insights into the health of a function, including reliability (error rates), performance (execution times) and usage (cpu and memory). As part of this work it refactors existing charts to use our new chart components. main consideration is the collective performance of error queries https://github.com/supabase/supabase/pull/44009/changes#diff-2a79cf61c5397a8ef363c333229fa7729a2efc90a4d8e0806e49c212d5aa97e7 ## To test: 1. Create an edge function that errors out randomly across requests. You can use cron to poll this function every second. 2. View the edge function and on the overview page confirm that errors are showing and grouped correctly in recent failed invocations sections. --------- Co-authored-by: Ali Waseem <waseema393@gmail.com>
159 lines
5.1 KiB
TypeScript
159 lines
5.1 KiB
TypeScript
import { useMemo } from 'react'
|
|
import { ChartMetric } from 'ui-patterns/Chart'
|
|
import { PageContainer } from 'ui-patterns/PageContainer'
|
|
import {
|
|
PageSection,
|
|
PageSectionContent,
|
|
PageSectionMeta,
|
|
PageSectionSummary,
|
|
PageSectionTitle,
|
|
} from 'ui-patterns/PageSection'
|
|
|
|
import { getCpuTooltipDetails, getMemoryTooltipDetails } from './EdgeFunctionMetricTooltipDetails'
|
|
import {
|
|
CPU_TIME_CHART_CONFIG,
|
|
formatMetric,
|
|
formatRate,
|
|
getChartEmptyStateCopy,
|
|
MEMORY_CHART_CONFIG,
|
|
} from './EdgeFunctionOverview.utils'
|
|
import { EdgeFunctionTimeSeriesChartCard } from './EdgeFunctionTimeSeriesChartCard'
|
|
import type { EdgeFunctionChartDatum } from './EdgeFunctionOverview.utils'
|
|
|
|
interface EdgeFunctionUsageSectionProps {
|
|
data: EdgeFunctionChartDatum[]
|
|
dateTimeFormat: string
|
|
isLoading: boolean
|
|
isError: boolean
|
|
errorMessage?: string
|
|
averageCpuTime: number
|
|
maxCpuTime: number
|
|
averageMemoryUsage: number
|
|
totalHeapMemory: number
|
|
totalExternalMemory: number
|
|
totalMemoryByType: number
|
|
}
|
|
|
|
export const EdgeFunctionUsageSection = ({
|
|
data,
|
|
dateTimeFormat,
|
|
isLoading,
|
|
isError,
|
|
errorMessage,
|
|
averageCpuTime,
|
|
maxCpuTime,
|
|
averageMemoryUsage,
|
|
totalHeapMemory,
|
|
totalExternalMemory,
|
|
totalMemoryByType,
|
|
}: EdgeFunctionUsageSectionProps) => {
|
|
const cpuEmptyStateCopy = getChartEmptyStateCopy('CPU time', isError, errorMessage)
|
|
const memoryEmptyStateCopy = getChartEmptyStateCopy('memory usage', isError, errorMessage)
|
|
const cpuTooltipDetails = useMemo(() => getCpuTooltipDetails(averageCpuTime), [averageCpuTime])
|
|
const memoryTooltipDetails = useMemo(
|
|
() => getMemoryTooltipDetails(averageMemoryUsage),
|
|
[averageMemoryUsage]
|
|
)
|
|
const cpuMetrics = (
|
|
<div className="flex flex-wrap gap-x-8 gap-y-4">
|
|
<ChartMetric
|
|
label="Average CPU Time"
|
|
value={formatMetric(averageCpuTime, 'ms')}
|
|
tooltip="Average CPU time usage for the function"
|
|
/>
|
|
<ChartMetric
|
|
label="Max CPU Time"
|
|
value={formatMetric(maxCpuTime, 'ms')}
|
|
tooltip="Maximum CPU time usage for the function"
|
|
/>
|
|
</div>
|
|
)
|
|
const memoryMetrics = (
|
|
<div className="flex flex-wrap gap-x-8 gap-y-4">
|
|
<ChartMetric
|
|
label="Average Memory Usage"
|
|
value={formatMetric(averageMemoryUsage, 'MB')}
|
|
tooltip="Average memory usage for the function"
|
|
/>
|
|
<ChartMetric
|
|
label="Heap"
|
|
value={formatRate(totalHeapMemory, totalMemoryByType)}
|
|
tooltip="Share of memory attributed to heap usage over the selected interval"
|
|
/>
|
|
<ChartMetric
|
|
label="External"
|
|
value={formatRate(totalExternalMemory, totalMemoryByType)}
|
|
tooltip="Share of memory attributed to external usage over the selected interval"
|
|
/>
|
|
</div>
|
|
)
|
|
|
|
return (
|
|
<PageSection>
|
|
<PageSectionContent>
|
|
<PageContainer size="full">
|
|
<div className="flex flex-col gap-6">
|
|
<PageSectionMeta>
|
|
<PageSectionSummary>
|
|
<PageSectionTitle>Usage</PageSectionTitle>
|
|
</PageSectionSummary>
|
|
</PageSectionMeta>
|
|
|
|
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
|
<EdgeFunctionTimeSeriesChartCard
|
|
data={data}
|
|
dateTimeFormat={dateTimeFormat}
|
|
isLoading={isLoading}
|
|
isError={isError}
|
|
emptyTitle={cpuEmptyStateCopy.title}
|
|
emptyDescription={cpuEmptyStateCopy.description}
|
|
metrics={cpuMetrics}
|
|
dataKey="max_cpu_time_used"
|
|
config={CPU_TIME_CHART_CONFIG}
|
|
tooltipDetails={cpuTooltipDetails}
|
|
referenceLines={[
|
|
{
|
|
y: averageCpuTime,
|
|
label: 'average',
|
|
stroke: 'hsl(var(--foreground-default))',
|
|
strokeWidth: 1.5,
|
|
},
|
|
]}
|
|
yAxisProps={{
|
|
width: 64,
|
|
tickFormatter: (value: number) => `${Math.round(value)}ms`,
|
|
}}
|
|
/>
|
|
|
|
<EdgeFunctionTimeSeriesChartCard
|
|
data={data}
|
|
dateTimeFormat={dateTimeFormat}
|
|
isLoading={isLoading}
|
|
isError={isError}
|
|
emptyTitle={memoryEmptyStateCopy.title}
|
|
emptyDescription={memoryEmptyStateCopy.description}
|
|
metrics={memoryMetrics}
|
|
dataKey="avg_memory_used"
|
|
config={MEMORY_CHART_CONFIG}
|
|
tooltipDetails={memoryTooltipDetails}
|
|
referenceLines={[
|
|
{
|
|
y: averageMemoryUsage,
|
|
label: 'average',
|
|
stroke: 'hsl(var(--foreground-default))',
|
|
strokeWidth: 1.5,
|
|
},
|
|
]}
|
|
yAxisProps={{
|
|
width: 64,
|
|
tickFormatter: (value: number) => `${Number(value).toFixed(1)}MB`,
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</PageContainer>
|
|
</PageSectionContent>
|
|
</PageSection>
|
|
)
|
|
}
|