useLogsQuery.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import { useQuery } from '@tanstack/react-query'
  2. import { IS_PLATFORM } from 'common'
  3. import { Dispatch, SetStateAction, useEffect, useState } from 'react'
  4. import {
  5. EXPLORER_DATEPICKER_HELPERS,
  6. getDefaultHelper,
  7. } from '@/components/interfaces/Settings/Logs/Logs.constants'
  8. import type {
  9. LogData,
  10. Logs,
  11. LogsEndpointParams,
  12. } from '@/components/interfaces/Settings/Logs/Logs.types'
  13. import {
  14. checkForILIKEClause,
  15. checkForWithClause,
  16. } from '@/components/interfaces/Settings/Logs/Logs.utils'
  17. import { get } from '@/data/fetchers'
  18. import { logsAllEndpointUrl } from '@/data/logs/logs-endpoint'
  19. import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
  20. import { DOCS_URL } from '@/lib/constants'
  21. export interface LogsQueryHook {
  22. params: LogsEndpointParams
  23. isLoading: boolean
  24. logData: LogData[]
  25. data?: never
  26. error: string | Object | null
  27. changeQuery: (newQuery?: string) => void
  28. runQuery: () => void
  29. setParams: Dispatch<SetStateAction<LogsEndpointParams>>
  30. enabled?: boolean
  31. }
  32. export const useLogsQuery = (
  33. projectRef: string,
  34. initialParams: Partial<LogsEndpointParams> = {},
  35. enabled = true,
  36. options: { useOtel?: boolean } = {}
  37. ): LogsQueryHook => {
  38. const { useOtel = false } = options
  39. const defaultHelper = getDefaultHelper(EXPLORER_DATEPICKER_HELPERS)
  40. const [params, setParams] = useState<LogsEndpointParams>({
  41. sql: initialParams?.sql || '',
  42. iso_timestamp_start: initialParams.iso_timestamp_start
  43. ? initialParams.iso_timestamp_start
  44. : defaultHelper.calcFrom(),
  45. iso_timestamp_end: initialParams.iso_timestamp_end
  46. ? initialParams.iso_timestamp_end
  47. : defaultHelper.calcTo(),
  48. })
  49. const { logsMetadata } = useIsFeatureEnabled(['logs:metadata'])
  50. useEffect(() => {
  51. setParams((prev) => ({
  52. ...prev,
  53. ...initialParams,
  54. sql: initialParams?.sql ?? prev.sql,
  55. iso_timestamp_start: initialParams.iso_timestamp_start ?? prev.iso_timestamp_start,
  56. iso_timestamp_end: initialParams.iso_timestamp_end ?? prev.iso_timestamp_end,
  57. }))
  58. }, [initialParams.sql, initialParams.iso_timestamp_start, initialParams.iso_timestamp_end])
  59. const _enabled = enabled && typeof projectRef !== 'undefined' && Boolean(params.sql)
  60. const usesWith = checkForWithClause(params.sql || '')
  61. const usesILIKE = checkForILIKEClause(params.sql || '')
  62. const {
  63. data,
  64. error: rqError,
  65. isPending: isLoading,
  66. isRefetching,
  67. refetch,
  68. } = useQuery({
  69. queryKey: ['projects', projectRef, 'logs', params, { otel: useOtel }],
  70. queryFn: async ({ signal }) => {
  71. const { data, error } = await get(logsAllEndpointUrl(useOtel), {
  72. params: {
  73. path: { ref: projectRef },
  74. query: params,
  75. },
  76. signal,
  77. })
  78. if (error) {
  79. throw error
  80. }
  81. return data as unknown as Logs
  82. },
  83. enabled: _enabled,
  84. refetchOnWindowFocus: false,
  85. })
  86. let error: null | string | object = rqError ? (rqError as any).message : null
  87. if (!error && data?.error) {
  88. error = data?.error
  89. }
  90. // BigQuery-specific parser limitations don't apply to the ClickHouse-backed
  91. // OTEL endpoint, so skip these warnings when querying it.
  92. if (IS_PLATFORM && !useOtel) {
  93. if (usesWith) {
  94. error = {
  95. message: 'The parser does not yet support WITH and subquery statements.',
  96. docs: `${DOCS_URL}/guides/platform/advanced-log-filtering#the-with-keyword-and-subqueries-are-not-supported`,
  97. }
  98. }
  99. if (usesILIKE) {
  100. error = {
  101. message: 'BigQuery does not support ILIKE. Use REGEXP_CONTAINS instead.',
  102. docs: `${DOCS_URL}/guides/platform/advanced-log-filtering#the-ilike-and-similar-to-keywords-are-not-supported`,
  103. }
  104. }
  105. }
  106. const changeQuery = (newQuery = '') => {
  107. setParams((prev) => ({ ...prev, sql: newQuery }))
  108. }
  109. const logData = (data?.result ?? []).map((x) => {
  110. if (logsMetadata) {
  111. return x
  112. } else {
  113. const { metadata, ...log } = x
  114. return log
  115. }
  116. })
  117. return {
  118. params,
  119. isLoading: (_enabled && isLoading) || isRefetching,
  120. logData: logData,
  121. error,
  122. changeQuery,
  123. runQuery: () => refetch(),
  124. setParams,
  125. }
  126. }
  127. export default useLogsQuery