Files
supabase/apps/studio/components/interfaces/Observability/DatabaseInfrastructureSection.utils.ts

97 lines
2.7 KiB
TypeScript

import type { InfraMonitoringResponse } from '@/data/analytics/infra-monitoring-query'
type NumericValue = string | number | undefined
/**
* Parses a numeric value that can be a number, string, or undefined.
* Returns 0 for invalid or missing values.
*/
export function parseNumericValue(val: NumericValue): number {
if (typeof val === 'number') return val
if (typeof val === 'string') return parseFloat(val) || 0
return 0
}
type MetricData = {
current: number
max: number
}
type InfrastructureMetrics = {
cpu: MetricData
ram: MetricData
disk: MetricData
diskIo: MetricData
}
export function parseInfrastructureMetrics(
infraData: InfraMonitoringResponse | undefined
): InfrastructureMetrics | null {
if (!infraData) {
return null
}
const series = 'series' in infraData ? infraData.series : {}
const cpuValue = parseNumericValue(series.avg_cpu_usage?.totalAverage)
const ramValue = parseNumericValue(series.ram_usage?.totalAverage)
const diskSystemValue = parseNumericValue(series.disk_fs_used_system?.totalAverage)
const diskWalValue = parseNumericValue(series.disk_fs_used_wal?.totalAverage)
const diskDatabaseValue = parseNumericValue(series.pg_database_size?.totalAverage)
const diskSizeValue = parseNumericValue(series.disk_fs_size?.totalAverage)
const diskUsedValue = diskSystemValue + diskWalValue + diskDatabaseValue
const diskUsageValue = diskSizeValue > 0 ? (diskUsedValue / diskSizeValue) * 100 : 0
const diskIoValue = parseNumericValue(series.disk_io_consumption?.totalAverage)
return {
cpu: {
current: cpuValue,
max: 100,
},
ram: {
current: ramValue,
max: 100,
},
disk: {
current: diskUsageValue,
max: 100,
},
diskIo: {
current: diskIoValue,
max: 100,
},
}
}
type ConnectionsData = {
peak: number
max: number
}
type MaxConnectionsData = {
maxConnections?: number
}
export function parseConnectionsData(
infraData: InfraMonitoringResponse | undefined,
maxConnectionsData: MaxConnectionsData | undefined
): ConnectionsData {
const max = maxConnectionsData?.maxConnections ?? 0
if (!infraData || !('series' in infraData)) {
return { peak: 0, max }
}
// Show the highest connection count observed in the selected window rather
// than the window's totalAverage. The average varies with bucket granularity
// (e.g. 1h vs 1m) and is hard to reason about; peak is interval-stable and
// the more actionable signal for headroom against the connection limit.
let peak = 0
for (const point of infraData.data ?? []) {
const n = parseNumericValue(point?.values?.pg_stat_database_num_backends)
if (n > peak) peak = n
}
return { peak: Math.round(peak), max }
}