# Palladium Monitor LD 逻辑板使用监控系统 — 解析 `test_server -short` 输出,可视化展示 Palladium 仿真器的逻辑板状态、逻辑板利用率、作业信息和 T-Pod 可用性。 ## 功能 - **逻辑板状态可视化** — Rack / Cluster / Board 三级结构,每块 LD 板的 8 个逻辑板 (D0-D7) 以色块展示 - 🟢 可用 (`-`) - 🔵 已加载/预留 (``) - 🔴 已禁用 (`D`) - ⬜ 不存在 (`X`) - **实时指标** — 逻辑板总数、在线/离线、逻辑板利用率、活跃作业数 - **作业信息** — 用户、PID、T-Pod、设计名、已运行时间 - **T-Pod 可用性** — 按 Rack 展示 HDSB / T-Pod 的可用/锁定/预留/不可用状态 - **历史趋势** — 利用率折线图 (Chart.js),支持历史快照查看和清理 - **自动刷新** — 可选 15s/30s/1m/5m 间隔自动刷新仪表板 - **多数据来源** — 手动粘贴、API 推送、远程采集脚本 ## 快速开始 ```bash cd palladium-monitor pip install -r requirements.txt --break-system-packages python3 app.py ``` 浏览器访问 `http://localhost:5100` ## 数据采集方式 ### 方式一:手动粘贴 (Web 界面) 1. 在 Palladium 主机执行 `test_server -short` 2. 复制完整输出 3. 在 Web 界面点击「📥 粘贴数据」按钮 4. 粘贴输出到文本框,点击「解析并存储」 ### 方式二:API 推送 (collect.py + 一键安装) 在 Palladium 主机上部署采集 agent,**推荐**用一键脚本(处理 env 加载、crontab、依赖): ```bash # 把 palladium-monitor/ 整个目录 scp 到 Z1 主机, 然后: sudo ./install_z1_agent.sh \ --url http://<监控服务器IP>:5100/api/collect \ --host scmp03 \ --env /edatools/vxe/VXE23.03.001/bin/env.csh \ --interval 30 ``` 脚本会:建 `/opt/palladium-monitor/`、装 `requests`、备份原 crontab、写入 `*/30 * * * *` 任务、跑一次 dry-run 验证。 **手动部署**(不跑安装器): ```bash # 安装 requests pip install requests # 手动推送一次 python3 collect.py --url http://<监控服务器IP>:5100/api/collect --host scmp03 # 配合 crontab 定时推送 (每30分钟) */30 * * * * /opt/palladium-monitor/collect.py --url http://<监控服务器IP>:5100/api/collect --host scmp03 --env /edatools/vxe/VXE23.03.001/bin/env.csh --log /var/log/palladium-collect.log >> /var/log/palladium-collect.cron.log 2>&1 ``` #### collect.py 参数 | 参数 | 默认值 | 说明 | |------|--------|------| | `--url` | `http://127.0.0.1:5000/api/collect` | 监控服务器 API 地址 | | `--cmd` | `test_server -short` | 采集命令 | | `--host` | `hostname` | 本机标签,会写入 `source` 字段 (如 `collect.py@scmp03`) | | `--env` | — | VXE env.csh/env.sh 路径,脚本自动 `source` 后再执行采集命令 | | `--timeout` | `300` | 采集命令超时秒数 | | `--retries` | `3` | 推送失败重试次数 | | `--retry-delay` | `5` | 重试间隔秒数 | | `--log` | — | 追加写日志文件路径 | | `--dry-run` | — | 只采集不推送,打印输出 | #### 退出码 | Code | 含义 | |------|------| | 0 | 成功 | | 1 | 采集命令无输出 / 失败 | | 2 | 推送失败 (已重试) | | 130 | 用户中断 (Ctrl-C) | cron 收到非 0 时会通过 `MAILTO` 触发告警。 ### 方式三:直接 API 调用 ```bash curl -X POST http://<服务器>:5100/api/collect \ -H "Content-Type: application/json" \ -d '{"raw_output": ""}' ``` ## API 端点 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/` | 仪表板页面 | | GET | `/history` | 历史快照列表 | | GET | `/snapshot/` | 快照详情 | | POST | `/paste` | 手动粘贴数据 (表单提交) | | POST | `/api/collect` | 接收原始输出 (JSON) | | GET | `/api/latest` | 最新快照 JSON | | GET | `/api/history` | 历史趋势 JSON | | GET | `/api/export` | 导出历史 (CSV/JSON, 支持时间范围 + 来源过滤) | | POST | `/api/cleanup?days=N` | 清理 N 天前数据 | | POST | `/api/snapshot//delete` | 删除指定快照 | ### 导出历史数据 `/api/export` 端点支持 CSV (Excel 友好, 带 UTF-8 BOM) 和 JSON 两种格式,可按时间范围和来源过滤。 ``` GET /api/export?format=csv # 默认: CSV 全部 GET /api/export?format=json # JSON 全部 GET /api/export?days=7 # 最近 7 天 GET /api/export?since=2026-07-01&until=2026-07-31 # 自定义范围 GET /api/export?source=collect.py # 按来源模糊匹配 GET /api/export?format=json&days=30&source=scmp03 # 组合 ``` 参数说明: - `format`: `csv` (默认) 或 `json` - `days`: 限制最近 N 天 (0/缺省 = 全部) - `since` / `until`: `YYYY-MM-DD` 或 ISO 时间戳 - `source`: 模糊匹配 `source` 字段 (如 `collect.py`、`scmp03`) - `limit`: 最多返回条数 (默认 10000, 上限 100000) CSV 文件名: `palladium_snapshots_YYYYMMDD_HHMMSS.csv`,包含 19 列(时间本地+UTC、仿真器/硬件/ConfigMgr、系统状态、来源、板/域计数、利用率、作业数等)。 Web 界面入口:历史记录页右上角「📤 导出」按钮。 ## 解析器支持的输出格式 ``` Emulator: sc01_emu Hardware: Palladium Z1 Configmgr: V21.02.102.s002System Status: PARTIAL Rack 0 has 2 clusters Cluster 0 has 6 boards CCD: ONLINE LD Status D0 D1 D2 D3 D4 D5 D6 D7 0 ONLINE - - - - - - - - ... ``` 逻辑板状态图例: - `-` → 可用 (Domain is available) - `X` → 不存在 (Domain does not exist) - `D` → 已禁用 (Domain is disabled) - `` → 已加载/预留 (Domain is downloaded or reserved) ## 项目结构 ``` palladium-monitor/ ├── app.py # Flask 应用: 解析器 + 数据模型 + 路由 + API ├── collect.py # 远程数据采集推送脚本 (Z1 主机跑) ├── install_z1_agent.sh # Z1 主机一键部署脚本 (env 加载 + crontab + 依赖) ├── requirements.txt # Flask, Flask-SQLAlchemy ├── instance/ # SQLite 数据库 ├── templates/ │ ├── base.html # 基础布局 (导航 + 粘贴弹窗) │ ├── dashboard.html # 主仪表板 │ ├── history.html # 历史记录列表 │ └── snapshot.html # 快照详情页 └── static/ └── style.css # 暗色主题样式 ``` ## 生产部署 ### 监控服务器端 ```bash cd palladium-monitor pip install -r requirements.txt --break-system-packages gunicorn --workers 2 --bind 0.0.0.0:5100 app:app ``` ### 邮件功能配置 (环境变量) 监控服务启动时会自动读以下环境变量, 无需 Web UI。所有变量都是可选的 (不配就相当于关闭邮件功能)。 | 变量 | 必填 | 默认 | 说明 | |------|------|------|------| | `MAIL_ENABLED` | ❌ | `false` | 是否启用邮件功能, 设为 `true`/`1`/`yes` 开启 | | `SMTP_HOST` | 启用时必填 | — | SMTP 服务器地址 (如 `smtp.gmail.com`、`smtp.exmail.qq.com`) | | `SMTP_PORT` | ❌ | `587` | SMTP 端口 (587=STARTTLS, 465=SSL, 25=明文) | | `SMTP_USER` | 启用时必填 | — | SMTP 登录用户名 (通常等于邮箱地址) | | `SMTP_PASSWORD` | 启用时必填 | — | SMTP 密码 (Gmail 用 App Password, 16 位) | | `SMTP_USE_TLS` | ❌ | `true` | 是否用 STARTTLS (端口 587 时设为 `true`) | | `SMTP_USE_SSL` | ❌ | `false` | 是否用隐式 SSL (端口 465 时设为 `true`) | | `MAIL_FROM` | 启用时必填 | — | 发件人邮箱 | | `MAIL_FROM_NAME` | ❌ | `Palladium Monitor` | 发件人显示名 | | `MAIL_TO` | 启用时必填 | — | 收件人列表, 英文逗号分隔 (如 `alice@x.com,bob@y.com`) | | `MAIL_SEND_HOUR` | ❌ | `9` | 每天发送时间-小时 (0-23) | | `MAIL_SEND_MINUTE` | ❌ | `0` | 每天发送时间-分钟 (0-59) | | `MONITOR_BASE_URL` | ❌ | `http://127.0.0.1:5100` | 监控页 URL (用于邮件里"查看完整仪表板"链接) | | `ALLOW_EMAIL_TRIGGER` | ❌ | — | 设为 `true` 允许通过 `POST /api/email/send` 手动触发 (默认禁止) | #### 启动方式 **方式 1: 直接 export** ```bash export MAIL_ENABLED=true export SMTP_HOST=smtp.gmail.com export SMTP_PORT=587 export SMTP_USER=monitor@gmail.com export SMTP_PASSWORD=**** # Gmail 用 App Password export MAIL_FROM=monitor@gmail.com export MAIL_TO=team-lead@company.com,ops@company.com gunicorn --workers 2 --bind 0.0.0.0:5100 app:app ``` **方式 2: systemd EnvironmentFile (推荐)** ```ini # /etc/palladium-monitor/mail.env MAIL_ENABLED=true SMTP_HOST=smtp.exmail.qq.com SMTP_PORT=587 SMTP_USER=monitor@company.com SMTP_PASSWORD=**** # 或从 secret manager 注入 MAIL_FROM=monitor@company.com MAIL_TO=team@company.com MAIL_SEND_HOUR=8 MAIL_SEND_MINUTE=30 ``` ```ini # /etc/systemd/system/palladium-monitor.service [Service] EnvironmentFile=/etc/palladium-monitor/mail.env ExecStart=/usr/bin/gunicorn --workers 2 --bind 0.0.0.0:5100 app:app ``` `systemctl daemon-reload && systemctl restart palladium-monitor` #### 邮件 API 端点 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/email/status` | 查看当前邮件配置 (不泄露密码) | | GET | `/api/email/preview` | 渲染报告内容 (不发送, 浏览器内联展示) | | POST | `/api/email/send` | 手动触发一次 (需 `ALLOW_EMAIL_TRIGGER=true`) | **注意**: scheduler 在进程内启动, **每个 gunicorn worker 都会尝试启动**; 但用 `_scheduler_started` 锁保证实际只有一个线程在跑, 其余的只是 `time.sleep(86400)` 等下一天, 不影响。 #### 邮件内容示例 每日报告包含: - **主题**: `[Palladium] 每日报告 YYYY-MM-DD — 利用率 X.X%` - **正文 (HTML + 纯文本)**: 系统信息 / 当前指标卡片 / 近 24h 趋势统计 + 样本柱状图 / 离线板列表 / 活跃作业列表 - **多部分**: 同时发 HTML 和纯文本, 邮件客户端自动选最合适的渲染 ### Z1 主机端(采集 agent) 把整个 `palladium-monitor/` 目录 `scp` 到 Z1 主机,然后一键安装: ```bash sudo ./install_z1_agent.sh \ --url http://<监控服务器IP>:5100/api/collect \ --host <本机标签, e.g. scmp03> \ --env /edatools/vxe/VXE23.03.001/bin/env.csh \ --interval 30 ``` 卸载:`sudo ./install_z1_agent.sh --uninstall`(保留日志)。 ### 故障排查 | 症状 | 检查 | |------|------| | 仪表板一直显示示例数据 | `curl http://:5100/api/latest` 看最新 snapshot 的 `source` 字段,应为 `collect.py@` 而不是 `sample` | | Z1 端推送失败 (exit=2) | `tail -50 /var/log/palladium-collect.log`;若 `test_server` 命令找不到,加 `--env /edatools/vxe/VXE23.03.001/bin/env.csh` | | cron 没跑 | `crontab -l \| grep palladium`;`grep CRON /var/log/syslog`(Linux) | | 推送成功但数据没更新 | 监控服务器 SQLite 写入是同步的,先看 `/api/latest` 的 `timestamp`,再 `tail /var/log/palladium-monitor-stderr.log`(gunicorn 日志) | | 想清理老数据 | `curl -X POST 'http://:5100/api/cleanup?days=30'` | | 多台 Z1 一起推 | 给每台用不同的 `--host` 标签,仪表板即可区分来源 | ## 技术栈 - **后端**: Flask 3.0 + Flask-SQLAlchemy + SQLite - **前端**: Jinja2 模板 + 原生 CSS (暗色主题) + Chart.js (趋势图) - **解析**: Python re 正则表达式解析 `test_server -short` 输出