Files
supabase/apps/studio/data/reports/v2/realtime.config.ts

392 lines
9.8 KiB
TypeScript

import { ReportConfig } from './reports.types'
import type { AnalyticsData, AnalyticsInterval } from '@/data/analytics/constants'
import { mapResponseToAnalyticsData } from '@/data/analytics/infra-monitoring-queries'
import {
getInfraMonitoringAttributes,
InfraMonitoringAttribute,
} from '@/data/analytics/infra-monitoring-query'
async function runInfraMonitoringQuery(
projectRef: string,
attribute: InfraMonitoringAttribute,
startDate: string,
endDate: string,
interval: AnalyticsInterval,
databaseIdentifier?: string
): Promise<AnalyticsData> {
const response = await getInfraMonitoringAttributes({
projectRef,
attributes: [attribute],
startDate,
endDate,
interval,
databaseIdentifier,
})
// Use shared mapping function that handles both single and multi-attribute response formats
const mapped = mapResponseToAnalyticsData(response, [attribute])
const analyticsData = mapped[attribute]
return {
data: analyticsData?.data ?? [],
format: analyticsData?.format,
yAxisLimit: analyticsData?.yAxisLimit,
total: analyticsData?.total,
totalGrouped: { [attribute]: analyticsData?.total },
} as AnalyticsData
}
export const realtimeReports = ({
projectRef,
startDate,
endDate,
interval,
databaseIdentifier,
}: {
projectRef: string
startDate: string
endDate: string
interval: AnalyticsInterval
databaseIdentifier?: string
}): ReportConfig[] => [
{
id: 'realtime_sum_connections_connected',
label: 'Connected Clients',
valuePrecision: 0,
hide: false,
showSumAsDefaultHighlight: false,
showNewBadge: true,
showTooltip: true,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'line',
titleTooltip: 'Total number of connected realtime clients.',
dataProvider: async () => {
const data = await runInfraMonitoringQuery(
projectRef,
'realtime_sum_connections_connected',
startDate,
endDate,
interval,
databaseIdentifier
)
const attributes = [
{
attribute: 'realtime_sum_connections_connected',
label: 'Connected Clients',
},
]
return { data: data?.data || [], attributes }
},
},
{
id: 'broadcast-events',
label: 'Broadcast Events',
valuePrecision: 0,
hide: false,
showNewBadge: true,
showTooltip: true,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'bar',
titleTooltip: '',
dataProvider: async () => {
const { data } = await runInfraMonitoringQuery(
projectRef,
'realtime_channel_events',
startDate,
endDate,
interval,
databaseIdentifier
)
const transformedData = data?.map((p) => ({
...p,
realtime_channel_events: Number(p.realtime_channel_events) || 0,
}))
const attributes = [
{
attribute: 'realtime_channel_events',
label: 'Events',
},
]
return { data: transformedData || [], attributes }
},
},
{
id: 'presence-events',
label: 'Presence Events',
valuePrecision: 0,
hide: false,
showNewBadge: true,
showTooltip: true,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'bar',
titleTooltip: '',
dataProvider: async () => {
const { data } = await runInfraMonitoringQuery(
projectRef,
'realtime_channel_presence_events',
startDate,
endDate,
interval,
databaseIdentifier
)
const transformedData = data?.map((p) => ({
...p,
realtime_channel_presence_events: Number(p.realtime_channel_presence_events) || 0,
}))
const attributes = [
{
attribute: 'realtime_channel_presence_events',
label: 'Events',
},
]
return { data: transformedData || [], attributes }
},
},
{
id: 'db-events',
label: 'Postgres Changes Events',
valuePrecision: 0,
hide: false,
showNewBadge: true,
showTooltip: true,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'bar',
titleTooltip: '',
dataProvider: async () => {
const { data } = await runInfraMonitoringQuery(
projectRef,
'realtime_channel_db_events',
startDate,
endDate,
interval,
databaseIdentifier
)
const transformedData = data?.map((p) => ({
...p,
realtime_channel_db_events: Number(p.realtime_channel_db_events) || 0,
}))
const attributes = [
{
attribute: 'realtime_channel_db_events',
label: 'Events',
},
]
return { data: transformedData || [], attributes }
},
},
{
id: 'realtime_rate_of_channel_joins',
label: 'Rate of Channel Joins',
valuePrecision: 2,
hide: false,
showSumAsDefaultHighlight: false,
showTooltip: false,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'line',
titleTooltip: '',
dataProvider: async () => {
const data = await runInfraMonitoringQuery(
projectRef,
'realtime_channel_joins',
startDate,
endDate,
interval,
databaseIdentifier
)
const attributes = [
{
attribute: 'realtime_channel_joins',
label: 'Channel Joins',
},
]
return { data: data?.data || [], attributes }
},
},
{
id: 'realtime_payload_size',
label: 'Message Payload Size',
valuePrecision: 2,
showNewBadge: true,
hide: false,
showSumAsDefaultHighlight: false,
showTooltip: true,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'line',
titleTooltip: 'Median size of message payloads sent',
YAxisProps: {
width: 50,
tickFormatter: (value: number) => `${value}B`,
},
format: (value: unknown) => `${Number(value).toFixed(2)}B`,
dataProvider: async () => {
const data = await runInfraMonitoringQuery(
projectRef,
'realtime_payload_size',
startDate,
endDate,
interval,
databaseIdentifier
)
const attributes = [
{
attribute: 'realtime_payload_size',
label: 'Median Payload Size (bytes)',
},
]
return { data: data?.data || [], attributes }
},
},
{
id: 'realtime_replication_connection_lag',
label: 'Broadcast From Database Replication Lag',
valuePrecision: 2,
showNewBadge: true,
hide: false,
showSumAsDefaultHighlight: false,
showTooltip: true,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'line',
titleTooltip:
'Median time between database commit and broadcast when using broadcast from database.',
entitlement: 'realtime',
requiredPlan: 'Pro',
YAxisProps: {
width: 50,
tickFormatter: (value: number) => `${value}ms`,
},
format: (value: unknown) => `${Number(value).toFixed(2)}ms`,
dataProvider: async () => {
const data = await runInfraMonitoringQuery(
projectRef,
'realtime_replication_connection_lag',
startDate,
endDate,
interval,
databaseIdentifier
)
const attributes = [
{
attribute: 'realtime_replication_connection_lag',
label: 'Median Replication Lag (ms)',
},
]
return { data: data?.data || [], attributes }
},
},
{
id: 'realtime_read_authorization_rls_execution_time',
label: '(Read) Private Channel Subscription RLS Execution Time',
valuePrecision: 2,
showNewBadge: true,
hide: false,
showSumAsDefaultHighlight: false,
showTooltip: true,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'line',
titleTooltip:
'Execution median time of RLS (Row Level Security) to subscribe to a private channel',
entitlement: 'realtime',
requiredPlan: 'Pro',
YAxisProps: {
width: 50,
tickFormatter: (value: number) => `${value}ms`,
},
format: (value: unknown) => `${Number(value).toFixed(2)}ms`,
dataProvider: async () => {
const data = await runInfraMonitoringQuery(
projectRef,
'realtime_read_authorization_rls_execution_time',
startDate,
endDate,
interval,
databaseIdentifier
)
const attributes = [
{
attribute: 'realtime_read_authorization_rls_execution_time',
label: 'RLS Execution Time (ms)',
},
]
return { data: data?.data || [], attributes }
},
},
{
id: 'realtime_write_authorization_rls_execution_time',
label: '(Write) Private Channel Subscription RLS Execution Time',
valuePrecision: 2,
showNewBadge: true,
hide: false,
showSumAsDefaultHighlight: false,
showTooltip: true,
showLegend: false,
showMaxValue: false,
hideChartType: false,
defaultChartStyle: 'line',
titleTooltip:
'Execution median time of RLS (Row Level Security) to publish to a private channel',
entitlement: 'realtime',
requiredPlan: 'Pro',
YAxisProps: {
width: 50,
tickFormatter: (value: number) => `${value}ms`,
},
format: (value: unknown) => `${Number(value).toFixed(2)}ms`,
dataProvider: async () => {
const data = await runInfraMonitoringQuery(
projectRef,
'realtime_write_authorization_rls_execution_time',
startDate,
endDate,
interval,
databaseIdentifier
)
const attributes = [
{
attribute: 'realtime_write_authorization_rls_execution_time',
label: 'RLS Execution Time (ms)',
},
]
return { data: data?.data || [], attributes }
},
},
]