dsh-server-dashboard 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +123 -0
- package/cordis.patch.yml +6 -0
- package/dist/client/thresholds.js +11 -0
- package/dist/client/types.js +2 -0
- package/dist/client.js +4606 -0
- package/dist/host/collector.js +878 -0
- package/dist/host/sshconfig.js +68 -0
- package/dist/index.js +718 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-server-dashboard contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# dsh-server-dashboard
|
|
2
|
+
|
|
3
|
+
DSH Web 插件:SSH 连接多台 GPU 服务器,在侧边栏展示服务器工作状态
|
|
4
|
+
(GPU 利用率/显存/温度/功耗、CPU/内存/磁盘、占用进程)与实验进展
|
|
5
|
+
(训练日志 tail + loss/epoch 曲线 + 实验结束提醒)。纯只读。
|
|
6
|
+
内置 **/dash/events 即时提醒通道**(长轮询挂起推送,秒级):实验日志停滞、
|
|
7
|
+
主机离线/恢复、高温出现/解除,状态翻转即刻 toast(无需等下一轮轮询)。
|
|
8
|
+
|
|
9
|
+
- 需求规格:[REQUIREMENTS.md](./REQUIREMENTS.md)
|
|
10
|
+
- 架构调研:[ARCHITECTURE_NOTES.md](./ARCHITECTURE_NOTES.md)
|
|
11
|
+
|
|
12
|
+
## 功能
|
|
13
|
+
|
|
14
|
+
- **看板**:侧边栏底部显示器按钮打开;**停靠在左侧**(自动量取工作区侧栏宽度避让,
|
|
15
|
+
侧栏拖宽/折叠实时跟随),与右侧的学者工作台互不冲突、可同时打开;每台主机一张卡片
|
|
16
|
+
- 顶部 **GPU 热力总览条 + 舰队计数徽章**(●N 训练中 / ●N 异常 / ●N 空闲):
|
|
17
|
+
每主机一行、每卡一个色块(利用率着色,高温红框、停滞角标、离线整行红),
|
|
18
|
+
点击色块直达该主机卡并弹开对应 GPU 行
|
|
19
|
+
- 主区 = **固定主机全部常驻(不限数量)** + 异常主机自动上浮置顶;
|
|
20
|
+
未固定的健康主机折叠在「其他服务器」
|
|
21
|
+
- 主机卡头部 📌 一键固定/取消(原地点击,无需进设置页);固定后 📌 变主题蓝
|
|
22
|
+
- 抽屉拉宽时 GPU 行自动排双列(单屏可见卡数翻倍);抽屉宽度上限为
|
|
23
|
+
**窗口的 60%**(绝对上限 520px),窄窗口自动收窄、窗口恢复后自动还原
|
|
24
|
+
- GPU 状态条(利用率/显存/温度/功耗)+ 每卡进程归属(**完整命令行**,一眼识别哪个实验;
|
|
25
|
+
进程表默认显存降序、表头点击切换 PID 序)
|
|
26
|
+
- GPU 行带**双层扫描条**(上层利用率、下层显存),忙卡不用读数字;空闲 GPU 行自动淡化
|
|
27
|
+
- CPU(两次采样增量,真实瞬时值)/内存/磁盘/**1 分钟负载**、进程表、日志 tail、指标曲线
|
|
28
|
+
- 卡片顶部的"训练摘要条":epoch/loss 最新值一眼可见;**数值变化时琥珀色闪烁渐隐**
|
|
29
|
+
- 折叠态异常状态显示为**琥珀色 chip**(高温/停滞/磁盘),扫一眼定位问题卡
|
|
30
|
+
- 相对时间("5 秒前")+ 下次刷新倒计时;刷新按钮旋转反馈;图表宽度自适应抽屉,
|
|
31
|
+
曲线末端钉有当前值标签、角落有量程提示
|
|
32
|
+
- 图表带 **EMA 平滑**(默认开,图例行「S」开关),锯齿降噪看趋势;
|
|
33
|
+
**图例悬停聚焦**(悬停某指标时其余曲线压暗)
|
|
34
|
+
- 日志区**按语义着色**:ERROR/异常行红、WARNING 橙、指标数值主题蓝
|
|
35
|
+
- 磁盘只平铺根分区与 >70% 挂载点,其余折叠为「+N 个挂载点」
|
|
36
|
+
- GPU 展开区带背景色块 + 主题色左边线,与卡片层级清晰分离
|
|
37
|
+
- **SSH 连接池**:每主机一条常驻连接跨轮询复用(15s 保活、10 分钟闲置回收、
|
|
38
|
+
断连自动重连并重试一次;从配置移除的主机其连接在下一轮采集时立即回收,
|
|
39
|
+
无需等闲置超时)——暖轮询从 ~470ms 降到 ~125ms
|
|
40
|
+
- **自动发现训练日志**(两层):
|
|
41
|
+
- 设置页每台主机「🔍 发现日志」:读进程 stdout 重定向 + tee 命令行 +
|
|
42
|
+
工作目录扫描(3 层深),一键选用
|
|
43
|
+
- **每卡自动挂日志**:宿主自动从每张 GPU 的进程找到其日志并独立出曲线,
|
|
44
|
+
无需任何配置(发现结果按 PID 缓存 5 分钟,进程不变时跳过重复探测)
|
|
45
|
+
- **日志解析**:`name=value` / `name: value` / `Epoch 12/100` / tqdm 进度条 /
|
|
46
|
+
YOLO 定宽表格(含 `\r` 刷新与 ANSI 转义)/ JSON 行格式;
|
|
47
|
+
半写行(tqdm 同行续写)与日志轮转(文件变小)时游标自动校正,不重复计点
|
|
48
|
+
- **曲线跨重启**:冷启动/重启后首轮从日志尾部大窗口(2MB/2000 行)种子化恢复
|
|
49
|
+
最近 200 点——日志文件本身就是持久化
|
|
50
|
+
- **实验结束提醒**:主机级与**每卡**日志停滞 N 分钟(默认 10,可配)→ 页面 toast;
|
|
51
|
+
**toast 可点击**,直达对应主机卡并高亮;通知带 2 分钟宽限,稍晚打开页面也不会错过
|
|
52
|
+
- **设置**:主机增删改(含从 ~/.ssh/config 导入、**主机搜索框**)、认证(密钥/密码,
|
|
53
|
+
存 DSH 凭据库)、固定显示(常驻看板,不限数量)、刷新间隔(10-300s,改完即生效
|
|
54
|
+
无需刷新页面)、结束判定阈值;删除主机需确认;导入后显示导入/跳过统计;界面全量中英双语
|
|
55
|
+
- **安全**:仅只读远程命令;**全部 /dash/* 路由仅接受 loopback 来源**
|
|
56
|
+
(127.0.0.1 / ::1 / IPv4 映射 loopback;web 服务以 `--host 0.0.0.0` 对局域网
|
|
57
|
+
开放时,远程主机也无法直接访问看板读/写路由,非 loopback 请求一律 403);
|
|
58
|
+
带 body 的路由强制 application/json(防跨源表单投递);凭据经 DSH credentials
|
|
59
|
+
库存储(本地 provider 为 0600 明文 + 引用分离),且**凭据名一律由服务端按
|
|
60
|
+
主机 id 派生(`SD_<hostId>`)**——客户端提交的凭据名不参与凭据库寻址,
|
|
61
|
+
无法借 PUT 配置覆写任意既有凭据;任何日志都不输出密钥内容
|
|
62
|
+
|
|
63
|
+
## 已知限制
|
|
64
|
+
|
|
65
|
+
- 其他用户进程的日志(如 A5000 上 miaomiao 的训练)无法自动读取——需对方授权目录或提供凭据
|
|
66
|
+
- **实验结束判定为增量语义**:每轮采集比较日志 mtime/size 相对上轮是否变化(按本地
|
|
67
|
+
时钟记账"最后变化时刻"),不做"本地挂钟 − 远端 mtime"直接相减——远端主机时钟
|
|
68
|
+
偏移不再造成误报;首次观察到某个日志时给一个阈值时长的宽限期,看板关闭期间的
|
|
69
|
+
采集空档也不会累积成"停滞"
|
|
70
|
+
- 离线主机进入指数退避(1→2→5→10→30 分钟),期间展示缓存的错误快照;
|
|
71
|
+
看板顶部手动「刷新」清除全部退避,离线卡片上的「立即重试」只清那一台
|
|
72
|
+
(需带 force=1 才生效);**设置页保存配置同样清空全部退避**并立即按新配置重试
|
|
73
|
+
- /dash/events 的事件采样间隔与刷新间隔联动(下限 10 秒):刷新间隔调大后,
|
|
74
|
+
离线/高温翻转等事件的提醒时延也随之变大
|
|
75
|
+
- 无 GPU(或驱动异常)的机器显示 CPU/内存/磁盘,不整卡失败
|
|
76
|
+
- 宿主侧代码更新需完全重启桌面端/`dsh web`;客户端 UI 刷新页面即生效
|
|
77
|
+
|
|
78
|
+
## 目录
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
src/
|
|
82
|
+
host/collector.ts SSH 采集与解析(nvidia-smi/free/df/日志尾读/指标解析/自动发现)
|
|
83
|
+
host/sshconfig.ts ~/.ssh/config 解析
|
|
84
|
+
index.ts Cordis 宿主插件(settings + credentials + /dash/* 路由 + 轮询)
|
|
85
|
+
client/index.tsx 客户端入口(sidebar.footer.action 触发器 + settings.section)
|
|
86
|
+
client/DashboardPanel.tsx / SettingsSection.tsx / locales.ts / types.ts
|
|
87
|
+
scripts/ 构建与测试(smoke / regression / table / discover / repair / validate…)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 构建 / 安装
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
npm install # 需要 HTTPS_PROXY 可用
|
|
94
|
+
npm run build # tsc(宿主)+ tsdown(客户端)+ 包装器
|
|
95
|
+
# 安装进 web profile(父目录执行):
|
|
96
|
+
dsh plugin --profile web add ./dsh-server-dashboard
|
|
97
|
+
# 或手动:profile package.json 加 link 依赖 + dsh.profile.bundles 加包名,pnpm install
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 路由
|
|
101
|
+
|
|
102
|
+
| 路由 | 方法 | 说明 |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| `/dash/snapshots` | GET | 全部主机快照(GPU/CPU/内存/磁盘/进程/日志/曲线) |
|
|
105
|
+
| `/dash/config` | GET/PUT | 主机配置读写(PUT 可携带密钥/密码密文) |
|
|
106
|
+
| `/dash/import-ssh` | GET | 解析 ~/.ssh/config 返回可导入主机 |
|
|
107
|
+
| `/dash/test` | POST | 连接测试(返回主机名 + GPU 数) |
|
|
108
|
+
| `/dash/discover-logs` | POST | 自动发现训练日志候选 |
|
|
109
|
+
|
|
110
|
+
## 安装(npm 发布版)
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
dsh plugin --profile web add dsh-server-dashboard
|
|
114
|
+
# 然后完全重启 dsh web
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- 自定义路由(`/dash/*` `/scholar/*` `/traj/*` `/statusbar/*`)仅接受本机(loopback)访问;
|
|
118
|
+
若以 `--host 0.0.0.0` 对局域网开放 Web UI,插件路由也不会暴露给远程。
|
|
119
|
+
- 从源码 link 安装(开发):路径含空格时 `dsh plugin add` 会写坏 profile,请按仓库内文档手工修 link。
|
|
120
|
+
|
|
121
|
+
## Changelog
|
|
122
|
+
|
|
123
|
+
见 [CHANGELOG.md](./CHANGELOG.md)。
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# dsh-server-dashboard bundle layer — applied when a profile lists this bundle.
|
|
2
|
+
# `name` is a PACKAGE NAME resolved through the profile's node_modules
|
|
3
|
+
# (or the $DSH_HOME/profiles/node_modules fallback), not a relative path.
|
|
4
|
+
- insert:
|
|
5
|
+
- id: dsh-server-dashboard
|
|
6
|
+
name: dsh-server-dashboard
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Shared alarm thresholds — the dashboard's single source of truth so the
|
|
2
|
+
* heatmap cells, temp pills, anomaly flags and chart tones never drift apart. */
|
|
3
|
+
/** GPU is "hot" at or above this temperature (°C) */
|
|
4
|
+
export const TEMP_HOT = 82;
|
|
5
|
+
/** GPU enters the warm band at this temperature (°C) */
|
|
6
|
+
export const TEMP_WARM = 75;
|
|
7
|
+
/** utilization (%, 0-100) at/above which a GPU counts as maxed/saturated */
|
|
8
|
+
export const UTIL_SATURATED = 95;
|
|
9
|
+
/** disk usage (%) above which a mount is flagged */
|
|
10
|
+
export const DISK_WARN = 90;
|
|
11
|
+
export const thresholds = { TEMP_HOT, TEMP_WARM, UTIL_SATURATED, DISK_WARN };
|