docs: synthetic demo mode and a screenshot with no customer data
The first screenshot was captured on a real workstation: it carried a machine name, a live call with a named participant, and a staging URL. None of that belongs in a public repo. --demo now loads demo/demo-snapshot.json and serves it through the same API, so documentation screenshots are reproducible, reviewable, and free of anyone's actual desktop. The canned snapshot is shaped to tell the story: a leaked automation run at 6.10 cores with idle pages, and a video call tab carrying 221% page work beside its idle siblings.
This commit is contained in:
parent
9d065153b0
commit
b66c6619d8
4 changed files with 1489 additions and 1 deletions
|
|
@ -63,6 +63,10 @@ the same row, always labeled:
|
||||||
Requirements: Linux, Python 3.9+, a `/proc` filesystem. No dependencies, no
|
Requirements: Linux, Python 3.9+, a `/proc` filesystem. No dependencies, no
|
||||||
root, no agent installed inside your apps.
|
root, no agent installed inside your apps.
|
||||||
|
|
||||||
|
Want to see it without pointing it at your machine? `python3 server.py --demo`
|
||||||
|
serves a canned snapshot at the same URL, which is how the screenshot above was
|
||||||
|
made.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://forge.binaryranch.com/sastian/vitals.git
|
git clone https://forge.binaryranch.com/sastian/vitals.git
|
||||||
cd vitals
|
cd vitals
|
||||||
|
|
|
||||||
1460
demo/demo-snapshot.json
Normal file
1460
demo/demo-snapshot.json
Normal file
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 221 KiB |
26
server.py
26
server.py
|
|
@ -602,6 +602,16 @@ class Sampler(threading.Thread):
|
||||||
SAMPLER = Sampler()
|
SAMPLER = Sampler()
|
||||||
|
|
||||||
|
|
||||||
|
DEMO = {"data": None}
|
||||||
|
|
||||||
|
|
||||||
|
def load_demo():
|
||||||
|
path = os.path.join(HERE, "demo", "demo-snapshot.json")
|
||||||
|
with open(path) as f:
|
||||||
|
DEMO["data"] = json.load(f)
|
||||||
|
return DEMO["data"]
|
||||||
|
|
||||||
|
|
||||||
class Handler(BaseHTTPRequestHandler):
|
class Handler(BaseHTTPRequestHandler):
|
||||||
protocol_version = "HTTP/1.1"
|
protocol_version = "HTTP/1.1"
|
||||||
|
|
||||||
|
|
@ -626,12 +636,20 @@ class Handler(BaseHTTPRequestHandler):
|
||||||
except OSError:
|
except OSError:
|
||||||
return self._send("index.html missing", "text/plain", 500)
|
return self._send("index.html missing", "text/plain", 500)
|
||||||
if u.path == "/api/snapshot":
|
if u.path == "/api/snapshot":
|
||||||
|
if DEMO["data"]:
|
||||||
|
snap = dict(DEMO["data"]["snapshot"])
|
||||||
|
snap["t"] = time.time()
|
||||||
|
snap["demo"] = True
|
||||||
|
return self._send(json.dumps(snap))
|
||||||
with SAMPLER.lock:
|
with SAMPLER.lock:
|
||||||
return self._send(json.dumps(SAMPLER.latest))
|
return self._send(json.dumps(SAMPLER.latest))
|
||||||
if u.path == "/api/detail":
|
if u.path == "/api/detail":
|
||||||
key = parse_qs(u.query).get("key", [""])[0]
|
key = parse_qs(u.query).get("key", [""])[0]
|
||||||
if not key:
|
if not key:
|
||||||
return self._send('{"error":"key required"}', code=400)
|
return self._send('{"error":"key required"}', code=400)
|
||||||
|
if DEMO["data"]:
|
||||||
|
return self._send(json.dumps(
|
||||||
|
DEMO["data"]["details"].get(key, {"key": key, "processes": [], "series": []})))
|
||||||
return self._send(json.dumps(SAMPLER.detail(key)))
|
return self._send(json.dumps(SAMPLER.detail(key)))
|
||||||
return self._send("not found", "text/plain", 404)
|
return self._send("not found", "text/plain", 404)
|
||||||
|
|
||||||
|
|
@ -640,8 +658,14 @@ def main():
|
||||||
ap = argparse.ArgumentParser()
|
ap = argparse.ArgumentParser()
|
||||||
ap.add_argument("--port", type=int, default=int(os.environ.get("VITALS_PORT", 8791)))
|
ap.add_argument("--port", type=int, default=int(os.environ.get("VITALS_PORT", 8791)))
|
||||||
ap.add_argument("--host", default="127.0.0.1")
|
ap.add_argument("--host", default="127.0.0.1")
|
||||||
|
ap.add_argument("--demo", action="store_true",
|
||||||
|
help="serve the canned demo snapshot (documentation, screenshots, UI work)")
|
||||||
args = ap.parse_args()
|
args = ap.parse_args()
|
||||||
SAMPLER.start()
|
if args.demo:
|
||||||
|
load_demo()
|
||||||
|
print("Vitals in DEMO mode — canned data, no /proc sampling, no CDP", flush=True)
|
||||||
|
else:
|
||||||
|
SAMPLER.start()
|
||||||
time.sleep(1.2)
|
time.sleep(1.2)
|
||||||
try:
|
try:
|
||||||
srv = ThreadingHTTPServer((args.host, args.port), Handler)
|
srv = ThreadingHTTPServer((args.host, args.port), Handler)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue