| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- import { useInfiniteQuery, useQuery } from '@tanstack/react-query'
- import dayjs from 'dayjs'
- import { useCallback, useMemo, useState } from 'react'
- import { useFillTimeseriesSorted } from './useFillTimeseriesSorted'
- import { useLogsUrlState } from './useLogsUrlState'
- import useTimeseriesUnixToIso from './useTimeseriesUnixToIso'
- import {
- getDefaultHelper,
- LogsTableName,
- PREVIEWER_DATEPICKER_HELPERS,
- } from '@/components/interfaces/Settings/Logs/Logs.constants'
- import type {
- Count,
- EventChart,
- EventChartData,
- Filters,
- LogData,
- Logs,
- LogsEndpointParams,
- } from '@/components/interfaces/Settings/Logs/Logs.types'
- import {
- genChartQuery,
- genCountQuery,
- genDefaultQuery,
- } from '@/components/interfaces/Settings/Logs/Logs.utils'
- import { get } from '@/data/fetchers'
- interface LogsPreviewHook {
- logData: LogData[]
- error: string | Object | null
- newCount: number
- isSuccess: boolean
- isLoading: boolean
- isLoadingOlder: boolean
- filters: Filters
- params: LogsEndpointParams
- oldestTimestamp?: string
- eventChartData: EventChartData[]
- loadOlder: () => void
- refresh: () => void
- }
- function useLogsPreview({
- projectRef,
- table,
- filterOverride,
- limit,
- }: {
- projectRef: string
- table: LogsTableName
- filterOverride?: Filters
- limit?: number
- }): LogsPreviewHook {
- const defaultHelper = getDefaultHelper(PREVIEWER_DATEPICKER_HELPERS)
- const [latestRefresh, setLatestRefresh] = useState(new Date().toISOString())
- const {
- timestampStart: urlTimestampStart,
- timestampEnd: urlTimestampEnd,
- filters: urlFilters,
- search,
- } = useLogsUrlState()
- const timestampStart = useMemo(
- () => urlTimestampStart || defaultHelper.calcFrom(),
- [urlTimestampStart, defaultHelper]
- )
- const timestampEnd = useMemo(
- () => urlTimestampEnd || defaultHelper.calcTo(),
- [urlTimestampEnd, defaultHelper]
- )
- const mergedFilters = useMemo(
- () => ({
- ...urlFilters,
- ...filterOverride,
- ...(search ? { search_query: search } : {}),
- }),
- [JSON.stringify(urlFilters), JSON.stringify(filterOverride), search]
- )
- const params: LogsEndpointParams = useMemo(() => {
- const currentSql = genDefaultQuery(table, mergedFilters, limit)
- return {
- iso_timestamp_start: timestampStart,
- iso_timestamp_end: timestampEnd,
- sql: currentSql,
- }
- }, [timestampStart, timestampEnd, table, mergedFilters, limit])
- const queryKey = useMemo(() => ['projects', projectRef, 'logs', params], [projectRef, params])
- const {
- data,
- isSuccess,
- isLoading,
- isRefetching,
- error: rqError,
- fetchNextPage,
- isFetchingNextPage,
- refetch,
- } = useInfiniteQuery({
- queryKey,
- queryFn: async ({ signal, pageParam }) => {
- const { data, error } = await get(`/platform/projects/{ref}/analytics/endpoints/logs.all`, {
- params: {
- path: { ref: projectRef },
- query: {
- ...params,
- iso_timestamp_end: pageParam || params.iso_timestamp_end,
- },
- },
- signal,
- })
- if (error) {
- throw error
- }
- return data as unknown as Logs
- },
- refetchOnWindowFocus: false,
- initialPageParam: undefined as string | undefined,
- getNextPageParam(lastPage) {
- if ((lastPage.result?.length ?? 0) === 0) {
- return undefined
- }
- const len = lastPage.result.length
- const { timestamp: tsLimit }: LogData = lastPage.result[len - 1]
- const isoTsLimit = dayjs.utc(Number(tsLimit / 1000)).toISOString()
- return isoTsLimit
- },
- })
- const { logData, error, oldestTimestamp } = useMemo(() => {
- let logData: LogData[] = []
- let error: null | string | object = rqError ? (rqError as any).message : null
- data?.pages?.forEach((response) => {
- if (response?.result) {
- logData = [...logData, ...response.result]
- }
- if (!error && response?.error) {
- error = response.error
- }
- })
- const oldestTimestamp = logData.length > 0 ? logData[logData.length - 1]?.timestamp : undefined
- return { logData, error, oldestTimestamp }
- }, [data?.pages])
- const countQuerySql = useMemo(() => genCountQuery(table, mergedFilters), [table, mergedFilters])
- const countQueryKey = useMemo(
- () => [
- 'projects',
- projectRef,
- 'logs-count',
- {
- projectRef,
- sql: countQuerySql,
- iso_timestamp_start: latestRefresh,
- iso_timestamp_end: timestampEnd,
- table,
- mergedFilters,
- },
- ],
- [projectRef, countQuerySql, latestRefresh, timestampEnd, table, mergedFilters]
- )
- const { data: countData } = useQuery({
- queryKey: countQueryKey,
- queryFn: async ({ signal }) => {
- const { data, error } = await get(`/platform/projects/{ref}/analytics/endpoints/logs.all`, {
- params: {
- path: { ref: projectRef },
- query: {
- sql: countQuerySql,
- iso_timestamp_start: latestRefresh,
- iso_timestamp_end: timestampEnd,
- },
- },
- signal,
- })
- if (error) {
- throw error
- }
- return data as unknown as Count
- },
- refetchOnWindowFocus: false,
- refetchInterval: 60000,
- enabled: !error && data && data?.pages?.length > 0 ? true : false,
- })
- const newCount = countData?.result?.[0]?.count ?? 0
- const chartQuery = useMemo(
- () => genChartQuery(table, params, mergedFilters),
- [table, params, mergedFilters]
- )
- const chartQueryKey = useMemo(
- () => [
- 'projects',
- projectRef,
- 'logs-chart',
- {
- projectRef,
- sql: chartQuery,
- iso_timestamp_start: timestampStart,
- iso_timestamp_end: timestampEnd,
- },
- ],
- [projectRef, chartQuery, timestampStart, timestampEnd]
- )
- 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,
- })
- const refresh = useCallback(async () => {
- setLatestRefresh(new Date().toISOString())
- refreshEventChart()
- refetch()
- }, [refetch, refreshEventChart])
- 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 {
- newCount,
- logData,
- isSuccess,
- isLoading: isLoading || isRefetching,
- isLoadingOlder: isFetchingNextPage,
- error: error || eventChartError,
- filters: mergedFilters,
- params,
- oldestTimestamp: oldestTimestamp ? String(oldestTimestamp) : undefined,
- eventChartData,
- refresh,
- loadOlder: () => fetchNextPage(),
- }
- }
- export default useLogsPreview
|