Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2357,6 +2357,10 @@ export const telemetry: NavMenuConstant = {
name: 'Log drains',
url: '/guides/telemetry/log-drains',
},
{
name: 'Reports',
url: '/guides/telemetry/reports',
},
{
name: 'Metrics',
url: '/guides/telemetry/metrics',
Expand Down
26 changes: 26 additions & 0 deletions apps/docs/content/guides/database/connection-management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,32 @@ These numbers are generalizations and depends on other Supabase products that yo

### Capturing historical usage

#### Dashboard monitoring charts

<Image
alt="Database client connections chart"
zoomable
src={{
dark: '/docs/img/database/reports/db-connections-chart-dark.png',
light: '/docs/img/database/reports/db-connections-chart-light.png',
}}
/>

For Teams and Enterprise plans, Supabase provides Advanced Telemetry charts directly within the Dashboard. The `Database client connections` chart displays historical connection data broken down by connection type:

- **Postgres**: Direct connections from your application
- **PostgREST**: Connections from the PostgREST API layer
- **Reserved**: Administrative connections for Supabase services
- **Auth**: Connections from Supabase Auth service
- **Storage**: Connections from Supabase Storage service
- **Other roles**: Miscellaneous database connections

This chart helps you monitor connection pool usage, identify connection leaks, and plan capacity. It also shows a reference line for your compute size's maximum connection limit.

For more details on using these monitoring charts, see the [Reports guide](/docs/guides/telemetry/reports#advanced-telemetry).

#### Grafana Dashboard

Supabase offers a Grafana Dashboard that records and visualizes over 200 project metrics, including connections. For setup instructions, check the [metrics docs](/docs/guides/platform/metrics).

Its "Client Connections" graph displays connections for both Supavisor and Postgres
Expand Down
309 changes: 309 additions & 0 deletions apps/docs/content/guides/telemetry/reports.mdx

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export const BranchManagementSection = ({
<div className="bg-surface-100 shadow-sm flex justify-between items-center px-4 py-3 rounded-t-lg text-xs font-mono uppercase">
{typeof header === 'string' ? <span>{header}</span> : header}
</div>
<div className="bg-surface border-t shadow-sm rounded-b-lg text-sm divide-y">{children}</div>
<div className="bg-surface border-t shadow-sm rounded-b-lg text-sm divide-y px-4">
{children}
</div>
{footer !== undefined && <div className="bg-surface-100 px-6 py-1 border-t">{footer}</div>}
</div>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { BranchSelector } from './BranchSelector'
import { DocsButton } from 'components/ui/DocsButton'
import { Button } from 'ui'

const EMPTY_STATE_CONTAINER = 'flex items-center flex-col justify-center w-full py-10 px-4'

export const PullRequestsEmptyState = ({
url,
projectRef,
Expand All @@ -24,9 +26,9 @@ export const PullRequestsEmptyState = ({
gitlessBranching: boolean
}) => {
return (
<div className="flex items-center flex-col justify-center w-full py-10">
<div className={EMPTY_STATE_CONTAINER}>
<p>No merge requests</p>
<p className="text-foreground-light">
<p className="text-foreground-light text-center">
Create your first merge request to merge changes back to the main branch
</p>
<div className="flex items-center space-x-2 mt-4">
Expand Down Expand Up @@ -60,9 +62,9 @@ export const PreviewBranchesEmptyState = ({
onSelectCreateBranch: () => void
}) => {
return (
<div className="flex items-center flex-col justify-center w-full py-10">
<div className={EMPTY_STATE_CONTAINER}>
<p>Create your first preview branch</p>
<p className="text-foreground-light mb-4">
<p className="text-foreground-light text-center mb-4">
Preview branches are short-lived environments that let you safely experiment with changes to
your database schema without affecting your main database.
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import { useState } from 'react'
import { toast } from 'sonner'

import { useParams } from 'common'
import { useIsBranching2Enabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import { DropdownMenuItemTooltip } from 'components/ui/DropdownMenuItemTooltip'
import { useBranchQuery } from 'data/branches/branch-query'
import { useBranchResetMutation } from 'data/branches/branch-reset-mutation'
import { useBranchUpdateMutation } from 'data/branches/branch-update-mutation'
import type { Branch } from 'data/branches/branches-query'
import { branchKeys } from 'data/branches/keys'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useIsBranching2Enabled } from 'components/interfaces/App/FeaturePreview/FeaturePreviewContext'
import {
Button,
DropdownMenu,
Expand All @@ -32,10 +32,10 @@ import {
DropdownMenuTrigger,
} from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal'
import { BranchLoader, BranchManagementSection, BranchRow, BranchRowLoader } from './BranchPanels'
import { EditBranchModal } from './EditBranchModal'
import { PreviewBranchesEmptyState } from './EmptyStates'
import TextConfirmModal from 'ui-patterns/Dialogs/TextConfirmModal'

interface OverviewProps {
isLoading: boolean
Expand Down Expand Up @@ -99,7 +99,7 @@ export const Overview = ({
{isSuccess && persistentBranches.length === 0 && (
<div className="flex items-center flex-col justify-center w-full py-10">
<p>No persistent branches</p>
<p className="text-foreground-light">
<p className="text-foreground-light text-center">
Persistent branches are long-lived, cannot be reset, and are ideal for staging
environments.
</p>
Expand Down
9 changes: 2 additions & 7 deletions apps/studio/components/interfaces/Reports/ReportChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ const ReportChart = ({
const {
data,
isLoading: isLoadingChart,
chartAttributes,
highlightedValue,
} = useChartData({
attributes: chart.attributes,
Expand All @@ -72,9 +71,7 @@ const ReportChart = ({
const { data: filledData, isError: isFillError } = useFillTimeseriesSorted(
chartDataArray,
'period_start',
(chartAttributes.length > 0 ? chartAttributes : chart.attributes).map(
(attr: any) => attr.attribute
),
chart.attributes.map((attr: any) => attr.attribute),
0,
startDate,
endDate,
Expand Down Expand Up @@ -159,9 +156,7 @@ const ReportChart = ({
return (
<LogChartHandler
{...chart}
attributes={
(chartAttributes.length > 0 ? chartAttributes : chart.attributes) as MultiAttribute[]
}
attributes={chart.attributes as MultiAttribute[]}
data={finalData}
isLoading={isLoadingChart || isLoading}
highlightedValue={highlightedValue as any}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import TimeSplitInput from 'components/ui/DatePicker/TimeSplitInput'
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
import {
Button,
ButtonProps,
PopoverContent_Shadcn_,
PopoverTrigger_Shadcn_,
Popover_Shadcn_,
Expand All @@ -31,9 +32,17 @@ interface Props {
value: DatePickerValue
helpers: DatetimeHelper[]
onSubmit: (value: DatePickerValue) => void
buttonTriggerProps?: ButtonProps
popoverContentProps?: typeof PopoverContent_Shadcn_
}

export const LogsDatePicker = ({ onSubmit, helpers, value }: PropsWithChildren<Props>) => {
export const LogsDatePicker = ({
onSubmit,
helpers,
value,
buttonTriggerProps,
popoverContentProps,
}: PropsWithChildren<Props>) => {
const [open, setOpen] = useState(false)

// Reset the state when the popover closes
Expand Down Expand Up @@ -230,7 +239,7 @@ export const LogsDatePicker = ({ onSubmit, helpers, value }: PropsWithChildren<P
return (
<Popover_Shadcn_ open={open} onOpenChange={setOpen}>
<PopoverTrigger_Shadcn_ asChild>
<Button type="default" icon={<Clock size={12} />}>
<Button type="default" icon={<Clock size={12} />} {...buttonTriggerProps}>
{value.isHelper
? value.text
: `${dayjs(value.from).format('DD MMM, HH:mm')} - ${dayjs(value.to || new Date()).format('DD MMM, HH:mm')}`}
Expand All @@ -239,8 +248,9 @@ export const LogsDatePicker = ({ onSubmit, helpers, value }: PropsWithChildren<P
<PopoverContent_Shadcn_
className="flex w-full p-0"
side="bottom"
align="center"
align="end"
portal={true}
{...popoverContentProps}
>
<RadioGroup
onValueChange={handleHelperChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,22 +98,6 @@ export const filterFields = [
)
},
},
{
label: 'Host',
value: 'host',
type: 'checkbox',
defaultOpen: false,
options: [],
hasDynamicOptions: true,
hasAsyncSearch: true,
component: (props: Option) => {
return (
<span className="truncate block text-[0.75rem]" title={props.value as string}>
{props.value}
</span>
)
},
},
{
label: 'Pathname',
value: 'pathname',
Expand Down Expand Up @@ -196,12 +180,6 @@ export const sheetFields = [
),
skeletonClassName: 'w-56',
},
{
id: 'host',
label: 'Host',
type: 'input',
skeletonClassName: 'w-24',
},
{
id: 'pathname',
label: 'Pathname',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export const columnSchema = z.object({
id: z.string(),
log_type: z.enum(LOG_TYPES),
method: z.enum(METHODS),
host: z.string(),
pathname: z.string(),
level: z.enum(LEVELS),
status: z.number(),
Expand All @@ -36,7 +35,6 @@ export const columnFilterSchema = z.object({
.transform((val) => val.split(ARRAY_DELIMITER))
.pipe(z.enum(METHODS).array())
.optional(),
host: z.string().optional(),
pathname: z.string().optional(),
status: z
.string()
Expand Down
30 changes: 25 additions & 5 deletions apps/studio/components/interfaces/UnifiedLogs/UnifiedLogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
Separator,
} from 'ui'
import { RefreshButton } from '../../ui/DataTable/RefreshButton'
import { UNIFIED_LOGS_COLUMNS } from './components/Columns'
import { generateDynamicColumns, UNIFIED_LOGS_COLUMNS } from './components/Columns'
import { DownloadLogsButton } from './components/DownloadLogsButton'
import { LogsListPanel } from './components/LogsListPanel'
import { ServiceFlowPanel } from './ServiceFlowPanel'
Expand Down Expand Up @@ -100,6 +100,8 @@ export const UnifiedLogs = () => {
data: unifiedLogsData,
isLoading,
isFetching,
isFetchingNextPage,
isFetchingPreviousPage,
hasNextPage,
refetch: refetchLogs,
fetchNextPage,
Expand Down Expand Up @@ -131,6 +133,9 @@ export const UnifiedLogs = () => {

const isRefetchingData = isFetching || isFetchingCounts || isFetchingCharts

// Only fade when filtering (not when loading more data or live mode)
const isFetchingButNotPaginating = isFetching && !isFetchingNextPage && !isFetchingPreviousPage

const rawFlatData = useMemo(() => {
return unifiedLogsData?.pages?.flatMap((page) => page.data ?? []) ?? []
}, [unifiedLogsData?.pages])
Expand Down Expand Up @@ -165,13 +170,18 @@ export const UnifiedLogs = () => {
return cn(levelClassName, isPast ? 'opacity-50' : 'opacity-100', 'h-[30px]')
}

// Generate dynamic columns based on current data
const { columns: dynamicColumns, columnVisibility: dynamicColumnVisibility } = useMemo(() => {
return generateDynamicColumns(flatData)
}, [flatData])

const table: Table<any> = useReactTable({
data: flatData,
columns: UNIFIED_LOGS_COLUMNS,
columns: dynamicColumns,
state: {
columnFilters,
sorting,
columnVisibility,
columnVisibility: { ...columnVisibility, ...dynamicColumnVisibility },
rowSelection,
columnOrder,
},
Expand Down Expand Up @@ -331,7 +341,10 @@ export const UnifiedLogs = () => {
/>
<TimelineChart
data={unifiedLogsChart}
className="-mb-2"
className={cn(
'-mb-2',
isFetchingCharts && 'opacity-60 transition-opacity duration-150'
)}
columnId="timestamp"
chartConfig={filteredChartConfig}
/>
Expand All @@ -346,7 +359,14 @@ export const UnifiedLogs = () => {
className="h-full"
>
<ResizablePanelGroup key="main-logs" direction="vertical" className="h-full">
<ResizablePanel defaultSize={100} minSize={30} className="bg">
<ResizablePanel
defaultSize={100}
minSize={30}
className={cn(
'bg',
isFetchingButNotPaginating && 'opacity-60 transition-opacity duration-150'
)}
>
<DataTableInfinite
columns={UNIFIED_LOGS_COLUMNS}
totalRows={totalDBRowCount}
Expand Down
Loading
Loading