文章中的内容和图片内容均已做脱敏处理
零依赖、零侵入、零感知,CPU 不到 0.1%,内存不到 30MB。这篇文章是 CodeBuddy Coding Monitor 的完整复盘,从动机讲到架构,再讲到踩过的坑。
如果你去问一个天天用 AI 编程的人:这个月 AI 帮你写了多少代码?花了多少钱?哪个模型最划算?
大概率一个都答不上来。不是他懒,是压根没人给他看数据。Token 消耗、模型分布、缓存命中率、AI 代码占比,全是黑盒。企业环境更狠,不让装代理、不让抓包,安全软件盯着每一个网络连接。
所以我自己写了一个:CodeBuddy Coding Monitor。不碰网络、不装代理、不写日志文件,把 AI 编程的每一笔账算得明明白白。
一、先上三个最硬的数据
0 个第三方依赖
整个后端只用 Python 标准库:sqlite3、re、json、http.server、threading、os、subprocess。没有 pip install,没有虚拟环境,没有依赖地狱,也不用担心供应链安全。打包出来就一个 exe,双击即用。
市面上的监控全家桶(Prometheus 加 Grafana 加 node_exporter 那种),装完十几二十个组件。别人开的是舰队,我骑的是单车,而且单车还跑得更快。
CPU < 0.1%,内存 < 30MB
靠文件指针定位(seek + tell)做只读增量读取,只处理新增内容,第一次全量扫完就不再回头。空闲时资源占用低到可以忽略,跑在开发机上你完全感觉不到它。
监控工具做到这份上,基本等于隐身。
单 exe 交付
PyInstaller 打成一个 coding-monitor.exe,Windows 计划任务开机自启,pythonw 后台静默跑。部署成本约等于零:拷过去、双击、完事。
二、企业安全软件都发现不了它
市面上的 AI 用量监控,主流方案是代理中转或者 MITM 抓包,把 IDE 的网络流量拦下来数 token。听起来很美,企业环境里这就是自爆,安全软件秒告警,防火墙直接断连。
Coding Monitor 的路子完全不同。不装代理、不抓中间人、不拦网络,只以只读消费者的身份,增量读 CodeBuddy IDE / CLI 写下的本地日志。日志文件只读打开,不修改、不写入、不备份,只监听 127.0.0.1,一个端口都不对外开。
日志这玩意儿天生可审计、可追溯,比抓包稳。被监控产品发版更新?只要日志格式不变,采集链路纹丝不动。
一句话:这套方案能过安全审计,其他方案过不了。
三、杀手锏:别人只看成本,我能看产出
这是 Coding Monitor 跟市面上所有 token 统计工具拉开差距的地方。不光是记账,还帮你评估投入产出。
统计看板长这样:token 使用趋势、模型分布、缓存命中率、Skill 有效性、MCP 健康度,多维度交叉:

管理者看成本趋势、Credit 消耗,这个月 AI 花了多少钱一目了然;开发者看模型选择和缓存效率,哪个模型又贵又慢赶紧换掉;团队负责人看 AI 代码占比和 Skill 复用度,团队是真用上了还是装样子。
下面这张是 AI 代码占比看板,通过 Hook 采集工具调用指标,按提交和分支维度量化 AI 对代码库的贡献:

市面上的工具只会告诉你花了多少,这个工具能告诉你值不值。
四、AI 干了啥,回放给你看
光有统计数字不够。Coding Monitor 支持全量会话回放,IDE 和 CLI 的每一次对话都能回溯,Markdown 渲染、工具调用卡片、代码 diff 视图、SSE 实时刷新:

AI 做了什么、怎么做的、改了哪些代码,点开回放一清二楚。复盘、审计,甚至甩锅,都有据可查。
五、整体架构
从数据源到浏览器渲染,分层架构如下:
整个系统干的事就四件:读日志、归一化、存 SQLite、起一个本地 HTTP 服务给浏览器看。听起来朴素,能不能一直稳,全看工程细节。
主 Dashboard 总览页:总步数、总 Token、Credit 消耗、Token 分布、缓存命中率、每日趋势:

端到端数据流水线:
六、内核 + 插件平台:对标 VS Code 的插件化设计
系统拆成两块:稳定内核负责采集、解析、存储、HTTP 服务这些基础设施,插件平台承接所有扩展能力。新插件放进目录就生效,自动检测、自动加载,不用重启服务。
这套设计的妙处:
- 内核迭代不破坏插件,插件开发不污染内核,两边各干各的;
- 进程内事件总线:数据写入后自动广播,插件按需订阅,单个插件挂了也不影响内核和其他插件;
- 两段式 HTTP 路由:插件以自己的名字为前缀注册独立路由,互不打架,还白嫖内核的 CORS、错误处理这些基础设施;
- 免重启热加载:改完插件代码刷新页面就生效,开发体验是真的好。
一句话:内核稳定,边缘灵活。教科书里的解耦长啥样,这就是。
七、数据采集:异构数据源,一个归一化层全吃掉
CodeBuddy IDE 日志是文本行,CLI 会话是 JSONL,字段、结构、语义都不一样。Coding Monitor 用一个归一化层把差异消化在内核内部,插件开发者只消费标准数据:
多智能体(subagent)归因、步骤号序列化、角色派生,这些复杂逻辑全部集中在归一化层,不用在每个插件里重复实现。以后要接新数据源(Web API、别的 IDE),扩展一下归一化映射就行,上层零改动。
八、运维:一个工具把运维做成了产品
监控工具最怕装上就忘、坏了没人修。Coding Monitor 把运维门槛压到最低:
- 配置热加载:改完配置约 30 秒自动生效,支持动态启停数据源,服务不用重启;
- 远程解析规则:解析规则像杀毒软件的病毒库一样远程下发,sha256 校验加本地缓存加周期热更新,还有内置规则兜底。CodeBuddy 日志格式变了?不用重新打包发版,下发一条规则全搞定;
- 自动更新:版本检查、下载、备份、替换、重启,全流程后台完成,更新失败可回滚。更新脚本不被 Windows job object 锁死,父进程退出后依然能活下来完成替换;
- 三级日志清理:归档文件、旧目录、空目录逐级清理,活跃目录保护(5 分钟内有写入不清理),磁盘自动回收,不会越跑越臃肿。
部署架构:
技术栈一览:
| 层面 | 技术 |
|---|---|
| 后端 | Python 3.10+(仅标准库:sqlite3 / re / json / http.server / threading / os / subprocess) |
| 存储 | SQLite(WAL 模式) |
| 前端 | 单 HTML 文件 + ECharts(CDN + 本地化双模式) |
| 打包 | PyInstaller → 单 exe(coding-monitor.exe) |
| 部署 | Windows 计划任务开机自启,pythonw 后台运行 |
九、六个隐蔽 bug,全部追到根因
这部分是我觉得最值钱的。踩过的坑,每一个都不报错、悄悄出错,最考验底层功底。
坑 1:时区双重转换
前一天 16:00 后的新数据被错误归入当天。库里存的是本地时间,查询又套了 SQLite 的 localtime 修饰符,多偏了 8 小时。把 localtime 去掉就好了。
这种 bug 不会报错,只会让统计悄悄偏掉,特别隐蔽。写 SQLite 时间函数前,先搞清楚你存的是 UTC 还是本地时间。
坑 2:多模型会话显示错误
一个会话用多个模型时,显示的模型名对不上。原因是聚合查询用了 MAX() 取模型名,字符串上的 MAX() 是字母序比较,不是"最近一条",模型 ID 和名称还可能来自不同步骤。改成子查询取最后一步模型,再用 GROUP_CONCAT(DISTINCT) 展示全部模型。
SQL 聚合的语义陷阱,多值展示一定要用 GROUP_CONCAT 或者子查询取最新,别拿 MAX 糊弄。
坑 3:热加载读到过期缓存
改了插件代码,行为没变,查了半天发现 Python 的 source_file_loader 按文件路径复用了旧的 pyc 字节码缓存。每次加载用唯一模块名,清掉 __pycache__,临时关闭字节码写回,解决。
热加载场景必须主动打破"同路径同名"的缓存假设,不然"改了没生效"能让你怀疑人生。
坑 4:并发请求 socket 句柄错乱
多线程处理 HTTP 请求时触发 WinError 10038。插件管理器的请求状态放在实例属性上被多线程共享,socket 句柄互相覆盖。改成线程局部存储(threading.local())完事。
HTTP 服务天然多线程,跟"当前请求"相关的状态千万别放共享实例属性上。
坑 5:subprocess 编码崩溃
中文 Windows 下,子进程输出里带 UTF-8 中文直接 UnicodeDecodeError,整条链路崩掉。原因是 subprocess 默认用系统编码 GBK 解码。所有调用显式指定 encoding='utf-8', errors='replace',再对 None 返回值做防御。
跨平台 Python 工具,编码必须显式指定,别赌系统默认值,这是本地化环境最常见的大坑。
坑 6:日志系统白名单失配
大量日志被静默丢弃,一个报错都没有。白名单写的是模块名 data_source,实际 logger 名是带包前缀的 core.data_source,importlib 动态加载的命名空间跟静态导入也不一样。白名单改成实际 logger 名,动态插件按完整模块名前缀匹配。
日志过滤的前缀必须跟 logging.getLogger("") 的实际名称精确匹配。这类问题只会在你想排查的时候冒出来折磨你。
十、安全设计
监控工具天生容易被当成"内鬼",所以安全设计前置:
- 只监听
127.0.0.1,不对外暴露; - 不记录任何密钥和用户凭证;
- 日志文件只读打开,不修改、不写入、不备份;
- 解析异常静默处理,不往响应体里泄露任何敏感信息。
十一、最后
这套系统最大的收获,说不上是哪个具体功能,倒是验证了一个道理:轻量级工具不需要重度框架,也能做到工业级质量。
架构上:数据源抽象加归一化层消化多端差异;内核插件分离把变化隔离在边缘;事件总线加 SSE 实现零轮询实时;配置、规则、更新全部支持远程热更新。
工程上:纯标准库没有依赖负担;增量读取、只读打开、异常静默,对被监控产品零干扰;线程局部存储、显式编码、唯一模块名,每个并发、编码、缓存陷阱都被显式处理掉。
最后想说:工具型产品的最高境界,是用户忘记它的存在。这套系统一直在后台默默跑着,开发者唯一想起它的时刻,是看到 Dashboard 上某个数据突然飙高想查个究竟的时候。而这,恰恰是它存在的意义。