Skip to content

Latest commit

 

History

History
152 lines (120 loc) · 7.12 KB

File metadata and controls

152 lines (120 loc) · 7.12 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

DBSight is a database performance analyzer — Go API server with embedded background worker + React SPA. Single binary serves API, worker (goroutine), and static files. Supports PostgreSQL via pg_stat_statements, MySQL 5.7+/8.0+ via performance_schema, and MariaDB 10.x+ via performance_schema.

Monorepo Structure

pnpm workspaces monorepo: apps/web/ (React SPA) + apps/docs/ (Starlight docs site). Go module stays at root.

Commands

Build

make build                    # Build frontend then Go binary → bin/dbsight
go build -o bin/dbsight .     # Go only (requires apps/web/dist/ from prior pnpm build)
pnpm --filter web build       # Frontend only (tsc + vite)
pnpm --filter docs build      # Docs site only (Astro/Starlight)

Development

docker-compose up -d postgres  # Start local PostgreSQL
go run . migrate               # Run DB migrations
go run . serve                 # Start API server (port 42198) with embedded worker
pnpm --filter web dev          # Vite dev server with /api proxy to :42198
pnpm --filter docs dev         # Starlight docs dev server

Test & Lint

go test ./internal/...         # Go tests
go vet ./internal/...          # Go static analysis
pnpm --filter web lint         # Biome (lint + format check)
pnpm --filter web lint:fix     # Biome auto-fix
pnpm --filter web format       # Biome format only

Single test file

go test ./internal/crypto/ -v -run TestEncryptDecrypt

Architecture

Single binary (main.go at repo root) with cobra CLI:

  • dbsight serve — starts HTTP server + worker goroutine
  • dbsight migrate — runs embedded SQL migrations

//go:embed apps/web/dist in main.go embeds the React build into the binary. Must run pnpm --filter web build before go build.

Backend (Go)

main.go                          — Entry point, cobra CLI, runServer() wiring, embed directive
internal/config/                 — Config struct loaded from env vars
internal/models/                 — Domain types (Connection, SlowQuery, QueryDelta, etc.)
internal/store/store.go          — Store interface (connections, snapshots, index stats)
internal/store/postgres.go       — pgxpool implementation of Store
internal/store/migrate.go        — Embedded SQL migration runner
internal/adapter/adapter.go      — DBAnalyzer interface + factory (PostgreSQL, MySQL, MariaDB)
internal/adapter/postgres.go     — PostgreSQL adapter (Connect/Close)
internal/adapter/postgres_slow_queries.go — pg_stat_statements queries
internal/adapter/postgres_explain.go      — PostgreSQL EXPLAIN plan
internal/adapter/postgres_indexes.go      — PostgreSQL index stats from pg_stat_user_indexes
internal/adapter/postgres_stats.go        — PostgreSQL database-level stats
internal/adapter/mysql.go        — MySQL adapter (Connect/Close)
internal/adapter/mysql_slow_queries.go    — MySQL performance_schema queries
internal/adapter/mysql_explain.go         — MySQL EXPLAIN FORMAT=JSON
internal/adapter/mysql_indexes.go         — MySQL index stats from information_schema
internal/adapter/mysql_stats.go           — MySQL database-level stats (SHOW GLOBAL STATUS)
internal/adapter/mariadb.go      — MariaDB adapter (Connect/Close)
internal/adapter/mariadb_slow_queries.go  — MariaDB performance_schema queries
internal/adapter/mariadb_explain.go       — MariaDB EXPLAIN FORMAT=JSON
internal/adapter/mariadb_indexes.go       — MariaDB index stats with JSON_ARRAYAGG
internal/adapter/mariadb_stats.go         — MariaDB database-level stats
internal/adapter/mysqlcompat/    — Shared helpers for MySQL/MariaDB
internal/adapter/mysqlcompat/helpers.go   — DSN builder, EXPLAIN JSON parsing
internal/api/router.go           — Chi router, CORS, SPA fallback
internal/api/handlers/           — HTTP handlers (connection CRUD, queries, SSE, paste)
internal/worker/scheduler.go     — Ticker-based worker with concurrency limit (10)
internal/worker/collector.go     — Per-connection metrics collector
internal/crypto/encrypt.go       — AES-256-GCM encrypt/decrypt for DSN storage
migrations/                      — SQL files embedded via migrations/embed.go

Key patterns:

  • App struct in internal/api/app.go holds dependencies (Store, CryptoKey, NewAdapter factory)
  • All adapter code lives in internal/adapter/ package (flat, not subpackaged) to avoid import cycles
  • Migrations use //go:embed in migrations/embed.go, consumed by store.RunMigrations()
  • Worker starts as go worker.Run(ctx, ...) inside runServer()

Frontend (React + TypeScript)

apps/web/src/
  types/index.ts              — TS interfaces mirroring Go models
  api/client.ts               — Typed fetch wrapper for all API endpoints
  hooks/                      — use-connections, use-queries, use-sse
  components/layout/          — Sidebar + Layout shell
  components/connections/     — ConnectionForm, ConnectionList
  components/queries/         — SlowQueryTable (TanStack Table v8), QueryDetailDrawer, QuerySparkline
  components/ui/              — shadcn/ui components (DO NOT edit manually — use `npx shadcn@latest add`)
  pages/                      — Route pages (kebab-case filenames)
  App.tsx                     — React Router wiring

Key patterns:

  • @/ path alias configured in tsconfig + vite for imports
  • shadcn/ui + Tailwind CSS v4 for styling
  • Vite proxy: /apihttp://localhost:42198 in dev mode
  • SSE hook (use-sse.ts) with auto-reconnect for live query updates

API Endpoints

GET/POST       /api/connections
GET/PUT/DELETE /api/connections/{id}
POST           /api/connections/{id}/test
GET            /api/connections/{id}/queries          — Latest snapshot with deltas
GET            /api/connections/{id}/queries/stream    — SSE live updates
GET            /api/connections/{id}/queries/history   — Historical snapshots
POST           /api/paste/queries                      — Parse slow log text
/*             — SPA fallback (serves apps/web/dist/index.html)

Environment Variables

Variable Default Description
PORT 42198 HTTP server port
DATABASE_URL (required) PostgreSQL connection string for app metadata DB
ENCRYPTION_KEY (required) 64 hex chars (32 bytes) for AES-256-GCM DSN encryption
WORKER_INTERVAL_SECS 30 Background worker polling interval

Security Notes

  • DSN stored as AES-256-GCM ciphertext in connections.encrypted_dsn (BYTEA)
  • EncryptedDSN field has json:"-" tag — never serialized to API responses
  • EXPLAIN uses SET TRANSACTION READ ONLY to mitigate injection risk
  • All store queries use parameterized placeholders
  • Request body limits: 1MB for CRUD, 10MB for paste endpoint
  • No authentication in MVP — localhost-only tool