最近,我在一个库中修复了一个错误,该错误暴露了在打印(记录)之前修改ex-info
中数据的功能,通过创建一个新的ex-info
来存储更新后的数据。这自然覆盖了给定ex-info
中现有的堆栈跟踪,因此我的修复方法是通过使用交互操作来设置新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
的内部结构感觉不好或很尴尬。我理解由于交互操作的原因,`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))))