usePostgrestOverviewMetrics.ts101 lines · main
| 1 | import { useQuery } from '@tanstack/react-query' |
| 2 | |
| 3 | import type { LogsBarChartDatum } from '../ProjectHome/ProjectUsage.metrics' |
| 4 | import { get } from '@/data/fetchers' |
| 5 | |
| 6 | type PostgrestMetricsVariables = { |
| 7 | projectRef: string |
| 8 | startDate: string |
| 9 | endDate: string |
| 10 | interval: '1hr' | '1day' | '7day' |
| 11 | } |
| 12 | |
| 13 | const getIntervalTrunc = (interval: '1hr' | '1day' | '7day') => { |
| 14 | switch (interval) { |
| 15 | case '1hr': |
| 16 | return 'minute' // 1-minute buckets for 1 hour |
| 17 | case '1day': |
| 18 | return 'hour' // 1-hour buckets for 1 day |
| 19 | case '7day': |
| 20 | return 'day' // 1-day buckets for 7 days |
| 21 | default: |
| 22 | return 'hour' |
| 23 | } |
| 24 | } |
| 25 | |
| 26 | const POSTGREST_METRICS_SQL = (interval: '1hr' | '1day' | '7day') => { |
| 27 | const truncInterval = getIntervalTrunc(interval) |
| 28 | |
| 29 | return ` |
| 30 | -- postgrest-overview-metrics |
| 31 | select |
| 32 | cast(timestamp_trunc(t.timestamp, ${truncInterval}) as datetime) as timestamp, |
| 33 | countif(response.status_code < 300) as ok_count, |
| 34 | countif(response.status_code >= 300 and response.status_code < 400) as warning_count, |
| 35 | countif(response.status_code >= 400) as error_count |
| 36 | FROM edge_logs t |
| 37 | cross join unnest(metadata) as m |
| 38 | cross join unnest(m.response) as response |
| 39 | cross join unnest(m.request) as request |
| 40 | WHERE |
| 41 | request.path like '/rest/%' |
| 42 | GROUP BY |
| 43 | timestamp |
| 44 | ORDER BY |
| 45 | timestamp ASC |
| 46 | ` |
| 47 | } |
| 48 | |
| 49 | type MetricsRow = { |
| 50 | timestamp: string |
| 51 | ok_count: number |
| 52 | warning_count: number |
| 53 | error_count: number |
| 54 | } |
| 55 | |
| 56 | async function fetchPostgrestMetrics( |
| 57 | { projectRef, startDate, endDate, interval }: PostgrestMetricsVariables, |
| 58 | signal?: AbortSignal |
| 59 | ) { |
| 60 | const sql = POSTGREST_METRICS_SQL(interval) |
| 61 | |
| 62 | const { data, error } = await get(`/platform/projects/{ref}/analytics/endpoints/logs.all`, { |
| 63 | params: { |
| 64 | path: { ref: projectRef }, |
| 65 | query: { |
| 66 | sql, |
| 67 | iso_timestamp_start: startDate, |
| 68 | iso_timestamp_end: endDate, |
| 69 | }, |
| 70 | }, |
| 71 | signal, |
| 72 | }) |
| 73 | |
| 74 | if (error || data?.error) { |
| 75 | throw error || data?.error |
| 76 | } |
| 77 | |
| 78 | return (data?.result || []) as MetricsRow[] |
| 79 | } |
| 80 | |
| 81 | export const usePostgrestOverviewMetrics = ( |
| 82 | { projectRef, startDate, endDate, interval }: PostgrestMetricsVariables, |
| 83 | options?: { enabled?: boolean } |
| 84 | ) => { |
| 85 | return useQuery({ |
| 86 | queryKey: ['postgrest-overview-metrics', projectRef, startDate, endDate, interval], |
| 87 | queryFn: ({ signal }) => |
| 88 | fetchPostgrestMetrics({ projectRef, startDate, endDate, interval }, signal), |
| 89 | enabled: (options?.enabled ?? true) && Boolean(projectRef), |
| 90 | staleTime: 1000 * 60, |
| 91 | }) |
| 92 | } |
| 93 | |
| 94 | export const transformPostgrestMetrics = (rows: MetricsRow[]): LogsBarChartDatum[] => { |
| 95 | return rows.map((row) => ({ |
| 96 | timestamp: row.timestamp, |
| 97 | ok_count: row.ok_count, |
| 98 | warning_count: row.warning_count, |
| 99 | error_count: row.error_count, |
| 100 | })) |
| 101 | } |