Skip to content

Commit

Permalink
feat(hogql): better debug errors (#18522)
Browse files Browse the repository at this point in the history
  • Loading branch information
mariusandra authored Nov 9, 2023
1 parent bc55393 commit 7cf0229
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 20 deletions.
15 changes: 14 additions & 1 deletion frontend/src/queries/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1541,38 +1541,51 @@
"additionalProperties": false,
"properties": {
"clickhouse": {
"description": "Executed ClickHouse query",
"type": "string"
},
"columns": {
"description": "Returned columns",
"items": {},
"type": "array"
},
"error": {
"description": "Query error. Returned only if 'explain' is true. Throws an error otherwise.",
"type": "string"
},
"explain": {
"description": "Query explanation output",
"items": {
"type": "string"
},
"type": "array"
},
"hogql": {
"description": "Generated HogQL query",
"type": "string"
},
"modifiers": {
"$ref": "#/definitions/HogQLQueryModifiers"
"$ref": "#/definitions/HogQLQueryModifiers",
"description": "Modifiers used when performing the query"
},
"query": {
"description": "Input query string",
"type": "string"
},
"results": {
"description": "Query results",
"items": {},
"type": "array"
},
"timings": {
"description": "Measured timings for different parts of the query generation process",
"items": {
"$ref": "#/definitions/QueryTiming"
},
"type": "array"
},
"types": {
"description": "Types of returned columns",
"items": {},
"type": "array"
}
Expand Down
13 changes: 12 additions & 1 deletion frontend/src/queries/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,25 @@ export interface HogQLQueryModifiers {
}

export interface HogQLQueryResponse {
/** Input query string */
query?: string
/** Generated HogQL query */
hogql?: string
/** Executed ClickHouse query */
clickhouse?: string
/** Query results */
results?: any[]
types?: any[]
/** Query error. Returned only if 'explain' is true. Throws an error otherwise. */
error?: string
/** Returned columns */
columns?: any[]
/** Types of returned columns */
types?: any[]
/** Measured timings for different parts of the query generation process */
timings?: QueryTiming[]
/** Query explanation output */
explain?: string[]
/** Modifiers used when performing the query */
modifiers?: HogQLQueryModifiers
}

Expand Down
8 changes: 8 additions & 0 deletions frontend/src/scenes/debug/HogQLDebug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ export function HogQLDebug({ query, setQuery, queryKey }: HogQLDebugProps): JSX.
</>
) : (
<>
{response?.error ? (
<>
<h2 className="text-danger">Error Running Query!</h2>
<CodeSnippet language={Language.Text} wrap>
{response.error}
</CodeSnippet>
</>
) : null}
{response?.hogql ? (
<>
<h2>Executed HogQL</h2>
Expand Down
31 changes: 22 additions & 9 deletions posthog/hogql/query.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Dict, Optional, Union, cast

from posthog.clickhouse.client.connection import Workload
from posthog.errors import ExposedCHQueryError
from posthog.hogql import ast
from posthog.hogql.constants import HogQLGlobalSettings
from posthog.hogql.errors import HogQLException
Expand Down Expand Up @@ -143,16 +144,27 @@ def execute_hogql_query(
timings=timings_dict,
)

results, types = sync_execute(
clickhouse_sql,
clickhouse_context.values,
with_column_types=True,
workload=workload,
team_id=team.pk,
readonly=True,
)
error = None
try:
results, types = sync_execute(
clickhouse_sql,
clickhouse_context.values,
with_column_types=True,
workload=workload,
team_id=team.pk,
readonly=True,
)
except Exception as e:
if explain:
results, types = None, None
if isinstance(e, ExposedCHQueryError) or isinstance(e, HogQLException):
error = str(e)
else:
error = "Unknown error"
else:
raise e

if explain:
if explain and error is None: # If the query errored, explain will fail as well.
with timings.measure("explain"):
explain_results = sync_execute(
f"EXPLAIN {clickhouse_sql}",
Expand All @@ -170,6 +182,7 @@ def execute_hogql_query(
query=query,
hogql=hogql,
clickhouse=clickhouse_sql,
error=error,
timings=timings.to_list(),
results=results,
columns=print_columns,
Expand Down
1 change: 1 addition & 0 deletions posthog/hogql_queries/hogql_query_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def calculate(self) -> HogQLQueryResponse:
workload=Workload.ONLINE,
timings=self.timings,
in_export_context=self.in_export_context,
explain=bool(self.query.explain),
)

def _is_stale(self, cached_result_package):
Expand Down
25 changes: 16 additions & 9 deletions posthog/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -830,15 +830,22 @@ class HogQLQueryResponse(BaseModel):
model_config = ConfigDict(
extra="forbid",
)
clickhouse: Optional[str] = None
columns: Optional[List] = None
explain: Optional[List[str]] = None
hogql: Optional[str] = None
modifiers: Optional[HogQLQueryModifiers] = None
query: Optional[str] = None
results: Optional[List] = None
timings: Optional[List[QueryTiming]] = None
types: Optional[List] = None
clickhouse: Optional[str] = Field(default=None, description="Executed ClickHouse query")
columns: Optional[List] = Field(default=None, description="Returned columns")
error: Optional[str] = Field(
default=None, description="Query error. Returned only if 'explain' is true. Throws an error otherwise."
)
explain: Optional[List[str]] = Field(default=None, description="Query explanation output")
hogql: Optional[str] = Field(default=None, description="Generated HogQL query")
modifiers: Optional[HogQLQueryModifiers] = Field(
default=None, description="Modifiers used when performing the query"
)
query: Optional[str] = Field(default=None, description="Input query string")
results: Optional[List] = Field(default=None, description="Query results")
timings: Optional[List[QueryTiming]] = Field(
default=None, description="Measured timings for different parts of the query generation process"
)
types: Optional[List] = Field(default=None, description="Types of returned columns")


class LifecycleFilter(BaseModel):
Expand Down

0 comments on commit 7cf0229

Please sign in to comment.