Files
Danny White a5dcf3b57c feat(studio): rebuild pipeline health summary (#50445)
## What kind of change does this PR introduce?

Studio UI improvement.

## What is the current behavior?

Pipeline health is presented as a dense custom metrics panel with
repeated connection information and per-table lag details mixed into the
pipeline summary.

## What is the new behavior?

Moves the pipeline-level slot status, lag, WAL retention, and last
check-in into a standard detail section. It removes repeated connection
content and keeps table-specific state with the replicated tables.

| Before | After |
| --- | --- |
| <img width="1816" height="274" alt="CleanShot 2026-09-16 at 13 34
43@2x"
src="https://github.com/user-attachments/assets/eceed5bb-8af2-4a3b-83a9-7849f1554fbe"
/> | <img width="1830" height="506" alt="CleanShot 2026-09-16 at 13 34
15@2x"
src="https://github.com/user-attachments/assets/498c4390-17e2-45e5-a923-cb4a7cfd5978"
/> |

_Note that the page spacing may feel a bit funny. This is handled in
https://github.com/supabase/supabase/pull/49630_

This is an independent slice extracted from #49630. The related review
series is #50443, #50444, this PR, #50446, then #49630.

## To test

1. Open `/project/<ref>/database/replication` and select a running
pipeline.
2. Confirm **Pipeline health** shows slot status, lag, WAL retention
remaining, and last check-in.
3. Confirm unlimited WAL retention is labelled **Unlimited** and a
caught-up pipeline is labelled **Caught up**.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## UI Improvements

- Added a dedicated Pipeline Health section summarizing WAL status, slot
status, and replication lag.
- Replaced the inline metrics layout with responsive detail cards and
clearer supporting descriptions.
- Added tooltips for lag values and relative reply times, including
precise timestamps.
- Updated lag labels and status indicators for improved clarity.
- Added concise explanations for reserved, extended, unreserved, lost,
and unknown WAL states.
- Improved presentation of pipeline details with optional contextual
descriptions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-17 14:52:46 +10:00

105 lines
3.9 KiB
TypeScript

import { type ReactNode } from 'react'
import { Card, CardContent, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
import {
PageSection,
PageSectionContent,
PageSectionMeta,
PageSectionSummary,
PageSectionTitle,
} from 'ui-patterns/PageSection'
import { PIPELINE_DETAIL_GRID_CLASS_NAME, PipelineDetailItem } from './PipelineDetailItem'
import { type SlotLagMetrics as SlotLagMetricsType } from './ReplicationPipelineStatus.types'
import { getWalStatusMeta } from './ReplicationPipelineStatus.utils'
import { getFieldDisplay, SLOT_LAG_FIELDS } from './SlotLagMetrics'
import { SLOT_STATUS_TOOLTIP, SlotWalStatusValue } from './SlotStatus'
import { InlineLink } from '@/components/ui/InlineLink'
import { DOCS_URL } from '@/lib/constants'
interface PipelineHealthSectionProps {
/** Absent while the pipeline is stopped or failed and reports no slot metrics. */
metrics?: SlotLagMetricsType
/**
* Every notice about the pipeline's state, in priority order. This section is the single place
* they render, so a reader always finds "what needs my attention" at the top of Pipeline health.
*/
children?: ReactNode
}
export const PipelineHealthSection = ({ metrics, children }: PipelineHealthSectionProps) => {
const walStatusMeta = getWalStatusMeta(metrics?.wal_status)
return (
<PageSection>
<PageSectionMeta>
<PageSectionSummary>
<PageSectionTitle>Pipeline health</PageSectionTitle>
</PageSectionSummary>
</PageSectionMeta>
<PageSectionContent className="flex flex-col gap-y-4">
{children}
{metrics !== undefined && (
<Card>
<CardContent className="pb-5">
<dl className={PIPELINE_DETAIL_GRID_CLASS_NAME}>
<PipelineDetailItem
label="Slot status"
tooltip={SLOT_STATUS_TOOLTIP}
description={
<>
{walStatusMeta.description}{' '}
<InlineLink
className="text-foreground-lighter hover:text-foreground"
href={`${DOCS_URL}/guides/database/replication/pipelines-monitoring#slot-statuses`}
>
Learn more
</InlineLink>
</>
}
>
<SlotWalStatusValue status={metrics.wal_status} />
</PipelineDetailItem>
{SLOT_LAG_FIELDS.map((field) => {
const rawValue = metrics[field.key]
const { display, detail } = getFieldDisplay(field, rawValue)
const valueTooltip =
field.getValueTooltip && typeof rawValue === 'number'
? field.getValueTooltip(rawValue)
: undefined
return (
<PipelineDetailItem
key={field.key}
label={field.label}
tooltip={field.description}
>
{valueTooltip !== undefined ? (
<Tooltip>
<TooltipTrigger asChild>
<span className="w-fit cursor-default">{display}</span>
</TooltipTrigger>
<TooltipContent side="bottom" className="text-xs">
{valueTooltip}
</TooltipContent>
</Tooltip>
) : (
display
)}
{detail !== undefined && (
<span className="block text-xs text-foreground-lighter">{detail}</span>
)}
</PipelineDetailItem>
)
})}
</dl>
</CardContent>
</Card>
)}
</PageSectionContent>
</PageSection>
)
}