Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,19 @@ Tested on **PostgreSQL 13 through 18** via CI on every commit. Older versions (9

Works with the `pg_monitor` role — superuser is not required for most reports (corruption checks need superuser or explicit `GRANT EXECUTE`).

## Snapshot Mode (for LLMs, scripts, automation)

Dump all safe reports as plain text — perfect for feeding to an LLM, saving to a file, or piping into other tools:

```bash
./snapshot.sh -h localhost -U postgres -d mydb # plain text output
./snapshot.sh -d mydb > snapshot.txt # save to file
./snapshot.sh -d mydb | pbcopy # clipboard (macOS)
./snapshot.sh --full -d mydb # include expensive reports
```

Skips interactive and expensive reports by default. Use `--full` to include everything except interactive prompts.

## Adding Custom Reports

Drop a `.sql` file in `sql/`. The filename format is `<id>_<name>.sql`. The first line must be a `--` comment with the description — it becomes the menu entry automatically.
Expand Down
12 changes: 12 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ Robustness:
- Version-conditional: uses appropriate function signatures for PG11–18
- GIN support via `gin_index_check()` on PostgreSQL 18+

### snapshot.sh — LLM-friendly output

New `snapshot.sh` script dumps all safe reports as clean plain text — no ANSI colors, no interactive prompts, no psql noise. Perfect for:
- Feeding database state to an LLM for analysis
- Automated health checks in scripts
- Saving periodic snapshots to files

```bash
./snapshot.sh -d mydb > snapshot.txt
./snapshot.sh --full -d mydb # include expensive reports too
```

### m1 — Buffer cache contents
What's in your `shared_buffers` right now. Shows cached size vs total size, % of cache used per object, and dirty buffer counts. Requires `pg_buffercache` extension.

Expand Down
104 changes: 104 additions & 0 deletions snapshot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env bash
#
# postgres_dba snapshot — dump all safe reports as plain text.
# Perfect for feeding to LLMs, saving to files, or piping to tools.
#
# Usage:
# ./snapshot.sh # uses default psql connection
# ./snapshot.sh -h localhost -U postgres -d mydb
# ./snapshot.sh "postgresql://user@host/db"
# ./snapshot.sh -d mydb | pbcopy # copy to clipboard (macOS)
# ./snapshot.sh -d mydb > snapshot.txt # save to file
#
# Skips:
# - Interactive reports (r1, r2 — require user input)
# - Expensive/slow reports (b3, b4, c2, c3, c4, m1 — heavy I/O)
# - Progress reports (p1 — only useful during operations)
#
# To include expensive reports, use --full.

set -euo pipefail
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone runs this in a checkout without sql/*.sql (or the glob doesn’t match), bash will iterate the literal pattern and the script will fail under set -e. Enabling nullglob avoids that surprise.

Suggested change
set -euo pipefail
set -euo pipefail
shopt -s nullglob


DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

FULL=false
PSQL_ARGS=()

for arg in "$@"; do
if [[ "$arg" == "--full" ]]; then
FULL=true
else
PSQL_ARGS+=("$arg")
fi
done

# Reports to skip in normal mode
SKIP_NORMAL="b3 b4 c2 c3 c4 m1 p1 r1 r2"

# Reports to skip even in full mode (interactive only)
SKIP_ALWAYS="r1 r2"

if $FULL; then
SKIP="$SKIP_ALWAYS"
else
SKIP="$SKIP_NORMAL"
fi

# Ensure non-interactive mode for t1
PSQLRC_TMP=$(mktemp)
trap "rm -f $PSQLRC_TMP" EXIT
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor quoting nit: since this runs in a trap, it’s safer to quote the tmp path to avoid word-splitting/globbing edge cases.

Suggested change
trap "rm -f $PSQLRC_TMP" EXIT
trap 'rm -f "$PSQLRC_TMP"' EXIT

cat > "$PSQLRC_TMP" <<'EOF'
\set postgres_dba_wide true
\set postgres_dba_interactive_mode false
\pset pager off
\pset footer off
EOF

echo "-- postgres_dba snapshot"
echo "-- Generated: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo "-- Connection: $(psql "${PSQL_ARGS[@]}" --no-psqlrc -tAc "select format('%s@%s:%s/%s (PostgreSQL %s)', current_user, inet_server_addr(), inet_server_port(), current_database(), version())" 2>/dev/null || echo 'unknown')"
echo "--"
echo ""

for f in "$DIR"/sql/*.sql; do
prefix=$(basename "$f" | sed 's/_.*$//')

# Check skip list
skip=false
for s in $SKIP; do
if [[ "$prefix" == "$s" ]]; then
skip=true
break
fi
done
$skip && continue

desc=$(head -n1 "$f" | sed 's/^--//')

echo "================================================================"
echo "== $prefix —$desc"
echo "================================================================"
echo ""

PAGER=cat psql "${PSQL_ARGS[@]}" \
--no-psqlrc \
-f "$DIR/warmup.psql" \
-f "$PSQLRC_TMP" \
-f "$f" \
2>&1 \
| sed 's/^psql:[^ ]* //' \
| sed 's/^NOTICE: //' \
| sed 's/^WARNING: /⚠️ /' \
| grep -v '^Pager ' \
| grep -v '^Null display' \
| grep -v '^Footer is off' \
| grep -v '^DO$' \
| grep -v '^SET$' \
| grep -v '^$' \
| head -500 || true

echo ""
echo ""
done

echo "-- End of snapshot"