最近,我在一个库中修复了一个错误,该错误在打印(记录)之前,通过创建一个新的ex-info
来存储更新的数据,暴露了修改ex-info
内部数据的能力。这自然地覆盖了给定的ex-info
上的现有堆栈跟踪,因此我的修复方案是使用 interoperability 来将新的ex-info
的堆栈跟踪设置为原始ex-info
的堆栈跟踪
(let [cause (process-ex-data-map ex-data-field-fn (ex-cause ex))
new-ex (ex-info (ex-message ex)
(into {} (map (fn [[k v]] {k (ex-data-field-fn v)}) (ex-data ex)))
cause)]
(.setStackTrace ^ExceptionInfo new-ex (.getStackTrace ^ExceptionInfo ex))
new-ex)
这是一个不错的解决方案,但直接修改`ex-info`的内部结构感觉不对劲。我明白,由于 interoperability 的原因,`ExceptionInfo`可能不能是不可变的,但我认为如果clojure.core
中有函数在处理`ExceptionInfo`时视为不可变,将会很有帮助。
可能像这样?
(defn ex-stacktrace
([ex]
(when (instance? Throwable ex)
(.getStackTrace ^Throwable ex)))
([ex other]
(when (and (instance? clojure.lang.ExceptionInfo ex)
(instance? Throwable other))
(let [new-ex (ex-info (ex-message ex) (ex-data ex) (ex-cause ex))]
(.setStackTrace ^clojure.lang.ExceptionInfo new-ex
(.getStackTrace ^Throwable other))
new-ex))))