import { useParams } from 'common' import { isEqual } from 'lodash' import { useEffect, useState } from 'react' import { PRESET_CONFIG } from '@/components/interfaces/Reports/Reports.constants' import { ReportFilterItem } from '@/components/interfaces/Reports/Reports.types' import { getLogsSql, queriesFactory } from '@/components/interfaces/Reports/Reports.utils' import type { LogsEndpointParams } from '@/components/interfaces/Settings/Logs/Logs.types' import { useDatabaseSelectorStateSnapshot } from '@/state/database-selector' export const useApiReport = () => { const { ref: projectRef } = useParams() const state = useDatabaseSelectorStateSnapshot() const identifier = state.selectedDatabaseId const [filters, setFilters] = useState([]) const queryHooks = queriesFactory( PRESET_CONFIG.api.queries, projectRef ?? 'default' ) const totalRequests = queryHooks.totalRequests() const topRoutes = queryHooks.topRoutes() const errorCounts = queryHooks.errorCounts() const topErrorRoutes = queryHooks.topErrorRoutes() const responseSpeed = queryHooks.responseSpeed() const topSlowRoutes = queryHooks.topSlowRoutes() const networkTraffic = queryHooks.networkTraffic() const requestsByCountry = queryHooks.requestsByCountry() const activeHooks = [ totalRequests, topRoutes, errorCounts, topErrorRoutes, responseSpeed, topSlowRoutes, networkTraffic, requestsByCountry, ] const addFilter = (filter: ReportFilterItem) => { // use a deep equal when comparing objects. if (filters.some((f) => isEqual(f, filter))) return setFilters((prev) => [...prev, filter].sort((a, b) => { const keyA = a.key.toLowerCase() const keyB = b.key.toLowerCase() if (keyA < keyB) { return -1 } if (keyA > keyB) { return 1 } return 0 }) ) } const removeFilter = (filter: ReportFilterItem) => removeFilters([filter]) const removeFilters = (toRemove: ReportFilterItem[]) => { setFilters((prev) => { return prev.filter((f) => !toRemove.find((r) => isEqual(f, r))) }) } // [Joshen] Keeping database selector separate from filter state, and merging them here for simplicity const formattedFilters: ReportFilterItem[] = [ ...filters, ...(identifier !== undefined ? [{ key: 'identifier', value: identifier, compare: 'is' } as ReportFilterItem] : []), ] useEffect(() => { // update sql for each query if (totalRequests.changeQuery) { totalRequests.changeQuery( getLogsSql(PRESET_CONFIG.api.queries.totalRequests, formattedFilters) ) } if (topRoutes.changeQuery) { topRoutes.changeQuery(getLogsSql(PRESET_CONFIG.api.queries.topRoutes, formattedFilters)) } if (errorCounts.changeQuery) { errorCounts.changeQuery(getLogsSql(PRESET_CONFIG.api.queries.errorCounts, formattedFilters)) } if (topErrorRoutes.changeQuery) { topErrorRoutes.changeQuery( getLogsSql(PRESET_CONFIG.api.queries.topErrorRoutes, formattedFilters) ) } if (responseSpeed.changeQuery) { responseSpeed.changeQuery( getLogsSql(PRESET_CONFIG.api.queries.responseSpeed, formattedFilters) ) } if (topSlowRoutes.changeQuery) { topSlowRoutes.changeQuery( getLogsSql(PRESET_CONFIG.api.queries.topSlowRoutes, formattedFilters) ) } if (networkTraffic.changeQuery) { networkTraffic.changeQuery( getLogsSql(PRESET_CONFIG.api.queries.networkTraffic, formattedFilters) ) } if (requestsByCountry.changeQuery) { requestsByCountry.changeQuery( getLogsSql(PRESET_CONFIG.api.queries.requestsByCountry, formattedFilters) ) } }, [JSON.stringify(formattedFilters)]) const handleRefresh = async () => { activeHooks.forEach((hook) => hook.runQuery()) } const handleSetParams = (params: Partial) => { activeHooks.forEach((hook) => { hook.setParams?.((prev: LogsEndpointParams) => ({ ...prev, ...params })) }) } const isLoading = activeHooks.some((hook) => hook.isLoading) return { data: { totalRequests: totalRequests.logData, errorCounts: errorCounts.logData, responseSpeed: responseSpeed.logData, topRoutes: topRoutes.logData, topErrorRoutes: topErrorRoutes.logData, topSlowRoutes: topSlowRoutes.logData, networkTraffic: networkTraffic.logData, requestsByCountry: requestsByCountry.logData, }, params: { totalRequests: totalRequests.params, errorCounts: errorCounts.params, responseSpeed: responseSpeed.params, topRoutes: topRoutes.params, topErrorRoutes: topErrorRoutes.params, topSlowRoutes: topSlowRoutes.params, networkTraffic: networkTraffic.params, requestsByCountry: requestsByCountry.params, }, error: { totalRequest: totalRequests.error, errorCounts: errorCounts.error, responseSpeed: responseSpeed.error, topRoutes: topRoutes.error, topErrorRoute: topErrorRoutes.error, topSlowRoutes: topSlowRoutes.error, networkTraffic: networkTraffic.error, requestsByCountry: requestsByCountry.error, }, mergeParams: handleSetParams, filters, addFilter, removeFilter, removeFilters, isLoading, refresh: handleRefresh, } }