diff --git a/frontend/src/queries/nodes/DataNode/ElapsedTime.tsx b/frontend/src/queries/nodes/DataNode/ElapsedTime.tsx
index 3838c6c241006..f09ab068e5f14 100644
--- a/frontend/src/queries/nodes/DataNode/ElapsedTime.tsx
+++ b/frontend/src/queries/nodes/DataNode/ElapsedTime.tsx
@@ -5,18 +5,13 @@ import { Popover } from 'lib/lemon-ui/Popover'
import clsx from 'clsx'
import { QueryTiming } from '~/queries/schema'
-function ElapsedTimeWithTimings({
- elapsedTime,
- hasError,
- timings,
-}: {
- elapsedTime: number
- hasError: boolean
+export interface TimingsProps {
timings: QueryTiming[]
-}): JSX.Element | null {
- const [popoverVisible, setPopoverVisible] = useState(false)
+ elapsedTime: number
+}
- const overlay = (
+export function Timings({ timings, elapsedTime }: TimingsProps): JSX.Element | null {
+ return (
{timings.map(({ k: key, t: time }) => (
)
+}
+
+function ElapsedTimeWithTimings({
+ elapsedTime,
+ hasError,
+ timings,
+}: {
+ elapsedTime: number
+ hasError: boolean
+ timings: QueryTiming[]
+}): JSX.Element | null {
+ const [popoverVisible, setPopoverVisible] = useState(false)
return (
setPopoverVisible(false)}
visible={popoverVisible}
placement="bottom"
- overlay={overlay}
+ overlay={}
>
setPopoverVisible((visible) => !visible)}
diff --git a/frontend/src/scenes/appScenes.ts b/frontend/src/scenes/appScenes.ts
index 08e3d86ff793a..c72cdcf50a97f 100644
--- a/frontend/src/scenes/appScenes.ts
+++ b/frontend/src/scenes/appScenes.ts
@@ -73,7 +73,7 @@ export const appScenes: Record
any> = {
[Scene.Unsubscribe]: () => import('./Unsubscribe/Unsubscribe'),
[Scene.IntegrationsRedirect]: () => import('./IntegrationsRedirect/IntegrationsRedirect'),
[Scene.IngestionWarnings]: () => import('./data-management/ingestion-warnings/IngestionWarningsView'),
- [Scene.DebugQuery]: () => import('./query/QueryScene'),
+ [Scene.DebugQuery]: () => import('./debug/DebugScene'),
[Scene.VerifyEmail]: () => import('./authentication/signup/verify-email/VerifyEmail'),
[Scene.Feedback]: () => import('./feedback/Feedback'),
[Scene.Notebook]: () => import('./notebooks/NotebookScene'),
diff --git a/frontend/src/scenes/debug/DebugScene.tsx b/frontend/src/scenes/debug/DebugScene.tsx
new file mode 100644
index 0000000000000..c69aa492dd33f
--- /dev/null
+++ b/frontend/src/scenes/debug/DebugScene.tsx
@@ -0,0 +1,94 @@
+import { debugSceneLogic } from './debugSceneLogic'
+import { SceneExport } from 'scenes/sceneTypes'
+import { PageHeader } from 'lib/components/PageHeader'
+import { Query } from '~/queries/Query/Query'
+import { useActions, useValues } from 'kea'
+import { stringifiedExamples } from '~/queries/examples'
+import { LemonSelect } from 'lib/lemon-ui/LemonSelect'
+import { LemonLabel } from 'lib/lemon-ui/LemonLabel/LemonLabel'
+import { LemonButton } from 'lib/lemon-ui/LemonButton'
+import { HogQLQuery } from '~/queries/schema'
+import { HogQLDebug } from 'scenes/debug/HogQLDebug'
+
+export function DebugScene(): JSX.Element {
+ const { query } = useValues(debugSceneLogic)
+ const { setQuery } = useActions(debugSceneLogic)
+
+ let parsed: Record | undefined
+ try {
+ parsed = JSON.parse(query)
+ } catch (e) {
+ // do nothing
+ }
+
+ const showQueryEditor = !(
+ parsed &&
+ parsed.kind == 'DataTableNode' &&
+ parsed.source.kind == 'HogQLQuery' &&
+ (parsed.full || parsed.showHogQLEditor)
+ )
+
+ return (
+
+
+ setQuery(stringifiedExamples.HogQLRaw)}
+ >
+ HogQL Debug
+
+ setQuery(stringifiedExamples.HogQLTable)}
+ >
+ HogQL Table
+
+ setQuery(stringifiedExamples.Events)}
+ >
+ Any Query
+
+
+ k !== 'HogQLTable' && k !== 'HogQLRaw')
+ .map(([k, v]) => {
+ return { label: k, value: v }
+ })}
+ onChange={(v) => {
+ if (v) {
+ setQuery(v)
+ }
+ }}
+ />
+
+ >
+ }
+ />
+ {parsed && parsed?.kind === 'HogQLQuery' ? (
+ setQuery(JSON.stringify(query, null, 2))}
+ />
+ ) : (
+ setQuery(JSON.stringify(query, null, 2))}
+ context={{
+ showQueryEditor: showQueryEditor,
+ }}
+ />
+ )}
+
+ )
+}
+
+export const scene: SceneExport = {
+ component: DebugScene,
+ logic: debugSceneLogic,
+}
diff --git a/frontend/src/scenes/debug/HogQLDebug.tsx b/frontend/src/scenes/debug/HogQLDebug.tsx
new file mode 100644
index 0000000000000..62b495947c04f
--- /dev/null
+++ b/frontend/src/scenes/debug/HogQLDebug.tsx
@@ -0,0 +1,69 @@
+import { HogQLQueryEditor } from '~/queries/nodes/HogQLQuery/HogQLQueryEditor'
+import { DataNode, HogQLQuery } from '~/queries/schema'
+import { DateRange } from '~/queries/nodes/DataNode/DateRange'
+import { EventPropertyFilters } from '~/queries/nodes/EventsNode/EventPropertyFilters'
+import { BindLogic, useValues } from 'kea'
+import { dataNodeLogic, DataNodeLogicProps } from '~/queries/nodes/DataNode/dataNodeLogic'
+import { ElapsedTime, Timings } from '~/queries/nodes/DataNode/ElapsedTime'
+import { CodeSnippet, Language } from 'lib/components/CodeSnippet'
+import { CodeEditor } from 'lib/components/CodeEditors'
+
+interface HogQLDebugProps {
+ query: HogQLQuery
+ setQuery: (query: DataNode) => void
+}
+export function HogQLDebug({ query, setQuery }: HogQLDebugProps): JSX.Element {
+ const dataNodeLogicProps: DataNodeLogicProps = { query, key: 'debug-scene' }
+ const { dataLoading, response, responseErrorObject, elapsedTime } = useValues(dataNodeLogic(dataNodeLogicProps))
+ return (
+
+
+
+
+
+
+
+ {dataLoading ? (
+ <>
+
Running query...
+
+ Time elapsed:
+
+ >
+ ) : (
+ <>
+ {response?.hogql ? (
+ <>
+
Executed HogQL
+
+ {response.hogql}
+
+ >
+ ) : null}
+ {response?.clickhouse ? (
+ <>
+
Executed ClickHouse SQL
+
+ {response.clickhouse}
+
+ >
+ ) : null}
+ {response?.timings && elapsedTime !== null ? (
+ <>
+
Time spent
+
+ >
+ ) : null}
+
Raw response
+
+ >
+ )}
+
+
+ )
+}
diff --git a/frontend/src/scenes/query/querySceneLogic.ts b/frontend/src/scenes/debug/debugSceneLogic.ts
similarity index 75%
rename from frontend/src/scenes/query/querySceneLogic.ts
rename to frontend/src/scenes/debug/debugSceneLogic.ts
index c53fd3911ec91..aaf975c26ee85 100644
--- a/frontend/src/scenes/query/querySceneLogic.ts
+++ b/frontend/src/scenes/debug/debugSceneLogic.ts
@@ -1,14 +1,14 @@
import { actions, kea, path, reducers } from 'kea'
-import type { querySceneLogicType } from './querySceneLogicType'
+import type { debugSceneLogicType } from './debugSceneLogicType'
import { actionToUrl, urlToAction } from 'kea-router'
import { urls } from 'scenes/urls'
import { stringifiedExamples } from '~/queries/examples'
-const DEFAULT_QUERY: string = stringifiedExamples['Events']
+const DEFAULT_QUERY: string = stringifiedExamples['HogQLRaw']
-export const querySceneLogic = kea([
- path(['scenes', 'query', 'querySceneLogic']),
+export const debugSceneLogic = kea([
+ path(['scenes', 'query', 'debugSceneLogic']),
actions({
setQuery: (query: string) => ({ query: query }),
}),
diff --git a/frontend/src/scenes/query/QueryScene.tsx b/frontend/src/scenes/query/QueryScene.tsx
deleted file mode 100644
index d0cdf976cec05..0000000000000
--- a/frontend/src/scenes/query/QueryScene.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import { querySceneLogic } from './querySceneLogic'
-import { SceneExport } from 'scenes/sceneTypes'
-import { PageHeader } from 'lib/components/PageHeader'
-import { Query } from '~/queries/Query/Query'
-import { useActions, useValues } from 'kea'
-import { stringifiedExamples } from '~/queries/examples'
-import { LemonSelect } from 'lib/lemon-ui/LemonSelect'
-import { LemonLabel } from 'lib/lemon-ui/LemonLabel/LemonLabel'
-
-export function QueryScene(): JSX.Element {
- const { query } = useValues(querySceneLogic)
- const { setQuery } = useActions(querySceneLogic)
-
- let showEditor = true
- try {
- const parsed = JSON.parse(query)
- if (
- parsed &&
- parsed.kind == 'DataTableNode' &&
- parsed.source.kind == 'HogQLQuery' &&
- (parsed.full || parsed.showHogQLEditor)
- ) {
- showEditor = false
- }
- } catch (e) {
- // do nothing
- }
-
- return (
-
-
- Example queries:{' '}
- {
- return { label: k, value: v }
- })}
- onChange={(v) => {
- if (v) {
- setQuery(v)
- }
- }}
- />
-
- }
- />
-
- setQuery(JSON.stringify(query, null, 2))}
- context={{
- showQueryEditor: showEditor,
- }}
- />
-
- )
-}
-
-export const scene: SceneExport = {
- component: QueryScene,
- logic: querySceneLogic,
-}