mirror of
https://github.com/supabase/supabase.git
synced 2026-05-08 18:00:20 -04:00
4a0bb36ca8
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
108 lines
3.4 KiB
TypeScript
108 lines
3.4 KiB
TypeScript
import {
|
|
RawAuthMetricsResponseSchema,
|
|
type RawAuthMetricsResponse,
|
|
type RawAuthMetricsRow,
|
|
} from './OverviewUsage.schema'
|
|
import { get } from '@/data/fetchers'
|
|
|
|
export type AuthMetricsResponse = RawAuthMetricsResponse
|
|
|
|
export type MetricName =
|
|
| 'activeUsers'
|
|
| 'signUpCount'
|
|
| 'apiTotalRequests'
|
|
| 'apiErrorRequests'
|
|
| 'authTotalRequests'
|
|
| 'authTotalErrors'
|
|
| 'passwordResetRequests'
|
|
|
|
type NumericMetricKey = keyof Omit<RawAuthMetricsRow, 'period'>
|
|
|
|
const metricKeyMap: Record<MetricName, NumericMetricKey> = {
|
|
activeUsers: 'active_users',
|
|
signUpCount: 'sign_up_count',
|
|
apiTotalRequests: 'api_total_requests',
|
|
apiErrorRequests: 'api_error_requests',
|
|
authTotalRequests: 'auth_total_requests',
|
|
authTotalErrors: 'auth_total_errors',
|
|
passwordResetRequests: 'password_reset_requests',
|
|
}
|
|
|
|
export const fetchAllAuthMetrics = async (projectRef: string): Promise<RawAuthMetricsResponse> => {
|
|
const { data, error } = await get(
|
|
`/platform/projects/{ref}/analytics/endpoints/auth.metrics` as any,
|
|
{
|
|
params: {
|
|
path: { ref: projectRef },
|
|
query: {
|
|
interval: '1day',
|
|
},
|
|
},
|
|
}
|
|
)
|
|
if (error) throw error
|
|
|
|
const parsed = RawAuthMetricsResponseSchema.safeParse(data)
|
|
if (!parsed.success) {
|
|
const first = parsed.error.issues[0]
|
|
throw new Error(`Invalid auth metrics response: ${first?.message ?? 'Invalid shape'}`)
|
|
}
|
|
return parsed.data
|
|
}
|
|
|
|
export const getMetricValues = (
|
|
metrics: AuthMetricsResponse | undefined,
|
|
metricName: MetricName
|
|
) => {
|
|
const key = metricKeyMap[metricName]
|
|
const currentRow = metrics?.result.find((r) => r.period === 'current')
|
|
const previousRow = metrics?.result.find((r) => r.period === 'previous')
|
|
return {
|
|
current: currentRow ? currentRow[key] : 0,
|
|
previous: previousRow ? previousRow[key] : 0,
|
|
}
|
|
}
|
|
|
|
export const getApiSuccessRates = (metrics: AuthMetricsResponse | undefined) => {
|
|
const { current: apiTotalCurrent, previous: apiTotalPrevious } = getMetricValues(
|
|
metrics,
|
|
'apiTotalRequests'
|
|
)
|
|
const { current: apiErrorCurrent, previous: apiErrorPrevious } = getMetricValues(
|
|
metrics,
|
|
'apiErrorRequests'
|
|
)
|
|
const current =
|
|
apiTotalCurrent > 0 ? Math.max(0, 100 - (apiErrorCurrent / apiTotalCurrent) * 100) : 0
|
|
const previous =
|
|
apiTotalPrevious > 0 ? Math.max(0, 100 - (apiErrorPrevious / apiTotalPrevious) * 100) : 0
|
|
return { current, previous }
|
|
}
|
|
|
|
export const getAuthSuccessRates = (metrics: AuthMetricsResponse | undefined) => {
|
|
const { current: authTotalRequestsCurrent, previous: authTotalRequestsPrevious } =
|
|
getMetricValues(metrics, 'authTotalRequests')
|
|
const { current: authTotalErrorsCurrent, previous: authTotalErrorsPrevious } = getMetricValues(
|
|
metrics,
|
|
'authTotalErrors'
|
|
)
|
|
const current =
|
|
authTotalRequestsCurrent > 0
|
|
? Math.max(0, 100 - (authTotalErrorsCurrent / authTotalRequestsCurrent) * 100)
|
|
: 0
|
|
const previous =
|
|
authTotalRequestsPrevious > 0
|
|
? Math.max(0, 100 - (authTotalErrorsPrevious / authTotalRequestsPrevious) * 100)
|
|
: 0
|
|
return { current, previous }
|
|
}
|
|
|
|
export const calculatePercentageChange = (current: number, previous: number): number => {
|
|
if (previous === 0) return current > 0 ? 100 : 0
|
|
return ((current - previous) / previous) * 100
|
|
}
|
|
|
|
export const getChangeColor = (percentageChange: number): string => {
|
|
return percentageChange >= 0 ? 'text-brand' : 'text-destructive'
|
|
}
|