mirror of
https://github.com/supabase/supabase.git
synced 2026-06-20 16:26:02 +08:00
feat(logs): add realtime, supavisor, and pgbouncer to unified logs (#46786)
## Problem The unified logs view was missing three log sources that the backend already returns: Realtime (`realtime_logs`), Supavisor (`supavisor_logs`), and PgBouncer (`pgbouncer_logs`). Users had no way to filter or view logs from these services in the unified view. ## Fix - Added `realtime`, `supavisor`, and `pgbouncer` to `LOG_TYPE_PREDICATE` and `LOG_TYPE_EXPR` in the OTEL query builder so rows from these sources are matched and labeled correctly. - Added the three types to `LOG_TYPES` so filter chips appear in the UI. - Added icons (`Realtime` from the icons package, `Cable` from lucide-react for both pooler types) in `LogTypeIcon.tsx`. - Added display labels in `formatServiceTypeForDisplay` (`Realtime`, `Supavisor`, `PgBouncer`). - Fixed a pre-existing unsafe cast in `ServiceFlowPanel.tsx` where any log type not in the service flow allow-list (like the new types) would produce a truthy `serviceFlowType` and trigger a runtime error on row click. The fix checks against `SERVICE_FLOW_TYPES` before casting. Note: `pg_cron_logs` is not included because the backend otel query does not yet return that source. ## How to test 1. Open unified logs for a project that has Realtime activity. 2. In the log type filter, confirm `realtime`, `supavisor`, and `pgbouncer` chips are visible. 3. Toggle on `realtime` and confirm Realtime logs appear with the correct icon. 4. Click a realtime log row and confirm the detail panel opens on the raw JSON tab without a runtime error. 5. Toggle on `supavisor` or `pgbouncer` and confirm pooler logs appear if the project has connection pooler activity. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for three new log types — Realtime, Supavisor, and PgBouncer — in Unified Logs with display labels, icons, and filtering/viewing support. * **Bug Fixes / UI Behavior** * Service Flow “Overview” tab now only shows when the service type is recognized, preventing irrelevant overview content for unsupported log sources. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,7 @@ import { QuerySearchParamsType } from './UnifiedLogs.types'
|
||||
import { getRowTimestampMs } from './UnifiedLogs.utils'
|
||||
import { useDataTable } from '@/components/ui/DataTable/providers/DataTableProvider'
|
||||
import {
|
||||
SERVICE_FLOW_TYPES,
|
||||
ServiceFlowType,
|
||||
useUnifiedLogInspectionQuery,
|
||||
} from '@/data/logs/unified-log-inspection-query'
|
||||
@@ -63,8 +64,12 @@ export function ServiceFlowPanel({
|
||||
}, [selectedRowKey])
|
||||
|
||||
const logType = selectedRow?.log_type
|
||||
const serviceFlowType: ServiceFlowType | undefined =
|
||||
logType === 'edge function' ? 'edge-function' : (logType as ServiceFlowType)
|
||||
const normalizedLogType = logType === 'edge function' ? 'edge-function' : logType
|
||||
const serviceFlowType: ServiceFlowType | undefined = SERVICE_FLOW_TYPES.includes(
|
||||
normalizedLogType as ServiceFlowType
|
||||
)
|
||||
? (normalizedLogType as ServiceFlowType)
|
||||
: undefined
|
||||
const shouldShowServiceFlow = !!serviceFlowType
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -16,7 +16,16 @@ import {
|
||||
|
||||
export const REGIONS = ['ams', 'fra', 'gru', 'hkg', 'iad', 'syd'] as const
|
||||
export const METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'] as const
|
||||
export const LOG_TYPES = ['postgres', 'postgrest', 'auth', 'storage', 'edge function'] as const
|
||||
export const LOG_TYPES = [
|
||||
'postgres',
|
||||
'postgrest',
|
||||
'auth',
|
||||
'storage',
|
||||
'edge function',
|
||||
'realtime',
|
||||
'supavisor',
|
||||
'pgbouncer',
|
||||
] as const
|
||||
export const DEFAULT_LOG_TYPES = ['postgres', 'postgrest'] as const
|
||||
|
||||
const parseAsSort = createParser({
|
||||
|
||||
@@ -53,6 +53,9 @@ const LOG_TYPE_PREDICATE: Record<string, SafeLogSqlFragment> = {
|
||||
postgres: safeSql`source = 'postgres_logs'`,
|
||||
'edge function': safeSql`source = 'function_edge_logs'`,
|
||||
auth: safeSql`source = 'auth_logs'`,
|
||||
realtime: safeSql`source = 'realtime_logs'`,
|
||||
supavisor: safeSql`source = 'supavisor_logs'`,
|
||||
pgbouncer: safeSql`source = 'pgbouncer_logs'`,
|
||||
}
|
||||
|
||||
// Derived `log_type` column for SELECT / GROUP BY / countIf use.
|
||||
@@ -63,6 +66,9 @@ const LOG_TYPE_EXPR: SafeLogSqlFragment = safeSql`CASE
|
||||
WHEN source = 'postgres_logs' THEN 'postgres'
|
||||
WHEN source = 'function_edge_logs' THEN 'edge function'
|
||||
WHEN source = 'auth_logs' THEN 'auth'
|
||||
WHEN source = 'realtime_logs' THEN 'realtime'
|
||||
WHEN source = 'supavisor_logs' THEN 'supavisor'
|
||||
WHEN source = 'pgbouncer_logs' THEN 'pgbouncer'
|
||||
ELSE source
|
||||
END`
|
||||
|
||||
|
||||
@@ -95,6 +95,9 @@ export function formatServiceTypeForDisplay(serviceType: string): string {
|
||||
postgres: 'Postgres',
|
||||
auth: 'Auth',
|
||||
storage: 'Storage',
|
||||
realtime: 'Realtime',
|
||||
supavisor: 'Supavisor',
|
||||
pgbouncer: 'PgBouncer',
|
||||
}
|
||||
|
||||
return specialCases[serviceType.toLowerCase()] || serviceType
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Auth, EdgeFunctions, Storage } from 'icons'
|
||||
import { Box, Code2, Database } from 'lucide-react'
|
||||
import { Auth, EdgeFunctions, Realtime, Storage } from 'icons'
|
||||
import { Box, Cable, Code2, Database } from 'lucide-react'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
||||
|
||||
import { type LOG_TYPES } from '../UnifiedLogs.constants'
|
||||
@@ -11,38 +11,37 @@ interface LogTypeIconProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
type IconComponent = React.ComponentType<{
|
||||
size?: number
|
||||
strokeWidth?: number
|
||||
className?: string
|
||||
}>
|
||||
|
||||
// [Alaister]: commented out types coming in the future
|
||||
// edge: Globe,
|
||||
const ICON_MAP: Partial<Record<(typeof LOG_TYPES)[number], IconComponent>> = {
|
||||
postgrest: Code2,
|
||||
auth: Auth,
|
||||
'edge function': EdgeFunctions,
|
||||
postgres: Database,
|
||||
storage: Storage,
|
||||
realtime: Realtime,
|
||||
supavisor: Cable,
|
||||
pgbouncer: Cable,
|
||||
}
|
||||
|
||||
export const LogTypeIcon = ({
|
||||
type,
|
||||
size = 16,
|
||||
strokeWidth = 1.5,
|
||||
className,
|
||||
}: LogTypeIconProps) => {
|
||||
// [Alaister]: commented out types coming in the future
|
||||
const iconMap: Record<(typeof LOG_TYPES)[number], () => React.ReactNode> = {
|
||||
// edge: () => <Globe size={size} strokeWidth={strokeWidth} className={className} />,
|
||||
postgrest: () => <Code2 size={size} strokeWidth={strokeWidth} className={className} />,
|
||||
auth: () => <Auth size={size} strokeWidth={strokeWidth} className={className} />,
|
||||
'edge function': () => (
|
||||
<EdgeFunctions size={size} strokeWidth={strokeWidth} className={className} />
|
||||
),
|
||||
postgres: () => <Database size={size} strokeWidth={strokeWidth} className={className} />,
|
||||
// function_events: () => (
|
||||
// <EdgeFunctions size={size} strokeWidth={strokeWidth} className={className} />
|
||||
// ),
|
||||
// supavisor: () => <Cpu size={size} strokeWidth={strokeWidth} className={className} />,
|
||||
// postgres_upgrade: () => <Cpu size={size} strokeWidth={strokeWidth} className={className} />,
|
||||
storage: () => <Storage size={size} strokeWidth={strokeWidth} className={className} />,
|
||||
|
||||
// cron: () => <Clock size={size} strokeWidth={strokeWidth} className={className} />,
|
||||
}
|
||||
|
||||
const IconComponent =
|
||||
iconMap[type] || (() => <Box size={size} strokeWidth={strokeWidth} className={className} />)
|
||||
const Icon = ICON_MAP[type] ?? Box
|
||||
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<IconComponent />
|
||||
<Icon size={size} strokeWidth={strokeWidth} className={className} />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="left">
|
||||
<div className="text-xs">{type}</div>
|
||||
|
||||
@@ -3154,7 +3154,15 @@ export interface UnifiedLogsRowClickedEvent {
|
||||
* Server values are validated against this set by zod (UnifiedLogs.schema.ts) before
|
||||
* reaching the table; anything else is rejected upstream so the union here is exhaustive.
|
||||
*/
|
||||
logType: 'postgres' | 'postgrest' | 'auth' | 'storage' | 'edge function'
|
||||
logType:
|
||||
| 'postgres'
|
||||
| 'postgrest'
|
||||
| 'auth'
|
||||
| 'storage'
|
||||
| 'edge function'
|
||||
| 'realtime'
|
||||
| 'supavisor'
|
||||
| 'pgbouncer'
|
||||
}
|
||||
groups: TelemetryGroups
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user