最近,我在一个库中修复了一个错误,该库允许在打印(日志记录)之前修改`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))))