mirror of
https://github.com/supabase/supabase.git
synced 2026-10-07 18:35:07 +03:00
107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
import { useParams } from 'common'
|
|
import Link from 'next/link'
|
|
import { Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
|
|
|
import { metricColor } from './InstanceNode.utils'
|
|
import { useComputeMetrics } from '@/hooks/analytics/useComputeMetrics'
|
|
|
|
/**
|
|
* Compute metrics row at the bottom of a primary database node card, linking
|
|
* to the database report. Metrics are project-scoped, which reports the
|
|
* primary on both standard and High Availability projects.
|
|
*/
|
|
export const ComputeMetricsFooter = ({
|
|
isConnectionsAvailable = true,
|
|
}: {
|
|
isConnectionsAvailable?: boolean
|
|
}) => {
|
|
const { ref } = useParams()
|
|
|
|
const {
|
|
cpu,
|
|
disk,
|
|
memory,
|
|
connections,
|
|
isLoading: isMetricsLoading,
|
|
isError: isMetricsError,
|
|
} = useComputeMetrics({
|
|
projectRef: ref,
|
|
})
|
|
|
|
const observabilityUrl = `/project/${ref}/observability/database`
|
|
const hasConnectionMetrics = isConnectionsAvailable && connections !== null && connections.max > 0
|
|
|
|
return (
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Link
|
|
href={observabilityUrl}
|
|
className="border-t px-3 py-2 hover:bg-surface-200 transition flex items-center gap-x-3 text-xs"
|
|
>
|
|
{/* Stable live region: announces loading/unavailability, never the polled values */}
|
|
<span role="status" className="sr-only">
|
|
{isMetricsLoading && 'Loading metrics'}
|
|
{!isMetricsLoading && isMetricsError && 'Metrics unavailable'}
|
|
{!isMetricsLoading && !isMetricsError && (
|
|
<>
|
|
{cpu === null && 'CPU unavailable. '}
|
|
{disk === null && 'Disk unavailable. '}
|
|
{memory === null && 'RAM unavailable. '}
|
|
{!hasConnectionMetrics && 'Connection metrics unavailable.'}
|
|
</>
|
|
)}
|
|
</span>
|
|
{/* h-4 matches the text-xs line height so the card doesn't shift when metrics load */}
|
|
{isMetricsLoading && (
|
|
<div
|
|
aria-hidden="true"
|
|
className="h-4 w-44 rounded-sm bg-surface-300 motion-safe:animate-pulse"
|
|
/>
|
|
)}
|
|
{!isMetricsLoading && isMetricsError && (
|
|
<span aria-hidden="true" className="text-foreground-lighter">
|
|
Metrics unavailable
|
|
</span>
|
|
)}
|
|
{!isMetricsLoading && !isMetricsError && (
|
|
<>
|
|
<span>
|
|
CPU <MetricValue value={cpu} />
|
|
</span>
|
|
<span className="text-foreground-lighter">·</span>
|
|
<span>
|
|
Disk <MetricValue value={disk} />
|
|
</span>
|
|
<span className="text-foreground-lighter">·</span>
|
|
<span>
|
|
RAM <MetricValue value={memory} />
|
|
</span>
|
|
<span className="text-foreground-lighter">·</span>
|
|
<span className="text-foreground-light">
|
|
{hasConnectionMetrics ? (
|
|
<>
|
|
{connections.peak}/{connections.max} conns
|
|
</>
|
|
) : (
|
|
<>
|
|
Conns <span className="text-foreground-lighter">Unavailable</span>
|
|
</>
|
|
)}
|
|
</span>
|
|
</>
|
|
)}
|
|
</Link>
|
|
</TooltipTrigger>
|
|
<TooltipContent side="bottom">Go to Database Report</TooltipContent>
|
|
</Tooltip>
|
|
)
|
|
}
|
|
|
|
function MetricValue({ value }: { value: number | null }) {
|
|
if (value === null) {
|
|
return <span className="text-foreground-lighter">Unavailable</span>
|
|
}
|
|
|
|
return <span className={metricColor(value)}>{value.toFixed(0)}%</span>
|
|
}
|