From 6b6b7c048595ee5cddda4d6ea737a514a561f3fa Mon Sep 17 00:00:00 2001
From: Jordi Enric <37541088+jordienr@users.noreply.github.com>
Date: Thu, 16 Oct 2025 17:15:20 +0200
Subject: [PATCH] cleanup: consolidate database report (#39525)
* consolidate
* fix availableIn
---
apps/studio/data/reports/database-charts.ts | 254 +++---------------
.../pages/project/[ref]/reports/database.tsx | 146 ++++------
2 files changed, 88 insertions(+), 312 deletions(-)
diff --git a/apps/studio/data/reports/database-charts.ts b/apps/studio/data/reports/database-charts.ts
index 3f8efcc622c..692edba8947 100644
--- a/apps/studio/data/reports/database-charts.ts
+++ b/apps/studio/data/reports/database-charts.ts
@@ -7,210 +7,6 @@ import { DiskAttributesData } from '../config/disk-attributes-query'
import { MaxConnectionsData } from '../database/max-connections-query'
import { Project } from '../projects/project-detail-query'
-export const getReportAttributes = (diskConfig?: DiskAttributesData): ReportAttributes[] => {
- return [
- {
- id: 'ram-usage',
- label: 'Memory usage',
- availableIn: ['free', 'pro'],
- hide: false,
- showTooltip: false,
- showLegend: false,
- hideChartType: false,
- defaultChartStyle: 'bar',
- showMaxValue: false,
- showGrid: false,
- syncId: 'database-reports',
- valuePrecision: 0,
- format: '%',
- attributes: [
- {
- attribute: 'ram_usage',
- provider: 'infra-monitoring',
- label: 'Memory usage',
- format: '%',
- tooltip: 'RAM usage by the database',
- },
- ],
- },
- {
- id: 'avg_cpu_usage',
- label: 'Average CPU usage',
- syncId: 'database-reports',
- format: '%',
- valuePrecision: 2,
- availableIn: ['free', 'pro'],
- hide: false,
- showTooltip: false,
- showLegend: false,
- showMaxValue: false,
- showGrid: false,
- hideChartType: false,
- defaultChartStyle: 'bar',
- attributes: [
- {
- attribute: 'avg_cpu_usage',
- provider: 'infra-monitoring',
- label: 'Average CPU usage',
- format: '%',
- tooltip: 'Average CPU usage',
- },
- ],
- },
- {
- id: 'max_cpu_usage',
- label: 'Max CPU usage',
- syncId: 'database-reports',
- format: '%',
- valuePrecision: 2,
- availableIn: ['free', 'pro'],
- hide: false,
- showTooltip: false,
- showLegend: false,
- showMaxValue: false,
- showGrid: false,
- hideChartType: false,
- defaultChartStyle: 'bar',
- attributes: [
- {
- attribute: 'max_cpu_usage',
- provider: 'infra-monitoring',
- label: 'Max CPU usage',
- format: '%',
- tooltip: 'Max CPU usage',
- },
- ],
- },
- {
- id: 'disk-iops',
- label: 'Disk Input/Output operations per second (IOPS)',
- syncId: 'database-reports',
- availableIn: ['free', 'pro'],
- hide: false,
- showTooltip: true,
- valuePrecision: 2,
- showLegend: true,
- hideChartType: false,
- showGrid: true,
- showMaxValue: false,
- YAxisProps: {
- width: 35,
- tickFormatter: (value: any) => numberFormatter(value, 2),
- },
- defaultChartStyle: 'line',
- docsUrl: `${DOCS_URL}/guides/platform/compute-and-disk#compute-size`,
- attributes: [
- {
- attribute: 'disk_iops_write',
- provider: 'infra-monitoring',
- label: 'Write IOPS',
- tooltip:
- 'Number of write operations per second. High values indicate frequent data writes, logging, or transaction activity',
- },
- {
- attribute: 'disk_iops_read',
- provider: 'infra-monitoring',
- label: 'Read IOPS',
- tooltip:
- 'Number of read operations per second. High values suggest frequent disk reads due to queries or poor caching',
- },
- {
- attribute: 'disk_iops_max',
- provider: 'reference-line',
- label: 'Max IOPS',
- value: diskConfig?.attributes?.iops,
- tooltip:
- 'Maximum IOPS (Input/Output Operations Per Second) for your current compute size',
- isMaxValue: true,
- },
- ],
- },
- {
- id: 'disk-io-usage',
- label: 'Disk IO Usage',
- syncId: 'database-reports',
- availableIn: ['team', 'enterprise'],
- hide: false,
- format: '%',
- attributes: [],
- },
- {
- id: 'pooler-database-connections',
- label: 'Pooler to Database connections',
- syncId: 'database-reports',
- valuePrecision: 0,
- availableIn: ['free', 'pro'],
- hide: false,
- showTooltip: false,
- showLegend: false,
- showMaxValue: false,
- hideChartType: false,
- showGrid: false,
- defaultChartStyle: 'bar',
- attributes: [
- {
- attribute: 'pg_stat_database_num_backends',
- provider: 'infra-monitoring',
- label: 'Database connections',
- tooltip: 'Number of pooler connections to the database',
- },
- ],
- },
- {
- id: 'supavisor-connections',
- label: 'Shared Pooler connections',
- syncId: 'database-reports',
- valuePrecision: 0,
- availableIn: ['free', 'pro'],
- hide: false,
- showTooltip: false,
- showLegend: false,
- showMaxValue: false,
- showGrid: false,
- hideChartType: false,
- defaultChartStyle: 'bar',
- attributes: [
- {
- attribute: 'supavisor_connections_active',
- provider: 'infra-monitoring',
- label: 'Client to Shared Pooler connections',
- tooltip: 'Active connections from clients to the shared pooler',
- },
- ],
- },
- {
- id: 'pgbouncer-connections',
- label: 'Dedicated Pooler connections',
- syncId: 'database-reports',
- valuePrecision: 0,
- availableIn: ['pro', 'team'],
- hide: false,
- showTooltip: false,
- showLegend: false,
- showMaxValue: false,
- showGrid: false,
- hideChartType: false,
- defaultChartStyle: 'bar',
- attributes: [
- {
- attribute: 'client_connections_pgbouncer',
- provider: 'infra-monitoring',
- label: 'Client to Dedicated Pooler connections',
- tooltip: 'PgBouncer connections',
- },
- ],
- },
- {
- id: 'disk-size',
- label: 'Disk Usage',
- syncId: 'database-reports',
- availableIn: ['team', 'enterprise'],
- hide: false,
- attributes: [],
- },
- ]
-}
-
export const getReportAttributesV2: (
org: Organization,
project: Project,
@@ -227,7 +23,7 @@ export const getReportAttributesV2: (
id: 'ram-usage',
label: 'Memory usage',
docsUrl: `${DOCS_URL}/guides/telemetry/reports#memory-usage`,
- availableIn: ['team', 'enterprise'],
+ availableIn: ['free', 'pro', 'team', 'enterprise'],
hide: false,
showTooltip: true,
showLegend: true,
@@ -272,7 +68,7 @@ export const getReportAttributesV2: (
syncId: 'database-reports',
format: '%',
valuePrecision: 2,
- availableIn: ['team', 'enterprise'],
+ availableIn: ['free', 'pro', 'team', 'enterprise'],
hide: false,
showTooltip: true,
showLegend: true,
@@ -339,7 +135,7 @@ export const getReportAttributesV2: (
label: 'Disk Input/Output operations per second (IOPS)',
docsUrl: `${DOCS_URL}/guides/telemetry/reports#disk-inputoutput-operations-per-second-iops`,
syncId: 'database-reports',
- availableIn: ['team', 'enterprise'],
+ availableIn: ['free', 'pro', 'team', 'enterprise'],
hide: false,
showTooltip: true,
valuePrecision: 2,
@@ -408,12 +204,46 @@ export const getReportAttributesV2: (
],
},
{
+ // Client Connections metric for free tier
+ id: 'client-connections-basic',
+ label: 'Database Connections',
+ syncId: 'database-reports',
+ valuePrecision: 0,
+ availableIn: ['free'],
+ hide: !isFreePlan,
+ showTooltip: false,
+ showLegend: false,
+ showMaxValue: true,
+ hideChartType: false,
+ showGrid: true,
+ YAxisProps: { width: 30 },
+ defaultChartStyle: 'line',
+ docsUrl: `${DOCS_URL}/guides/telemetry/reports#database-connections`,
+ attributes: [
+ {
+ attribute: 'total_db_connections',
+ provider: 'infra-monitoring',
+ label: 'Total connections',
+ tooltip: 'Total number of active database connections',
+ },
+ {
+ attribute: 'max_db_connections',
+ provider: 'reference-line',
+ label: 'Max connections',
+ value: maxConnections?.maxConnections,
+ tooltip: 'Max available connections for your current compute size',
+ isMaxValue: true,
+ },
+ ],
+ },
+ {
+ // advanced client connections metric for paid and above
id: 'client-connections',
label: 'Database Connections',
syncId: 'database-reports',
valuePrecision: 0,
- availableIn: ['team', 'enterprise'],
- hide: false,
+ availableIn: ['pro', 'team', 'enterprise'],
+ hide: isFreePlan,
showTooltip: true,
showLegend: true,
showMaxValue: true,
@@ -476,7 +306,7 @@ export const getReportAttributesV2: (
label: 'Dedicated Pooler Client Connections',
syncId: 'database-reports',
valuePrecision: 0,
- availableIn: ['pro', 'team'],
+ availableIn: ['pro', 'team', 'enterprise'],
hide: isFreePlan,
showTooltip: true,
showLegend: true,
@@ -508,7 +338,7 @@ export const getReportAttributesV2: (
label: 'Shared Pooler (Supavisor) client connections',
syncId: 'database-reports',
valuePrecision: 0,
- availableIn: ['pro', 'team'],
+ availableIn: ['pro', 'team', 'enterprise'],
hide: isFreePlan,
showTooltip: false,
showLegend: false,
@@ -531,7 +361,7 @@ export const getReportAttributesV2: (
label: 'Disk Usage',
syncId: 'database-reports',
valuePrecision: 2,
- availableIn: ['free', 'pro', 'team'],
+ availableIn: ['free', 'pro', 'team', 'enterprise'],
hide: false,
showTooltip: true,
showLegend: true,
diff --git a/apps/studio/pages/project/[ref]/reports/database.tsx b/apps/studio/pages/project/[ref]/reports/database.tsx
index 0ba53523e2e..5eaca8b089d 100644
--- a/apps/studio/pages/project/[ref]/reports/database.tsx
+++ b/apps/studio/pages/project/[ref]/reports/database.tsx
@@ -6,7 +6,7 @@ import Link from 'next/link'
import { useEffect, useState } from 'react'
import { toast } from 'sonner'
-import { useFlag, useParams } from 'common'
+import { useParams } from 'common'
import ReportHeader from 'components/interfaces/Reports/ReportHeader'
import ReportPadding from 'components/interfaces/Reports/ReportPadding'
import { REPORT_DATERANGE_HELPER_LABELS } from 'components/interfaces/Reports/Reports.constants'
@@ -33,7 +33,7 @@ import { useProjectDiskResizeMutation } from 'data/config/project-disk-resize-mu
import { useDatabaseSizeQuery } from 'data/database/database-size-query'
import { useMaxConnectionsQuery } from 'data/database/max-connections-query'
import { usePgbouncerConfigQuery } from 'data/database/pgbouncer-config-query'
-import { getReportAttributes, getReportAttributesV2 } from 'data/reports/database-charts'
+import { getReportAttributesV2 } from 'data/reports/database-charts'
import { useDatabaseReport } from 'data/reports/database-report-query'
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
@@ -65,7 +65,6 @@ export default DatabaseReport
const DatabaseUsage = () => {
const { db, chart, ref } = useParams()
- const isReportsV2 = useFlag('reportsDatabaseV2')
const { data: project } = useSelectedProjectQuery()
const { data: org } = useSelectedOrganizationQuery()
@@ -81,10 +80,6 @@ const DatabaseUsage = () => {
handleDatePickerChange,
} = useReportDateRange(REPORT_DATERANGE_HELPER_LABELS.LAST_60_MINUTES)
- const isTeamsOrEnterprisePlan =
- !isOrgPlanLoading && (orgPlan?.id === 'team' || orgPlan?.id === 'enterprise')
- const showChartsV2 = isReportsV2 || isTeamsOrEnterprisePlan
-
const state = useDatabaseSelectorStateSnapshot()
const queryClient = useQueryClient()
@@ -130,8 +125,7 @@ const DatabaseUsage = () => {
}
)
- const REPORT_ATTRIBUTES = getReportAttributes(diskConfig)
- const REPORT_ATTRIBUTES_V2 = getReportAttributesV2(
+ const REPORT_ATTRIBUTES = getReportAttributesV2(
org!,
project!,
diskConfig,
@@ -149,51 +143,22 @@ const DatabaseUsage = () => {
const onRefreshReport = async () => {
if (!selectedDateRange) return
- // [Joshen] Since we can't track individual loading states for each chart
- // so for now we mock a loading state that only lasts for a second
setIsRefreshing(true)
refresh()
const { period_start, period_end, interval } = selectedDateRange
- REPORT_ATTRIBUTES.forEach((attr) => {
- queryClient.invalidateQueries(
- analyticsKeys.infraMonitoring(ref, {
- attribute: attr?.id,
- startDate: period_start.date,
- endDate: period_end.date,
- interval,
- databaseIdentifier: state.selectedDatabaseId,
- })
- )
+ REPORT_ATTRIBUTES.forEach((chart: any) => {
+ chart.attributes.forEach((attr: any) => {
+ queryClient.invalidateQueries(
+ analyticsKeys.infraMonitoring(ref, {
+ attribute: attr.attribute,
+ startDate: period_start.date,
+ endDate: period_end.date,
+ interval,
+ databaseIdentifier: state.selectedDatabaseId,
+ })
+ )
+ })
})
- if (showChartsV2) {
- REPORT_ATTRIBUTES_V2.forEach((chart: any) => {
- chart.attributes.forEach((attr: any) => {
- queryClient.invalidateQueries(
- analyticsKeys.infraMonitoring(ref, {
- attribute: attr.attribute,
- startDate: period_start.date,
- endDate: period_end.date,
- interval,
- databaseIdentifier: state.selectedDatabaseId,
- })
- )
- })
- })
- } else {
- REPORT_ATTRIBUTES.forEach((chart: any) => {
- chart.attributes.forEach((attr: any) => {
- queryClient.invalidateQueries(
- analyticsKeys.infraMonitoring(ref, {
- attribute: attr.attribute,
- startDate: period_start.date,
- endDate: period_end.date,
- interval,
- databaseIdentifier: state.selectedDatabaseId,
- })
- )
- })
- })
- }
if (isReplicaSelected) {
queryClient.invalidateQueries(
analyticsKeys.infraMonitoring(ref, {
@@ -274,56 +239,37 @@ const DatabaseUsage = () => {
>
{selectedDateRange &&
orgPlan?.id &&
- (showChartsV2
- ? REPORT_ATTRIBUTES_V2.filter((chart) => !chart.hide).map((chart) => (
-
- ))
- : REPORT_ATTRIBUTES.filter((chart) => !chart.hide).map((chart, i) =>
- chart.availableIn?.includes(orgPlan?.id) ? (
-
- ) : (
-
- )
- ))}
+ REPORT_ATTRIBUTES.filter((chart) => !chart.hide).map((chart) =>
+ chart.availableIn?.includes(orgPlan?.id) ? (
+
+ ) : (
+
+ )
+ )}
{selectedDateRange && isReplicaSelected && (