/
exception.clj
75 lines (70 loc) · 2.64 KB
/
exception.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
(ns zpst.exception
(:require clojure.string
clojure.set))
;;
;; # Exception processing
;;
(defn extract-info
"Given an exception, get the information we are about out
of it. Return this in a map with keys:
[:stacktrace-array :exception :exception-str :zcall-vec]"
[e]
#_(println "extract-info: class:" (class e))
(if-let [data (ex-data e)]
; We have a clojure.lang.ExceptionInfo exception, so this has
; the :zcalls, and the cause of this exception has the stack.
{:stacktrace-array nil,
:exception (class e),
:exception-str (str (-> e
class
.getSimpleName)
" "
(.getMessage e)),
:zcall-vec (:zcalls data)}
; We have a regular java or Clojure exception, not one with extra
; data.
{:stacktrace-array (.getStackTrace e),
:exception (class e),
:exception-str (str (-> e
class
.getSimpleName)
" "
(.getMessage e)),
:zcall-vec nil}))
(defn exception-vec
"Given a single exception, look through it and get all of the
nested exception information out into a top level vector of
maps."
[e]
(letfn [(f [ex]
(if-let [cause (.getCause ex)]
(cons ex (f cause))
(list ex)))]
(let [exception-vec (reverse (f e))]
(doseq [x exception-vec]
#_(println "\n\nType:" (type x) "\nType Cause:" (type (.getCause x))))
(into [] (map extract-info exception-vec)))))
(defn sconcat
"Concatentate a sequence of stacks together (which are actually arrays)."
[stacktrace-array-seq]
(let [stacktrace-array-seq (remove nil? stacktrace-array-seq)
length (apply + (map count stacktrace-array-seq))
output (make-array java.lang.StackTraceElement length)]
(loop [array-seq stacktrace-array-seq
index 0]
(if-let [stacktrace-array (first array-seq)]
(do (System/arraycopy stacktrace-array
0
output
index
(count stacktrace-array))
(recur (next array-seq) (+ index (count stacktrace-array))))
output))))
(defn concat-causes
"Take an exception and concatenate all of the causes onto one another."
[e]
(let [ex-vec (exception-vec e)]
{:stacktrace-array (sconcat (map :stacktrace-array ex-vec)),
:exception (vec (map :exception ex-vec)),
:exception-str-vec (vec (map :exception-str ex-vec)),
:zcall-vec (into [] (apply concat (map :zcall-vec ex-vec)))}))