Files
supabase/apps/studio/hooks/analytics/useProjectUsageStats.tsx
T
Jordi Enric db0a2ab752 refactor useFillTimeSeriesSorted hook (#42255)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Safer error rendering across analytics and reporting with a fallback
"Unknown error".

* **Tests**
* Added unit tests covering timeseries sorting and timestamp validation.

* **Refactor**
* Standardized timeseries hook and all callers to accept a single
options object and improved nullish handling.

* **New Features**
* Exposed timeseries utilities and explicit options/result types;
exported chart data type.

* **Chores**
  * Relaxed index signatures to allow dynamic metric keys.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-29 21:05:09 +01:00

119 lines
3.0 KiB
TypeScript

import { useQuery } from '@tanstack/react-query'
import { LogsTableName } from 'components/interfaces/Settings/Logs/Logs.constants'
import type {
EventChart,
EventChartData,
Filters,
LogsEndpointParams,
} from 'components/interfaces/Settings/Logs/Logs.types'
import { genChartQuery } from 'components/interfaces/Settings/Logs/Logs.utils'
import { get } from 'data/fetchers'
import { useMemo } from 'react'
import { useFillTimeseriesSorted } from './useFillTimeseriesSorted'
import useTimeseriesUnixToIso from './useTimeseriesUnixToIso'
interface ProjectUsageStatsHookResult {
error: string | Object | null
isLoading: boolean
filters: Filters
params: LogsEndpointParams
eventChartData: EventChartData[]
refresh: () => void
}
function useProjectUsageStats({
projectRef,
table,
timestampStart,
timestampEnd,
filterOverride,
}: {
projectRef: string
table: LogsTableName
timestampStart: string
timestampEnd: string
filterOverride?: Filters
}): ProjectUsageStatsHookResult {
const filterOverrideString = JSON.stringify(filterOverride)
const mergedFilters = useMemo(
() => ({
...filterOverride,
}),
[filterOverrideString]
)
const params: LogsEndpointParams = useMemo(() => {
return { iso_timestamp_start: timestampStart, iso_timestamp_end: timestampEnd }
}, [timestampStart, timestampEnd])
const chartQuery = useMemo(
() => genChartQuery(table, params, mergedFilters),
[table, params, mergedFilters]
)
const chartQueryKey = useMemo(
() => [
'projects',
projectRef,
'logs-chart',
table,
{
projectRef,
sql: chartQuery,
iso_timestamp_start: timestampStart,
iso_timestamp_end: timestampEnd,
},
],
[projectRef, chartQuery, timestampStart, timestampEnd, table]
)
const { data: eventChartResponse, refetch: refreshEventChart } = useQuery({
queryKey: chartQueryKey,
queryFn: async ({ signal }) => {
const { data, error } = await get(`/platform/projects/{ref}/analytics/endpoints/logs.all`, {
params: {
path: { ref: projectRef },
query: {
iso_timestamp_start: timestampStart,
iso_timestamp_end: timestampEnd,
sql: chartQuery,
},
},
signal,
})
if (error) {
throw error
}
return data as unknown as EventChart
},
refetchOnWindowFocus: false,
enabled: typeof projectRef !== 'undefined',
})
const normalizedEventChartData = useTimeseriesUnixToIso(
eventChartResponse?.result ?? [],
'timestamp'
)
const { data: eventChartData, error: eventChartError } = useFillTimeseriesSorted({
data: normalizedEventChartData,
timestampKey: 'timestamp',
valueKey: 'count',
defaultValue: 0,
startDate: timestampStart,
endDate: timestampEnd ?? new Date().toISOString(),
})
return {
isLoading: !eventChartResponse,
error: eventChartError,
filters: mergedFilters,
params,
eventChartData,
refresh: refreshEventChart,
}
}
export default useProjectUsageStats