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
Copy file name to clipboardExpand all lines: TUTORIAL.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -103,7 +103,7 @@ Privileges:
103
103
dryrun init --db "$DATABASE_URL"
104
104
```
105
105
106
-
Creates `dryrun.toml`, the `.dryrun/` directory, and `.dryrun/schema.json`. Snapshot history lives in `~/.dryrun/history.db` (shared across projects, keyed by `(project_id, database_id)`).
106
+
Creates `dryrun.toml`, the `.dryrun/` directory, and `.dryrun/schema.json`. Snapshot history lives in `~/.dryrun/history.db` (shared across projects, keyed by `(project_id, database_id)`). If a `data-masking-policy.yml` resolves, `init` masks planner stats in-process before writing; for projects with PII, set `require_masks = true` in `dryrun.toml` to fail closed when the policy is missing. See [SECURITY.md](SECURITY.md).
107
107
108
108
### 3. Snapshots and diffing
109
109
@@ -151,15 +151,15 @@ All tools available including EXPLAIN ANALYZE (runs in rolled-back transactions,
151
151
152
152
For setups with one primary and N replicas serving different query patterns. Activity counters (`seq_scan`, `idx_scan`, `n_dead_tup`) differ per node and only live where the queries actually run, on the replicas. dryrun captures schema + planner stats from the primary and activity stats from each replica, then aggregates them.
153
153
154
-
In v0.6.0 a snapshot is split into three rows in `~/.dryrun/history.db`: `schema`, `planner_stats`, `activity_stats`. `snapshot take` writes the first two from the primary; `snapshot activity` writes one `activity_stats` row per replica, tagged with `--label`.
154
+
A snapshot is split into three rows in `~/.dryrun/history.db`: `schema`, `planner_stats`, `activity_stats`. `snapshot take` writes all three from the primary, with the activity row labeled `primary`. `snapshot activity` writes one additional `activity_stats` row per replica, tagged with `--label`. Planner stats are masked per `data-masking-policy.yml` at capture time; see [SECURITY.md](SECURITY.md).
155
155
156
-
### 1. Schema + planner stats from the primary
156
+
### 1. Schema + planner + activity from the primary
157
157
158
158
```sh
159
159
dryrun --profile primary snapshot take
160
160
```
161
161
162
-
Refuses to run on a standby. Writes `schema` (DDL) + `planner_stats` (`reltuples`, `relpages`, `pg_statistic`) to history.
162
+
Refuses to run on a standby. Writes `schema` (DDL), `planner_stats` (`reltuples`, `relpages`, `pg_statistic`; masked per policy), and one `activity_stats` row labeled `primary`.
163
163
164
164
### 2. Activity stats from each replica
165
165
@@ -293,6 +293,6 @@ GRANT pg_monitor TO your_readonly_user;
293
293
294
294
**"invalid schema JSON"** - The file must be a valid SchemaSnapshot. If you renamed fields or edited by hand, re-dump from the database.
295
295
296
-
**Multi-node stats not showing** - Run `dryrun snapshot list` and confirm you see both`schema`rows (from `snapshot take` on the primary) and `activity_stats`rows (from `snapshot activity --label ...` on each replica) sharing the same `schema_ref_hash`. Activity captured before any schema exists needs `--allow-orphan` and won't reattach automatically.
296
+
**Multi-node stats not showing** - Run `dryrun snapshot list` and confirm you see a`schema`row plus `activity_stats` rows for each node sharing the same `schema_ref_hash`. The primary contributes its own `activity_stats`row (labeled `primary`) via `snapshot take`; each replica contributes one via `snapshot activity --label ...`. Activity captured before any schema exists needs `--allow-orphan` and won't reattach automatically.
-**`planner_stats`**: what the planner uses (`reltuples`, `relpages`, `pg_statistic`).
12
+
-**`planner_stats`**: what the planner uses (`reltuples`, `relpages`, `pg_statistic`). Masked per `data-masking-policy.yml` at capture time; see [SECURITY.md](../SECURITY.md).
`snapshot take` writes `schema` + `planner_stats` from the primary. `snapshot activity` writes one `activity_stats` row per replica, tagged with a `--label`. Activity rows attach to the most recent matching schema by `schema_ref_hash`.
15
+
`snapshot take` writes all three rows from the primary, with the activity row labeled `primary`. `snapshot activity` writes one `activity_stats` row per replica, tagged with a `--label`. Activity rows attach to the most recent matching schema by `schema_ref_hash`.
16
16
17
17
```
18
18
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
@@ -22,7 +22,9 @@ A snapshot in v0.6.0 is split into three rows in `~/.dryrun/history.db`:
@@ -34,7 +36,7 @@ A snapshot in v0.6.0 is split into three rows in `~/.dryrun/history.db`:
34
36
dryrun --profile primary snapshot take
35
37
```
36
38
37
-
Refuses to run on a standby (`pg_is_in_recovery() = false` required). Writes one `schema` rowand one `planner_stats` row.
39
+
Refuses to run on a standby (`pg_is_in_recovery() = false` required). Writes one `schema` row, one `planner_stats` row (masked per policy), and one `activity_stats` row labeled `primary`.
38
40
39
41
### Activity stats from replicas
40
42
@@ -152,7 +154,7 @@ A connection pooler is supposed to round-robin across three replicas, but `compa
152
154
153
155
## Automating collection
154
156
155
-
Activity captures are lightweight and safe for cron. Take the primary snapshot first so activity rows have a `schema_ref_hash` to attach to:
157
+
Activity captures are lightweight and safe for cron. Take the primary snapshot first so replica activity rows have a `schema_ref_hash` to attach to:
156
158
157
159
```sh
158
160
# /etc/cron.d/dryrun-stats
@@ -162,16 +164,10 @@ Activity captures are lightweight and safe for cron. Take the primary snapshot f
`snapshot take` is idempotent on a quiet schema; repeated runs produce the same `schema_ref_hash`, so re-attaching activity rows is automatic. Run it nightly alongside activity captures, or only after migrations if you want fewer rows in history.
167
+
`snapshot take`already captures the primary's own activity row (labeled `primary`), so there is no separate `snapshot activity` line for the primary, and the command itself refuses to run on the primary. `snapshot take` is idempotent on a quiet schema: repeated runs produce the same `schema_ref_hash`, so re-attaching activity rows is automatic. Run it nightly alongside activity captures, or only after migrations if you want fewer rows in history.
166
168
167
169
## Snapshot storage
168
170
169
-
Snapshots live in `~/.dryrun/history.db`, keyed by `(project_id, database_id, kind, schema_ref_hash, node_label)`. Activity rows from `snapshot activity` carry their `--label` in `node_label`; rows from `snapshot take`use an empty label. `is_standby` is auto-detected from `pg_is_in_recovery()` and enforced by the CLI: `take` requires false, `activity` requires true.
171
+
Snapshots live in `~/.dryrun/history.db`, keyed by `(project_id, database_id, kind, schema_ref_hash, node_label)`. Activity rows from `snapshot activity` carry their `--label` in `node_label`; the activity row from `snapshot take`uses `primary`. `is_standby` is auto-detected from `pg_is_in_recovery()` and enforced by the CLI: `take` requires false, `activity` requires true.
170
172
171
-
To export a snapshot for sharing or archiving:
172
-
173
-
```sh
174
-
dryrun snapshot export
175
-
```
176
-
177
-
Writes `{project_id}/{database_id}/{timestamp}-{hash}.json.zst`. The zstd-compressed JSON contains the schema row plus all attached planner and activity rows.
173
+
To share a snapshot across machines, use `snapshot push` / `snapshot pull`. They move `history.db` byte-for-byte between stores without re-masking or re-transforming. See [SECURITY.md](../SECURITY.md) for the sharing trust model.
0 commit comments