dashboard

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

Package dashboard serves a local, self-hosted web view of a Litescope fleet.

It is intentionally dependency-free: the frontend is a single embedded HTML file (no build step, no node_modules) and the server is the Go standard library. It runs on the operator's own machine or server — no cloud, no outbound telemetry. The hosted, multi-user, org-scoped dashboard is a separate Enterprise offering; this one is free.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AutopilotAction

type AutopilotAction struct {
	Kind   string `json:"kind"` // analyze | optimize | vacuum | create-index | drop-index
	Risk   string `json:"risk"` // safe | risky
	Table  string `json:"table,omitempty"`
	SQL    string `json:"sql,omitempty"` // the statement autopilot would run (empty = guidance only)
	Reason string `json:"reason"`        // plain-language explanation
}

AutopilotAction is one optimization step autopilot would take (mirrors autopilot.Action). Risk is "safe" (auto-applied) or "risky" (needs review).

type AutopilotFn

type AutopilotFn func(dbName string) (*AutopilotPlan, error)

AutopilotFn builds the autopilot plan for the named database. The CLI supplies it so this package stays decoupled from DSN resolution; when nil, the panel hides.

type AutopilotPlan

type AutopilotPlan struct {
	Source  string            `json:"source"`
	Actions []AutopilotAction `json:"actions"`
	Safe    int               `json:"safe"`    // count of safe (auto-applied) actions
	Risky   int               `json:"risky"`   // count of risky (review-first) actions
	Queries int               `json:"queries"` // observed queries fed to the advisor
}

AutopilotPlan is the DBA self-driving moat's verdict for one database: the set of maintenance and indexing actions it would take, surfaced read-only so the operator can see the plan before applying it from the CLI. Queries records how many observed SQL console queries fed the EXPLAIN-based index advice.

type BackupReport

type BackupReport struct {
	Source    string         `json:"source"`
	Snapshots []SnapshotInfo `json:"snapshots"`
}

BackupReport is the snapshot history for one database — the file-superpower moat (point-in-time backups) surfaced in the dashboard.

type BrowseFn

type BrowseFn func(dbName, table, orderBy, dir string, limit, offset int) (*BrowseResult, error)

BrowseFn returns one paginated, optionally sorted page of a table. The CLI supplies it; it validates the table and sort column to prevent injection.

type BrowseResult

type BrowseResult struct {
	Columns []string `json:"columns"`
	Rows    [][]any  `json:"rows"`
	Total   int64    `json:"total"`
	Offset  int      `json:"offset"`
	Limit   int      `json:"limit"`
	OrderBy string   `json:"order_by,omitempty"`
	Dir     string   `json:"dir,omitempty"`
}

BrowseResult is one page of a table, with server-side sorting and the total row count so the dashboard can paginate.

type ContentionWindow added in v0.8.0

type ContentionWindow struct {
	StartTS    int64    `json:"start_ts"`     // unix ms of the first locked event
	EndTS      int64    `json:"end_ts"`       // unix ms of the last locked event in the run
	DurationMS int64    `json:"duration_ms"`  // EndTS - StartTS
	Events     int      `json:"events"`       // locked observations in the window
	PeakWaitMS int64    `json:"peak_wait_ms"` // worst BEGIN IMMEDIATE wait in the window
	Holders    []string `json:"holders,omitempty"`
}

ContentionWindow is a maximal contiguous run of "locked" observations — a period during which some writer held the lock and others would have seen SQLITE_BUSY. It answers "when, and for how long, was this database jammed?"

type CreateSnapshotFn

type CreateSnapshotFn func(dbName, label string) (*SnapshotInfo, error)

CreateSnapshotFn takes a new snapshot of the named database with an optional label and returns the created snapshot.

type DiffColumnChange

type DiffColumnChange struct {
	Name    string `json:"name"`
	OldType string `json:"old_type,omitempty"`
	NewType string `json:"new_type,omitempty"`
}

DiffColumnChange records a column whose definition changed between two databases.

type DiffData

type DiffData struct {
	Table   string `json:"table"`
	Added   int64  `json:"added"`
	Removed int64  `json:"removed"`
	Changed int64  `json:"changed"`
}

DiffData is the row-count delta for one table between the two databases.

type DiffFn

type DiffFn func(oldDB, newDB string) (*DiffResult, error)

DiffFn compares two databases by fleet name (old → new) and returns the curated diff. The CLI supplies it so this package stays decoupled from DSN resolution and the diff engine; when nil, the diff panel is disabled.

type DiffResult

type DiffResult struct {
	Old         string      `json:"old"`
	New         string      `json:"new"`
	Schema      []DiffTable `json:"schema"`
	Data        []DiffData  `json:"data"`
	Identical   bool        `json:"identical"`
	DataSkipped bool        `json:"data_skipped"` // true for remote sources (schema-only)
}

DiffResult is the full comparison rendered in the dashboard's diff panel — "see what changes before you apply it".

type DiffTable

type DiffTable struct {
	Name           string             `json:"name"`
	Status         string             `json:"status"`
	AddedColumns   []string           `json:"added_columns,omitempty"`
	RemovedColumns []string           `json:"removed_columns,omitempty"`
	ChangedColumns []DiffColumnChange `json:"changed_columns,omitempty"`
	AddedIndexes   []string           `json:"added_indexes,omitempty"`
	RemovedIndexes []string           `json:"removed_indexes,omitempty"`
}

DiffTable is one table's worth of schema change between the old and new database. Status is "added", "removed", or "changed".

type FleetLockEntry added in v0.8.0

type FleetLockEntry struct {
	Name   string
	Source string
	Events []LockEvent
}

FleetLockEntry pairs a fleet member's display name and source DSN with its raw lock event stream (oldest first, as returned by LockSeries).

type FleetLockReport added in v0.8.0

type FleetLockReport struct {
	SinceMS   int64              `json:"since_ms"`
	Databases []FleetLockSummary `json:"databases"`
	CheckedAt time.Time          `json:"checked_at"`
}

FleetLockReport aggregates per-database contention across the fleet, sorted worst-first (critical → warning → ok).

func BuildFleetLockReport added in v0.8.0

func BuildFleetLockReport(sinceMs int64, entries []FleetLockEntry) *FleetLockReport

BuildFleetLockReport reduces each member's raw lock stream to a contention summary and sorts the fleet worst-first. Pure function so it can be unit-tested without a store.

func (*FleetLockReport) Counts added in v0.8.0

func (r *FleetLockReport) Counts() (ok, warning, critical int)

Counts tallies databases by contention severity.

func (*FleetLockReport) HasContention added in v0.8.0

func (r *FleetLockReport) HasContention() bool

HasContention reports whether any database saw lock contention in the window.

type FleetLockSummary added in v0.8.0

type FleetLockSummary struct {
	Name            string       `json:"name"`
	Source          string       `json:"source"`
	Severity        string       `json:"severity"` // ok | warning | critical
	Events          int          `json:"events"`
	LockedEvents    int          `json:"locked_events"`
	Windows         int          `json:"windows"`
	LongestWindowMS int64        `json:"longest_window_ms"`
	MaxWaitMS       int64        `json:"max_wait_ms"`
	P95WaitMS       int64        `json:"p95_wait_ms"`
	LastContention  int64        `json:"last_contention_ts,omitempty"` // unix ms of the most recent jam
	WALLastBytes    int64        `json:"wal_last_bytes"`
	WALPeakBytes    int64        `json:"wal_peak_bytes"`
	WALBloated      bool         `json:"wal_bloated"`
	TopHolders      []HolderStat `json:"top_holders,omitempty"`
}

FleetLockSummary is one database's contention rollup — the fleet lock doctor's per-member row. It answers, for the whole fleet at a glance, "which databases are jammed, how badly, and who is holding them?"

type FleetSource added in v0.8.0

type FleetSource struct {
	Name   string
	Source string
}

FleetSource identifies one fleet member for the lock rollup: a display name and the source key its lock events were recorded under (the DSN).

type History

type History struct {
	// contains filtered or unexported fields
}

History persists fleet-health snapshots to a local SQLite file. The store is itself a SQLite database — the monitoring history of a SQLite tool lives in a SQLite file, no external time-series infrastructure required. It is safe for concurrent use.

func OpenHistory

func OpenHistory(path string) (*History, error)

OpenHistory opens (creating if needed) the SQLite history store at path.

func (*History) Close

func (h *History) Close() error

Close releases the underlying database.

func (*History) FleetLockReport added in v0.8.0

func (h *History) FleetLockReport(sources []FleetSource, sinceMs int64) (*FleetLockReport, error)

FleetLockReport reads each source's recorded lock series from the store and aggregates them into a fleet-wide contention report, worst-first. A member with no recorded events still appears (as ok), so the fleet roster is complete.

func (*History) LockSeries added in v0.8.0

func (h *History) LockSeries(source string, sinceMs int64) ([]LockEvent, error)

LockSeries returns lock events for source with ts >= sinceMs (0 for all), oldest first.

func (*History) Record

func (h *History) Record(ov *Overview) error

Record stores a snapshot derived from the overview. It is best-effort and rate-limited by minSampleGap; callers may ignore the returned error.

func (*History) RecordLockEvent added in v0.8.0

func (h *History) RecordLockEvent(source, state string, waitMS, walBytes int64, holders []LockHolderInfo, detail string) error

RecordLockEvent stores one lock observation for source, rate-limited per source by minLockEventGap. Free/steady-state events are also recorded (at the coarser rate) so the timeline shows recovery, not just contention.

func (*History) Series

func (h *History) Series(sinceMs int64) ([]Sample, error)

Series returns samples with ts >= sinceMs (0 for all), oldest first.

type HolderStat added in v0.8.0

type HolderStat struct {
	Command string `json:"command"`
	Events  int    `json:"events"`
}

HolderStat counts how often a process was seen holding the lock during contended observations, ranking the biggest offenders.

type ImportFn

type ImportFn func(filename string, data io.Reader) (summary string, err error)

ImportFn ingests an uploaded data file (CSV/TSV/JSON) and returns a short human summary (e.g. the new table name). The CLI supplies it so this package stays decoupled from the importer; when nil, drag-drop import is disabled.

type LockEvent added in v0.8.0

type LockEvent struct {
	TS       int64            `json:"ts"` // unix milliseconds
	Source   string           `json:"source"`
	State    string           `json:"state"` // "locked" | "readable" | "free" | "error"
	WaitMS   int64            `json:"wait_ms"`
	WALBytes int64            `json:"wal_bytes"` // WAL file size at observation time (0 if none/remote)
	Holders  []LockHolderInfo `json:"holders,omitempty"`
	Detail   string           `json:"detail,omitempty"`
}

LockEvent is one point-in-time observation of a database's lock state — either an event-driven capture (a real SQLITE_BUSY hit during a litescope operation) or a `locks --watch` poll. Source of truth for the lock doctor's per-database contention timeline.

type LockFinding

type LockFinding struct {
	Severity string `json:"severity"` // "ok" | "warning" | "critical"
	Rule     string `json:"rule"`
	Summary  string `json:"summary"`
	Detail   string `json:"detail"`
	Fix      string `json:"fix"`
}

LockFinding is one static lock-configuration issue (mirrors locks.Finding).

type LockHolder

type LockHolder struct {
	PID     int    `json:"pid"`
	Command string `json:"command"`
	Access  string `json:"access"`
}

LockHolder is a process holding the database file open (mirrors locks.Holder).

type LockHolderInfo added in v0.8.0

type LockHolderInfo struct {
	PID     int    `json:"pid"`
	Command string `json:"command"`
}

LockHolderInfo is a process holding a database file open, recorded alongside a lock event (mirrors locks.Holder, kept local to avoid an import cycle).

type LockReport

type LockReport struct {
	Source     string            `json:"source"`
	Provider   string            `json:"provider"` // "local" | "d1" | "turso"
	Verdict    string            `json:"verdict"`  // "ok" | "attention" | "critical"
	Pragmas    map[string]string `json:"pragmas,omitempty"`
	WALBytes   int64             `json:"wal_bytes"`
	Findings   []LockFinding     `json:"findings"`
	LiveState  string            `json:"live_state,omitempty"` // "free" | "locked" | "readable" | "error"
	LiveDetail string            `json:"live_detail,omitempty"`
	WaitMS     int64             `json:"wait_ms,omitempty"`
	Holders    []LockHolder      `json:"holders,omitempty"`
	Hint       string            `json:"hint,omitempty"`
}

LockReport is the lock doctor's verdict for one database — static PRAGMA diagnosis plus, for local files, a live probe of who holds the lock right now.

type LockTimeline added in v0.8.0

type LockTimeline struct {
	Source       string             `json:"source"`
	SinceMS      int64              `json:"since_ms"`
	Events       int                `json:"events"`
	FirstTS      int64              `json:"first_ts,omitempty"`
	LastTS       int64              `json:"last_ts,omitempty"`
	LockedEvents int                `json:"locked_events"`
	ErrorEvents  int                `json:"error_events"`
	MaxWaitMS    int64              `json:"max_wait_ms"`
	P95WaitMS    int64              `json:"p95_wait_ms"`
	Windows      []ContentionWindow `json:"windows,omitempty"`
	TopHolders   []HolderStat       `json:"top_holders,omitempty"`
	WALPeakBytes int64              `json:"wal_peak_bytes"`
	WALLastBytes int64              `json:"wal_last_bytes"`
	WALBloated   bool               `json:"wal_bloated"` // WAL ever crossed the bloat threshold
}

LockTimeline is the aggregated per-database contention time-series — the lock doctor's drill-down view. It turns a raw stream of lock observations into the three questions an operator actually asks: how often is it jammed, who jams it, and is the WAL checkpoint keeping up.

func BuildLockTimeline added in v0.8.0

func BuildLockTimeline(source string, sinceMs int64, events []LockEvent) LockTimeline

BuildLockTimeline aggregates a source's lock events (oldest first, as returned by LockSeries) into a contention timeline. It is a pure function so it can be unit-tested without a store.

type LocksFn

type LocksFn func(dbName string) (*LockReport, error)

LocksFn diagnoses lock health for the named database. The CLI supplies it so this package stays decoupled from DSN resolution; when nil, the panel hides.

type Overview

type Overview struct {
	FleetName   string                   `json:"fleet_name"`
	Total       int                      `json:"total"`
	Preview     bool                     `json:"preview"`     // true when a Free preview cap is in effect
	PreviewCap  int                      `json:"preview_cap"` // databases shown under the cap
	FullTotal   int                      `json:"full_total"`  // databases the fleet actually contains
	Health      *fleet.HealthReport      `json:"health"`
	Fingerprint *fleet.FingerprintReport `json:"fingerprint"`
	GeneratedAt time.Time                `json:"generated_at"`
}

Overview is the payload the dashboard renders. It is recomputed on each request so the browser always reflects the current state of the fleet.

type Provider

type Provider func() (*Overview, error)

Provider computes a fresh Overview. The CLI supplies this so the dashboard package stays decoupled from license gating and config loading.

type QueryFn

type QueryFn func(dbName, sql string) (*QueryResult, error)

QueryFn runs a read-only SQL query against the named database. Read-only safety is enforced by the CLI at the engine level (mode=ro + query_only).

type QueryResult

type QueryResult struct {
	Columns    []string `json:"columns"`
	Rows       [][]any  `json:"rows"`
	Truncated  bool     `json:"truncated"`
	DurationMs int64    `json:"duration_ms"`
}

QueryResult is the outcome of a read-only SQL query against one database.

type RestoreSnapshotFn

type RestoreSnapshotFn func(dbName, snapshotPath string) error

RestoreSnapshotFn overwrites the named database with one of its snapshots (identified by path). A safety snapshot of the current state is taken first.

type RewindFn

type RewindFn func(dbName, to string) (*RewindResult, error)

RewindFn restores the named database to the given point in time (RFC 3339 or a human form like "2h ago"). Destructive — the CLI supplies it only for D1 sources, which is why it lives alongside TimeTravelFn rather than the local backup panel's RestoreSnapshotFn.

type RewindResult

type RewindResult struct {
	Bookmark  string `json:"bookmark"`
	Timestamp string `json:"timestamp"`
}

RewindResult is the outcome of a Time Travel restore (mirrors connector.D1TimeTravelResult, kept local so this package stays decoupled from the D1 connector).

type Sample

type Sample struct {
	TS        int64 `json:"ts"` // unix milliseconds
	Total     int   `json:"total"`
	OK        int   `json:"ok"`
	Warning   int   `json:"warning"`
	Critical  int   `json:"critical"`
	SizeBytes int64 `json:"size_bytes"`
}

Sample is one point on the fleet's health timeline.

type SchemaColumn

type SchemaColumn struct {
	Name  string `json:"name"`
	Type  string `json:"type"`
	PK    bool   `json:"pk"`
	FK    bool   `json:"fk"`
	Drift string `json:"drift,omitempty"`
}

SchemaColumn is one column in an ERD table node. Drift, when set, marks how the column deviates from the fleet's canonical schema: "added" (present here, absent in canonical), "changed" (type/not-null differs), or "missing" (present in canonical, absent here).

type SchemaEdge

type SchemaEdge struct {
	From   string `json:"from"`   // table holding the foreign key
	To     string `json:"to"`     // referenced table
	Column string `json:"column"` // column in From that references To
}

SchemaEdge is a foreign-key relationship between two tables.

type SchemaFingerprint

type SchemaFingerprint struct {
	ClusterID    string `json:"cluster_id"`
	IsCanonical  bool   `json:"is_canonical"`
	CanonicalID  string `json:"canonical_id"`
	ClusterCount int    `json:"cluster_count"` // databases sharing this exact schema
	FleetTotal   int    `json:"fleet_total"`   // databases fingerprinted
	DriftTables  int    `json:"drift_tables"`  // tables differing from canonical
	DriftColumns int    `json:"drift_columns"` // columns differing from canonical
}

SchemaFingerprint places one database's ERD in the context of the whole fleet: which schema cluster it belongs to and how far it has drifted from canonical.

type SchemaFn

type SchemaFn func(dbName string) (*SchemaGraph, error)

SchemaFn returns the ERD graph of the named database. The CLI supplies it so this package stays decoupled from schema loading; when nil, the ERD is disabled.

type SchemaGraph

type SchemaGraph struct {
	Tables      []SchemaTable      `json:"tables"`
	Edges       []SchemaEdge       `json:"edges"`
	Fingerprint *SchemaFingerprint `json:"fingerprint,omitempty"` // fleet drift overlay
}

SchemaGraph is the entity-relationship graph of one database, rendered as an interactive ERD in the dashboard.

type SchemaTable

type SchemaTable struct {
	Name    string         `json:"name"`
	Columns []SchemaColumn `json:"columns"`
	Drift   string         `json:"drift,omitempty"`
	Ghost   bool           `json:"ghost,omitempty"`
}

SchemaTable is one entity (table) in the ERD. Drift "added" marks a table present here but absent from canonical; Ghost marks a table present in canonical but missing here (rendered as a placeholder).

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server serves the embedded dashboard and its JSON API.

func New

func New(provider Provider) *Server

New builds a dashboard server backed by the given provider.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns the HTTP handler (useful for tests and custom hosting).

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(addr string) error

ListenAndServe starts the dashboard on addr (e.g. "127.0.0.1:7575").

func (*Server) SetAutopilot

func (s *Server) SetAutopilot(fn AutopilotFn)

SetAutopilot enables the DBA autopilot panel (read-only plan preview).

func (*Server) SetBackup

func (s *Server) SetBackup(list SnapshotsFn, create CreateSnapshotFn, restore RestoreSnapshotFn)

SetBackup enables the snapshot/restore (backup) panel. list is required; create and restore enable the respective actions when non-nil.

func (*Server) SetDataBrowser

func (s *Server) SetDataBrowser(tables TablesFn, query QueryFn)

SetDataBrowser enables the read-only data browser and SQL console.

func (*Server) SetDiffProvider

func (s *Server) SetDiffProvider(fn DiffFn)

SetDiffProvider enables the visual schema/data diff panel.

func (*Server) SetHistory

func (s *Server) SetHistory(h *History)

SetHistory enables the fleet-health timeline, persisting a snapshot on each overview request to the given store.

func (*Server) SetImportHandler

func (s *Server) SetImportHandler(fn ImportFn)

SetImportHandler enables drag-drop import in the dashboard.

func (*Server) SetLockDoctor

func (s *Server) SetLockDoctor(fn LocksFn)

SetLockDoctor enables the lock doctor panel.

func (*Server) SetSchemaProvider

func (s *Server) SetSchemaProvider(fn SchemaFn)

SetSchemaProvider enables the interactive ERD.

func (*Server) SetTableBrowser

func (s *Server) SetTableBrowser(fn BrowseFn)

SetTableBrowser enables paginated, sortable table browsing.

func (*Server) SetTimeTravel

func (s *Server) SetTimeTravel(info TimeTravelFn, rewind RewindFn)

SetTimeTravel enables the D1 Time Travel panel (window info + restore). info is required; rewind enables the restore action when non-nil.

type SnapshotInfo

type SnapshotInfo struct {
	Path      string    `json:"path"`
	Label     string    `json:"label,omitempty"`
	CreatedAt time.Time `json:"created_at"`
	SizeBytes int64     `json:"size_bytes"`
}

SnapshotInfo is one stored point-in-time backup (mirrors snapshot.Snapshot).

type SnapshotsFn

type SnapshotsFn func(dbName string) (*BackupReport, error)

SnapshotsFn lists the snapshots of the named database. The CLI supplies it so this package stays decoupled from DSN resolution; when nil, the panel hides.

type TableInfo

type TableInfo struct {
	Name string `json:"name"`
	Rows int64  `json:"rows"`
}

TableInfo describes one table available for browsing in a database.

type TablesFn

type TablesFn func(dbName string) ([]TableInfo, error)

TablesFn lists the browsable tables of the named database. The CLI supplies it so this package stays decoupled from DSN resolution; when nil, the data browser is disabled.

type TimeTravelFn

type TimeTravelFn func(dbName string) (*TimeTravelInfo, error)

TimeTravelFn reports the Time Travel window for the named database. The CLI supplies it and rejects non-D1 sources; when nil, the panel hides.

type TimeTravelInfo

type TimeTravelInfo struct {
	Source string    `json:"source"`
	Oldest time.Time `json:"oldest"`
	Now    time.Time `json:"now"`
}

TimeTravelInfo describes the Cloudflare D1 Time Travel window for one database — the file-superpower moat's D1-native counterpart to local snapshots (D1 keeps 30 days of continuous history, no local backup needed).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL