scope-capture 两大进阶技巧:捕获动态 Var 与“远距离间谍“only-from 条件触发
scope-capture 两大进阶技巧:捕获动态 Var 与"远距离间谍"only-from 条件触发
【免费下载链接】scope-captureProject your Clojure(Script) REPL into the same context as your code when it ran项目地址: https://gitcode.com/gh_mirrors/sc/scope-capture
scope-capture是一个 Clojure(Script) REPL 调试神器:通过sc.api/spy和sc.api/brk两个宏,把代码运行时"脚下的现场"(局部变量、动态绑定)快照下来,再用letsc/defsc在 REPL 里原样复现。本文讲解它的两大进阶技巧:① 用:sc/dynamic-vars选项捕获动态 Var 绑定;② 用calling-from+:sc/called-from(内部即 only-from 条件)只在特定调用链触发间谍,过滤掉调试噪音。
快速回顾:spy 如何工作
先把sc.api加载进环境(推荐放在 Leiningen 的:userprofile,见 README.md):
(require 'sc.api)在代码中某处插入(sc.api/spy 表达式)后,每次求值都会记录一个 Execution Point(执行点,正整数 ID),REPL 中即可用它重建现场。示例见 lab/sc/lab/example.cljc,完整流程见 doc/Tutorial.md。
技巧一:捕获动态 Var(:sc/dynamic-vars)
普通的spy只会记录词法局部变量。而*out*、日志上下文、请求属性这类动态作用域的值,必须显式声明才会被捕获:
(sc.api/spy {:sc/dynamic-vars [*out* my.app/*foo*]} expr)要点:
spy和brk都支持该选项(选项说明见 src/sc/api.cljc);- 捕获信息可通过
(sc.api/ep-info ep-id)查看,动态绑定在:sc.ep/dynamic-var-bindings键下; - 复现现场时,
sc.api/letsc会用binding重新绑定这些动态 Var,而sc.api/defsc不会(它只def普通 Vars),需要动态环境时请优先用letsc或子 REPL(sc.repl/ep-repl ep-id)。
这个能力在调试 Web 服务、数据库连接等"难以手工伪造"的运行时状态时尤为关键。
技巧二:远距离间谍——only-from 条件触发
假设通用函数f被很多地方调用,但 Bug 只在从g调用时出现。直接在f里放spy,绝大多数记录都是噪音。解决办法:给间谍下条件触发指令,只有当调用来源匹配时才记录。
第 1 步:在f的间谍处声明"只关心来自:foo的调用":
(defn f [x] (sc.api/spy `{:sc/called-from :foo} ...))第 2 步:用sc.api/calling-from在源头g里标记调用来源:
(defn g [] (sc.api/calling-from :foo (f ...)))原理是:calling-from会把动态 Varsc.api.from/*caller*绑定到指定值(定义在 src/sc/api/from.cljc);间谍点运行时,实现层用should-capture?把*caller*与:sc/called-from期望值比较,不相等就直接跳过记录——这个比较值在源码中就叫only-from(见 src/sc/impl.cljc)。
效果:无论f被调用多少次,只有"来自g"的那一次执行点会被保存,日志干净、内存友好。配合sc.api/disable!还能整点关闭某个代码位的间谍行为。
收尾:别让间谍常驻
- 调试完成后删除 spy 调用并
(sc.api/dispose! ep-id)释放内存,间谍进生产会造成内存泄漏; - 两个技巧可以叠加:在条件触发的间谍上同时声明
:sc/dynamic-vars; - 更多姿势(无表达式 spy、错误才触发、合并多个现场等)见 doc/Tips-and-Tricks.md。
💡 想上手试试?克隆仓库 https://link.gitcode.com/i/3150269b753d391e686f472821872aba 后运行 lab/ 下的示例即可体验。
【免费下载链接】scope-captureProject your Clojure(Script) REPL into the same context as your code when it ran项目地址: https://gitcode.com/gh_mirrors/sc/scope-capture
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
