Home / Function/ QueryPerformanceChart() — supabase Function Reference

QueryPerformanceChart() — supabase Function Reference

Architecture documentation for the QueryPerformanceChart() function in QueryPerformanceChart.tsx from the supabase codebase.

Entity Profile

Dependency Diagram

graph TD
  0f4e0758_d08d_4514_7f21_93d850ccdbf9["QueryPerformanceChart()"]
  b1259752_04bc_1519_0b13_de719e165b16["calculatePercentilesFromHistogram()"]
  0f4e0758_d08d_4514_7f21_93d850ccdbf9 -->|calls| b1259752_04bc_1519_0b13_de719e165b16
  style 0f4e0758_d08d_4514_7f21_93d850ccdbf9 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

apps/studio/components/interfaces/QueryPerformance/QueryPerformanceChart.tsx lines 50–387

export const QueryPerformanceChart = ({
  onDateRangeChange,
  chartData,
  isLoading,
  error,
  currentSelectedQuery,
  parsedLogs,
}: QueryPerformanceChartProps) => {
  const [selectedMetric, setSelectedMetric] = useState('query_latency')

  const currentMetrics = useMemo(() => {
    if (!chartData || chartData.length === 0) return []

    switch (selectedMetric) {
      case 'query_latency': {
        let trueP95: number = 0

        if (parsedLogs && parsedLogs.length > 0) {
          const bucketCount = parsedLogs[0]?.resp_calls?.length || 50
          const combinedHistogram = new Array(bucketCount).fill(0)

          parsedLogs.forEach((log) => {
            if (log.resp_calls && Array.isArray(log.resp_calls)) {
              log.resp_calls.forEach((count: number, index: number) => {
                if (index < combinedHistogram.length) {
                  combinedHistogram[index] += count
                }
              })
            }
          })

          // [kemal]: this might need a revisit
          const percentiles = calculatePercentilesFromHistogram(combinedHistogram)
          trueP95 = percentiles.p95
        } else {
          // [kemal]: fallback to weighted average
          const totalCalls = chartData.reduce((sum, d) => sum + d.calls, 0)
          trueP95 =
            totalCalls > 0
              ? chartData.reduce((sum, d) => sum + d.p95_time * d.calls, 0) / totalCalls
              : 0
        }

        return [
          {
            label: 'Average p95',
            value: `${Math.round(trueP95)}ms`,
          },
        ]
      }
      case 'rows_read': {
        const totalRowsRead = chartData.reduce((sum, d) => sum + d.rows_read, 0)

        return [
          {
            label: 'Total Rows Read',
            value: totalRowsRead.toLocaleString(),
          },
        ]
      }
      case 'calls': {
        const totalCalls = chartData.reduce((sum, d) => sum + d.calls, 0)

        return [
          {
            label: 'Total Calls',
            value: totalCalls.toLocaleString(),
          },
        ]
      }
      case 'cache_hits': {
        const totalHits = chartData.reduce((sum, d) => sum + d.cache_hits, 0)
        const totalMisses = chartData.reduce((sum, d) => sum + d.cache_misses, 0)
        const total = totalHits + totalMisses
        const hitRate = total > 0 ? (totalHits / total) * 100 : 0

        return [
          {
            label: 'Cache Hit Rate',
            value: `${hitRate.toFixed(2)}%`,
          },
        ]
      }
      default:
        return []
    }
  }, [chartData, selectedMetric])

  const transformedChartData = useMemo(() => {
    if (selectedMetric !== 'query_latency') return chartData

    const transformed = chartData.map((dataPoint) => ({
      ...dataPoint,
      p50_time: parseFloat((dataPoint.p50_time / 1000).toFixed(3)),
      p95_time: parseFloat((dataPoint.p95_time / 1000).toFixed(3)),
    }))

    return transformed
  }, [chartData, selectedMetric])

  const querySpecificData = useMemo(() => {
    if (!currentSelectedQuery || !parsedLogs.length) return null

    const normalizedSelected = currentSelectedQuery.replace(/\s+/g, ' ').trim()
    const queryLogs = parsedLogs.filter((log) => {
      const normalized = (log.query || '').replace(/\s+/g, ' ').trim()
      return normalized === normalizedSelected
    })

    const queryDataMap = new Map<
      number,
      {
        time: number
        rows_read: number
        calls: number
        cache_hits: number
      }
    >()

    queryLogs.forEach((log) => {
      const timestamps = [log.bucket_start_time, log.bucket, log.timestamp, log.ts]
      const validTimestamp = timestamps.find((t) => t && !isNaN(new Date(t).getTime()))

      if (!validTimestamp) return

      const time = new Date(validTimestamp).getTime()
      const meanTime = log.mean_time ?? log.mean_exec_time ?? log.mean_query_time ?? 0
      const rowsRead = log.rows_read ?? log.rows ?? 0
      const calls = log.calls ?? 0
      const cacheHits = log.shared_blks_hit ?? log.cache_hits ?? 0

      queryDataMap.set(time, {
        time: parseFloat(String(meanTime)),
        rows_read: parseFloat(String(rowsRead)),
        calls: parseFloat(String(calls)),
        cache_hits: parseFloat(String(cacheHits)),
      })
    })

    return queryDataMap
  }, [currentSelectedQuery, parsedLogs])

  const mergedChartData = useMemo(() => {
    if (!querySpecificData || !currentSelectedQuery) {
      return transformedChartData
    }

    return transformedChartData.map((dataPoint) => {
      const queryData = querySpecificData.get(dataPoint.period_start)

      return {
        ...dataPoint,
        selected_query_time:
          queryData?.time !== undefined
            ? selectedMetric === 'query_latency'
              ? queryData.time / 1000
              : queryData.time
            : null,
        selected_query_rows_read: queryData?.rows_read !== undefined ? queryData.rows_read : null,
        selected_query_calls: queryData?.calls !== undefined ? queryData.calls : null,
        selected_query_cache_hits:
          queryData?.cache_hits !== undefined ? queryData.cache_hits : null,
      }
    })
  }, [transformedChartData, querySpecificData, currentSelectedQuery, selectedMetric])

  const getChartAttributes = useMemo((): MultiAttribute[] => {
    const attributeMap: Record<string, MultiAttribute[]> = {
      query_latency: [
        {
          attribute: 'p50_time',
          label: 'p50',
          provider: 'logs',
          type: 'line',
          color: { light: '#8B5CF6', dark: '#8B5CF6' },
        },
        {
          attribute: 'p95_time',
          label: 'p95',
          provider: 'logs',
          type: 'line',
          color: { light: '#65BCD9', dark: '#65BCD9' },
        },
      ],
      rows_read: [
        {
          attribute: 'rows_read',
          label: 'Rows Read',
          provider: 'logs',
        },
      ],
      calls: [
        {
          attribute: 'calls',
          label: 'Calls',
          provider: 'logs',
        },
      ],
      cache_hits: [
        {
          attribute: 'cache_hits',
          label: 'Cache Hits',
          provider: 'logs',
          type: 'line',
          color: { light: '#10B981', dark: '#10B981' },
        },
      ],
    }

    const baseAttributes = attributeMap[selectedMetric] || []

    // Add selected query line based on current metric
    if (currentSelectedQuery && querySpecificData) {
      const selectedQueryAttributes: Record<string, MultiAttribute> = {
        query_latency: {
          attribute: 'selected_query_time',
          label: 'Selected Query',
          provider: 'logs',
          type: 'line',
          color: { light: '#10B981', dark: '#10B981' },
          strokeWidth: 3,
        },
        rows_read: {
          attribute: 'selected_query_rows_read',
          label: 'Selected Query',
          provider: 'logs',
          type: 'line',
          color: { light: '#F59E0B', dark: '#F59E0B' },
          strokeWidth: 3,
        },
        calls: {
          attribute: 'selected_query_calls',
          label: 'Selected Query',
          provider: 'logs',
          type: 'line',
          color: { light: '#EC4899', dark: '#EC4899' },
          strokeWidth: 3,
        },
        cache_hits: {
          attribute: 'selected_query_cache_hits',
          label: 'Selected Query',
          provider: 'logs',
          type: 'line',
          color: { light: '#8B5CF6', dark: '#8B5CF6' },
          strokeWidth: 3,
        },
      }

      const selectedQueryAttr = selectedQueryAttributes[selectedMetric]
      if (selectedQueryAttr) {
        return [...baseAttributes, selectedQueryAttr]
      }
    }

    return baseAttributes
  }, [selectedMetric, currentSelectedQuery, querySpecificData])

  const updateDateRange = (from: string, to: string) => {
    onDateRangeChange?.(from, to)
  }

  const getYAxisFormatter = useMemo(() => {
    if (selectedMetric === 'query_latency') {
      return formatTimeValue
    }
    return formatNumberValue
  }, [selectedMetric])

  return (
    <div className="bg-surface-200 border-t">
      <Tabs_Shadcn_
        value={selectedMetric}
        onValueChange={(value) => setSelectedMetric(value as string)}
        className="w-full"
      >
        <TabsList_Shadcn_ className="flex justify-start rounded-none gap-x-4 border-b !mt-0 pt-0 px-6">
          {QUERY_PERFORMANCE_CHART_TABS.map((tab) => (
            <TabsTrigger_Shadcn_
              key={tab.id}
              value={tab.id}
              className="flex items-center gap-2 text-xs py-3 border-b-[1px] font-mono uppercase"
            >
              {tab.label}
            </TabsTrigger_Shadcn_>
          ))}
        </TabsList_Shadcn_>

        <TabsContent_Shadcn_ value={selectedMetric} className="bg-surface-200 mt-0 h-inherit">
          <div className="w-full flex items-center justify-center min-h-[282px]">
            {isLoading ? (
              <Loader2 size={20} className="animate-spin text-foreground-lighter" />
            ) : error ? (
              <p className="text-sm text-foreground-light text-center h-full flex items-center justify-center">
                Error loading chart data
              </p>
            ) : (
              <div className="w-full flex flex-col h-full px-6 py-4">
                <div className="flex gap-6 mb-4">
                  {currentMetrics.map((metric, index) => (
                    <QueryMetricBlock key={index} label={metric.label} value={metric.value} />
                  ))}
                </div>
                <ComposedChart
                  data={mergedChartData as any}
                  attributes={getChartAttributes}
                  yAxisKey={getChartAttributes[0]?.attribute || ''}
                  xAxisKey="period_start"
                  title=""
                  customDateFormat="MMM D, YYYY hh:mm A"
                  hideChartType={true}
                  hideHighlightArea={true}
                  showTooltip={true}
                  showGrid={true}
                  showLegend={
                    selectedMetric === 'query_latency' ||
                    selectedMetric === 'cache_hits' ||
                    selectedMetric === 'rows_read' ||
                    selectedMetric === 'calls'
                  }
                  showTotal={false}
                  showMaxValue={false}
                  updateDateRange={updateDateRange}
                  YAxisProps={{
                    tick: true,
                    width: 60,
                    tickFormatter: getYAxisFormatter,
                  }}
                  xAxisIsDate={true}
                  className="mt-2"
                />
              </div>
            )}
          </div>
        </TabsContent_Shadcn_>
      </Tabs_Shadcn_>
    </div>
  )
}

Subdomains

Frequently Asked Questions

What does QueryPerformanceChart() do?
QueryPerformanceChart() is a function in the supabase codebase.
What does QueryPerformanceChart() call?
QueryPerformanceChart() calls 1 function(s): calculatePercentilesFromHistogram.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free