Files
Dash/README.md
T
arsam 009652ce3e Import documentation: README.md
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:20:34 +03:30

6.4 KiB
Raw Blame History

Dash — uptime observatory

A self-hosted uptime monitoring dashboard in a single binary. A Go check engine with SQLite persistence streams live status over SSE into a hand-built React frontend: three bespoke SVG circular visualizations with spring physics, full RTL (Farsi) support, and a shareable public status mode.

Dash

What it does

  • Five check types — HTTP (status + latency), TCP port, TLS certificate expiry (days remaining), ICMP ping, and Docker (container running + healthcheck status via the daemon socket). Each target runs on its own interval.
  • Flap detection — N consecutive failures before a target is marked down, M consecutive successes before it recovers. No alert noise from a single dropped packet.
  • Incident grouping — one incident spans the entire down period, from the first failed check of the streak until recovery.
  • Live stream — /api/stream pushes every probe and every confirmed state transition over Server-Sent Events. The UI never polls.
  • Every result persisted — timestamp, latency, status, error string in SQLite (pure Go driver, no CGO), pruned after history_days.

The frontend

Three circular instruments, all hand-built SVG + Framer Motion (no charting libraries):

  1. Status rings — one per target. The outer arc fills to the uptime percentage over the selected window (24H/7D) and springs to every new value; the inner brass gauge encodes latency on a log scale (1ms–2.5s); each completed probe lands as a visible pulse; confirmed state changes ripple outward. Click a ring and it travels into a detail view (shared layout transition) with a latency sparkline, a per-target day dial, and recent incidents.
  2. Orbital overview — every target orbits the system core at Kepler-flavored speeds (inner orbits run faster). Healthy bodies drift calmly with motion trails, degraded ones breathe, a down body breaks its orbit outward and flares red over the scar of its old path. The core carries fleet-wide uptime and a brass scanner hand.
  3. Day dial — a 24-hour clock face. Each of the last 24 hours is one segment at its true wall-clock position, colored by status. Hours without data stay hairline-thin. A brass hand marks now. One glance, one full day.

Plus: a boot sequence where the instruments draw themselves in, staggered; prefers-reduced-motion collapses all motion to fully-formed static rendering; فارسی / RTL is a first-class layout mode (mirrored layout, Vazirmatn type, Persian digits and the Persian solar calendar via fa-IR); dark and light themes (persisted, both tuned variants of the same brass / ink design language); and a Status mode — the same instruments stripped to a clean, shareable public status page.

Continuous motion (the orbital field, the scanner hand) runs outside React entirely — one animation-frame loop mutates SVG attributes directly, so the page stays at full frame rate regardless of target count. No SVG filters, no blend modes on hot layers.

Build

Requires Go ≥ 1.22 and Node ≥ 20. The frontend must be built first because the binary embeds it via go:embed.

# 1. build the frontend into web/dist
cd web && npm install && npm run build && cd ..

# 2. compile the single binary (web/dist is embedded)
go build -o dash .

The result is one self-contained file, dash. Copy it and a targets.yaml to any Linux/macOS/Windows box — nothing else to install.

Run

./dash                       # uses ./targets.yaml, ./dash.db, :8080
./dash -config /etc/dash/targets.yaml -db /var/lib/dash.db -listen :9090

Open http://localhost:8080.

ICMP checks need raw-socket privileges. Run as root, or grant the binary CAP_NET_RAW (setcap cap_net_raw+ep ./dash), or allow unprivileged ping (sysctl net.ipv4.ping_group_range="0 2147483647"). Other check types work without any privileges.

Configuration — targets.yaml

settings:
  listen: ":8080"        # bind address
  db: "dash.db"          # sqlite file
  history_days: 30       # raw check retention

targets:
  - id: example-web      # unique slug (required)
    name: "Example Website"
    type: http           # http | tcp | tls | icmp
    url: https://example.com    # http → url, tcp/tls → address, icmp → host
    interval: 15s        # time between checks       (default 30s)
    timeout: 5s          # per-check timeout         (default 5s)
    fail_threshold: 3    # consecutive fails → down  (default 3)
    recover_threshold: 2 # consecutive oks → up      (default 2)
    expect_status: 200   # http only: require exact status
    degraded_latency_ms: 1500   # mark degraded above this latency

  - id: github-tls
    name: "GitHub TLS"
    type: tls
    address: github.com:443
    interval: 5m
    warn_days: 21        # tls only: degraded when cert expires sooner

  - id: my-container
    name: "My Container"
    type: docker
    container: my-container     # docker container name
    interval: 30s
    # socket: /var/run/docker.sock   (default)

Docker checks read the daemon socket. Run the binary as a user in the docker group (or SupplementaryGroups=docker in the systemd unit). A container is up when running, degraded while its healthcheck reports starting, and failing when stopped or unhealthy.

API

Endpoint Description
GET /api/targets Current state of all targets: flap-filtered status, last check, 24h/7d uptime, latency percentiles, open incident
GET /api/targets/{id}/history?range=24h Time series: downsampled points plus 24 aggregate buckets (range: 30m, 24h, 7d, …)
GET /api/incidents?range=7d Grouped incidents, ongoing first
GET /api/stream SSE: snapshot on connect, then check per probe and state per confirmed transition

Development

go run . &            # backend on :8080
cd web && npm run dev # vite on :5173, proxies /api → :8080

Layout

main.go, webfs.go        entrypoint + embedded frontend
internal/config          targets.yaml parsing, defaults, validation
internal/checker         the four probe implementations
internal/engine          scheduler, flap detection, incidents, SSE hub
internal/store           sqlite persistence (modernc.org/sqlite, no CGO)
internal/api             REST + SSE handlers
web/                     React + TypeScript + Vite + Tailwind v4 + Motion