Skip to content

feat(cmd/stats): /v1/stats 的终端查看入口——按模型的可读表格 - #172

Merged
Sliverkiss merged 1 commit into
Sliverkiss:masterfrom
SunshineR04:feat/cmd-stats-cli
Sep 19, 2026
Merged

Sliverkiss merged 1 commit into
Sliverkiss:masterfrom
SunshineR04:feat/cmd-stats-cli

Conversation

@SunshineR04

@SunshineR04 SunshineR04 commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

本段由 AI 治理机器人自动维护,请勿手工删除上面这行锚点注释。

  • 要点

要点:为 /v1/stats 增加一个终端查看入口,以按模型的可读表格形式展示请求统计。
要做的事:

  • 新增 cmd/stats 命令,读取 /v1/stats 数据并渲染为表格
  • 支持 -json、-watch、-sort、-server 等命令行参数
  • 配置解析与 cmd/acct 对齐,复用相同的 listen/api_key 优先级约定
  • 纯标准库实现,不引入外部依赖,也不修改任何既有文件
  • 做好跨平台编译支持与测试,验证表格和 -json 两条路径
  • 关联时间:2026-09-18T19:44:15.742Z

关联 canonical issue

Related to #171


Closes #171

动机

GET /v1/stats#161 引入)提供了按模型聚合的请求统计,但只能通过 curl | jq 查看:

curl -s -H "Authorization: Bearer $KEY" http://127.0.0.1:7863/v1/stats | jq

实际排障时这类查看是高频、重复、以「比较」为目的的:模型一多,单行 JSON 没法竖着扫,看「哪个模型首字慢」「缓存命中率掉了没」要在嵌套结构里逐字段比对。PR #161 里那个很好的洞察——「输入是输出的 638 倍,成本几乎全在输入侧」——用 jq 手工拼也要好几步才看得出来。

本 PR 补一个终端展示层,形态对标既有的 cmd/creditcmd/acct

效果

📈 网关请求统计 · 窗口 25h5m(自 09-14 20:43)
--------------------------------------------------------------------------------------------------
 模型                        |  请求 | 失败 |   首字 |   耗时 |      吞吐 |     输入/输出 | 缓存命中 |    扣费 |  流式 | 最后活动
-----------------------------+-------+------+--------+--------+-----------+---------------+----------+---------+-------+----------
 deepseek-v4.1-flash         | 1,014 |    3 |  4.63s |  9.22s | 235 tok/s | 334.04M/1.10M |    94.8% |  462.82 | 1,005 |     1s前
 deepseek-v4-pro             |    13 |    0 | 23.34s | 39.91s |  65 tok/s |   7.35M/13.9K |    53.9% |  916.70 |    13 |  11.3h前
-----------------------------+-------+------+--------+--------+-----------+---------------+----------+---------+-------+----------
 合计                        | 1,101 |    9 |  4.87s |  9.13s | 228 tok/s | 341.40M/1.12M |    93.9% | 1379.66 | 1,018 |     1s前
扣费单位=账号积分(非货币)· 完整字段见 -json

用法

go run ./cmd/stats                  # 一次性快照
go run ./cmd/stats -json            # 原始 JSON(供脚本消费)
go run ./cmd/stats -watch 5s        # 原地刷新(Ctrl+C 退出)
go run ./cmd/stats -sort ttfb       # requests|ttfb|tokens|credit
go run ./cmd/stats -server http://127.0.0.1:7863   # 直接指定网关地址

与既有约定的对齐

配置解析与 cmd/acct 同口径(同仓库两个读 config.json 的工具不应有两套约定):

优先级
地址 -server > WB2A_URL > config.jsonlisten
密钥 WB2A_API_KEY > config.jsonapi_key

listen 归一采用与 acctnormalizeListen 逐字一致的实现(net.SplitHostPort + 通配收敛回环),覆盖 [::]:7863 / 裸 :: 等 IPv6 形态;测试表也与 acctTestNormalizeListen 同表,避免两处实现各自走样。

设计取向

  • 不新增采集、不动端点契约:数据全部来自 /v1/stats,本工具只做渲染。
  • 无状态、无外部依赖:纯标准库,不引入常驻服务——是 CLI 不是面板,与「不内嵌 Web 管理面板」的边界一致。
  • 窗口口径如实展示:窗口起点取响应的 since,显示「统计窗口」而非进程 uptime。/v1/stats 是纯内存累加器,重启清零是预期行为,工具侧不做任何补偿或掩饰。
  • 缺字段不崩表:全部用值类型 + 零值兜底,未采集 usage 时显示占位符。

已知的可选复杂度

main.go 约 1.2k 行,其中排版引擎占大头(按终端尺寸淘汰次要列、压缩模型列、折叠多余行、resize 时重算绘制基线)。这部分是可选体验,不是功能必需。

若维护者认为体量过大,可以砍到「按 -json 字段平铺的最简表格」(约 200 行),去掉自适应排版与 watch 原地刷新。请评判哪种粒度更合适。

验证

  • go build ./... 通过;go vet 干净
  • 三平台编译:linux / darwin / windows 全部通过(含平台专用文件 term_windows.go / term_unix.go / term_other.go / term_ansi_nosize.go,build tag 覆盖 windows / unix / solaris+aix / other)
  • 两平台测试编译:linux / darwin 通过
  • go test ./cmd/stats/ 全绿(2000 行测试:布局、填充、resize、屏幕控制、地址解析、错误路径)
  • 对运行中的网关实测:表格与 -json 两条路径均正常取数

说明

本 PR 零修改既有文件——只新增 cmd/stats/ 目录,其余文件与 master 逐字一致。

Sliverkiss#161 引入的 GET /v1/stats 补一个终端展示层。形态对标既有的
cmd/credit 与 cmd/acct:读 config.json 的 listen/api_key、走 HTTP、
无状态、用完即退。

为什么需要:/v1/stats 目前只能 curl | jq 查看。这类查看是高频、重复、
以「比较」为目的的操作——模型一多,单行 JSON 没法竖着扫,看「哪个模型
首字慢」「缓存命中率掉了没」要在嵌套结构里逐字段比对。

不新增采集、不动端点契约:本工具只做渲染,数据全部来自 /v1/stats。
无状态、无外部依赖(纯标准库)、不引入常驻服务——与「不内嵌 Web 管理
面板」的边界一致,是 CLI 不是面板。

功能:
- 默认按模型一行的表格:请求/失败/首字/耗时/吞吐/token/缓存命中率/
  扣费/流式数/最后活动;多模型时附「合计」行
- 按终端尺寸自适应:窗口宽时纳入更多列,窄时依次让位次要列、压缩模型
  列、折叠多余行;窄于最简表则回落为滚动输出(不原地覆盖,避免错位)
- -json 透传原始响应(供脚本消费)
- -watch 原地刷新(-alt-screen 用备用屏,退出还原)
- -sort requests|ttfb|tokens|credit

口径说明(与端点语义一致):
- 窗口起点取响应的 since,展示「统计窗口」而非进程 uptime——/v1/stats
  是纯内存累加器,重启清零是预期行为,工具不做补偿
- 缺字段一律显示占位符(- / 0),不让整表崩掉

配置解析与 cmd/acct 同口径:
- 地址:-server > WB2A_URL > config.json 的 listen
- 密钥:WB2A_API_KEY > config.json 的 api_key
- listen 归一用 net.SplitHostPort(与 acct 的 normalizeListen 逐字一致),
  覆盖 "[::]:7863" / 裸 "::" 等 IPv6 形态

验证:
- linux/darwin/windows 三平台 go build 通过;linux/darwin 测试编译通过
- go test ./cmd/stats/ 全绿;go vet 干净
- 对运行中的网关实测取数正常(表格与 -json 两条路径)
@github-actions github-actions Bot added the enhancement New feature or request label Sep 18, 2026
@github-actions

Copy link
Copy Markdown

🤖 本机器人已对这条 PR 做要点提炼,并关联到对应主题的规范 issue(机器人整理,如有异议请联系维护者)。

要点:为 /v1/stats 增加一个终端查看入口,以按模型的可读表格形式展示请求统计。
要做的事:

此 PR 保持开启,治理机器人不会关闭它。

@Sliverkiss
Sliverkiss merged commit 41a0e32 into Sliverkiss:master Sep 19, 2026
1 check passed
SunshineR04 added a commit to SunshineR04/workbuddy2api that referenced this pull request Sep 19, 2026
PR Sliverkiss#172 已合并(上游 41a0e32),cmd/stats/ 不再属于本 fork。更新
「本仓库与上游的区别」段以反映实际差异:

- 归属表:cmd/stats 从「本 fork」移到「上游」(附 PR 号)
- 「本 fork 新增的内容」→「唯一新增」,只列 stats.ps1
- 对上游文件的改动:由「新增 cmd/stats/ 与 stats.ps1」改为「只新增 stats.ps1」
- 补上游 cmd/stats 的完整用法(含 -server / -alt-screen),
  stats.ps1 段说明其相对上游脚本的额外能力(按需重编译)
@Sliverkiss

Copy link
Copy Markdown
Owner

已合并(commit 41a0e32)。审查结论:apply 干净、全量 gate 全绿(含 -race)、四项必查声称全部属实(配置解析与 cmd/acct 对齐、纯标准库零依赖、零触碰既有文件、跨平台编译),0 个 CRITICAL/HIGH。终端表格与 -json 两条路径的测试覆盖完整。感谢贡献——/v1/stats 从此有了对标 cmd/credit 的终端入口。

@SunshineR04
SunshineR04 deleted the feat/cmd-stats-cli branch September 19, 2026 04:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] /v1/stats 的终端查看入口——按模型的可读表格(对标 cmd/credit)

2 participants