You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(history): attribute each job to its target table; capture load jobs
Follow-up to `sqlmesh history` addressing how interwoven Python models,
hooks, and signals appear:
- Add a `Target` column showing the physical table each job wrote to
(from BigQuery's INFORMATION_SCHEMA.JOBS destination_table). This makes
interleaved Python/SQL model steps and pre/post-hook statements legible
instead of an anonymous stream of INSERT/CREATE. Anonymous SELECT result
tables are omitted.
- Label BigQuery load jobs (LoadJobConfig) with the correlation id, so
Python-model dataframe loads and seed loads appear as `LOAD` rows instead
of being invisible. Factored the label out into `_correlation_labels`,
shared by query and load jobs.
- Document that signals (Python readiness checks) and pure-Python model
logic run no SQL and don't appear; point to `check_intervals`.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/guides/history.md
+22-18Lines changed: 22 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ The `sqlmesh history` command does that correlation for you. Give it a plan id a
11
11
12
12
## How it works
13
13
14
-
Every query SQLMesh runs for a plan is tagged with that plan's correlation id — a BigQuery job label on the query job itself. `sqlmesh history` looks up the plan (either the one you specify or one you pick from a menu), then queries BigQuery's job history for every job carrying that label and renders the results chronologically.
14
+
Every job SQLMesh runs for a plan — both query jobs and the load jobs used to ingest Python-model dataframes and seeds —is tagged with that plan's correlation id as a BigQuery job label. `sqlmesh history` looks up the plan (either the one you specify or one you pick from a menu), then queries BigQuery's job history for every job carrying that label and renders the results chronologically.
15
15
16
16
Because it's driven by the query engine's job history rather than SQLMesh state, it only shows what actually executed against the warehouse. It's the fastest way to answer "did this step run, how long did it take, and if it failed, why?" without leaving your terminal.
17
17
@@ -55,28 +55,32 @@ You only need to type enough of the plan id to uniquely identify it — the
55
55
```bash linenums="1"
56
56
$ sqlmesh history 3f9a2c1e
57
57
58
-
History · plan 3f9a2c1e · 41 queries · 38 ✓ 2 ✗ 1 running
1 failed · re-run with `-o failures.sql` to export the SQL.
69
70
```
70
71
71
-
The header line summarizes the plan: the short plan id, total query count, and a breakdown of how many queries succeeded (`✓`), failed (`✗`), or are still running (`…`).
72
+
(In your terminal this is rendered as a bordered table.) The header line summarizes the plan: the short plan id, environment, total job count, and a breakdown of how many succeeded (`✓`), failed (`✗`), or are still running (`…`).
72
73
73
-
-**Time**— when the query started.
74
+
-**Time**— when the job started.
74
75
-**Status**—`✓` succeeded, `✗` failed, `…` still running.
75
-
-**Operation**— the leading SQL keyword (`CREATE TABLE`, `INSERT`, `MERGE`, `CREATE VIEW`, `ALTER TABLE`, etc.), so you can scan for the kind of work each query did without reading the full statement.
76
-
-**Duration**— wall-clock time the query took. Shown as `-` for queries that haven't finished.
76
+
-**Operation**— the leading SQL keyword (`CREATE TABLE`, `INSERT`, `MERGE`, `CREATE VIEW`, `ALTER TABLE`, `LOAD`, etc.), so you can scan the kind of work each job did without reading the full statement.
77
+
-**Target**— the physical table the job wrote to, so you can tell which model (and which step) each row belongs to. This is how you follow a Python model whose steps are interleaved with SQL models, or attribute a `LOAD`/`INSERT`/`MERGE` to the right table. Shown as `-` for jobs with no destination (for example a standalone audit `SELECT`).
78
+
-**Duration**— wall-clock time the job took. Shown as `-` for jobs that haven't finished.
A failed query is followed by an indented line with the error message BigQuery returned, so you can see why it failed without opening the warehouse UI.
81
+
A failed job is followed by an indented line with the error message BigQuery returned, so you can see why it failed without opening the warehouse UI.
82
+
83
+
Because the rows are ordered by execution time, the steps of a **Python model** (its physical `CREATE TABLE`, the `LOAD` of its dataframe, and the `INSERT`/`MERGE` that publishes it) slot chronologically in between the SQL models' steps, and **hooks**— model pre/post-statements and environment `before_all`/`after_all` statements — appear as their own rows in position. Use the **Target** column to tell them apart.
80
84
81
85
## Exporting the SQL
82
86
@@ -110,7 +114,7 @@ The file is one statement per entry, in execution order, so it can be read top t
110
114
```
111
115
112
116
- **Ingestion latency and retention.** BigQuery's job history views have some delay before a query appears and don't retain jobs forever, so a plan applied moments ago or a very old plan may show no rows.
113
-
- **Labeled query jobs only.** SQLMesh labels the query jobs it runs, but some operations — like loading a seed model's dataframe into BigQuery — use a load job rather than a labeled query job, so they won't appear in the history.
117
+
- **Signals and pure-Python logic aren't shown.** Signals are Python readiness checks that gate whether a model runs; they execute no SQL, so they don't appear as rows. Their effect shows up as an *absence* — a signal-blocked model simply has no `INSERT` for that interval. To inspect what a signal is holding back, use [`sqlmesh check_intervals`](../reference/cli.md#check_intervals), which reports pending intervals while respecting signals. Likewise, any purely in-memory work inside a Python model (API calls, dataframe transforms) runs no SQL and won't appear — only the jobs that touch the warehouse do.
0 commit comments