Skip to content

Commit d09eebb

Browse files
committed
Summarize large data structures when logging at level :trace.
If we don't do this, the test can run extremely slowly or OOM the JVM.
1 parent 73fd39b commit d09eebb

File tree

1 file changed

+57
-3
lines changed

1 file changed

+57
-3
lines changed

src/clj_libssh2/logging.clj

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,61 @@
33
clj-libssh2."
44
(:require [clojure.tools.logging :as log]
55
[clojure.pprint :refer [pprint]]
6-
[robert.hooke :as hook]))
6+
[robert.hooke :as hook])
7+
(:import [java.io InputStream OutputStream]
8+
[com.sun.jna Pointer]))
9+
10+
(def ^:const byte-array-type (type (byte-array 0)))
11+
(defmulti summarize-structure
12+
"Given an object, trim down the larger items so that logging them doesn't
13+
result in a combination of extreme performance degradataion and lack of
14+
readability.
15+
16+
Arguments:
17+
18+
object The object to summarize.
19+
20+
Return:
21+
22+
An object of the same type and shape as the input, but with the larger parts
23+
of the object summarized into a brief description of their contents."
24+
(fn [object]
25+
(cond (map? object) :map
26+
(sequential? object) :sequence
27+
(instance? Pointer object) :summarize
28+
(instance? InputStream object) :summarize
29+
(instance? OutputStream object) :summarize
30+
(string? object) :string
31+
(= (type object) byte-array-type) :bytes
32+
:else :passthru)))
33+
34+
(defmethod summarize-structure :map
35+
[object]
36+
(->> object
37+
(map #(hash-map (key %) (summarize-structure (val %))))
38+
(apply merge)))
39+
40+
(defmethod summarize-structure :sequence
41+
[object]
42+
(map summarize-structure object))
43+
44+
(defmethod summarize-structure :summarize
45+
[object]
46+
(type object))
47+
48+
(defmethod summarize-structure :string
49+
[object]
50+
(if (< 1024 (count object))
51+
(format "String[%d]" (count object))
52+
object))
53+
54+
(defmethod summarize-structure :bytes
55+
[object]
56+
(format "byte[%d]" (count object)))
57+
58+
(defmethod summarize-structure :passthru
59+
[object]
60+
object)
761

862
(defn- spy-fn
963
"Create a function that can be used as a hook to log the call and result from
@@ -24,8 +78,8 @@
2478
fn-name (symbol (str (ns-name (:ns fn-meta))) (str (:name fn-meta)))
2579
make-message (fn [args result]
2680
(format "%s => %s"
27-
(with-out-str (pprint (cons fn-name args)))
28-
(with-out-str (pprint result))))]
81+
(with-out-str (pprint (cons fn-name (summarize-structure args))))
82+
(with-out-str (pprint (summarize-structure result)))))]
2983
(fn [f & args]
3084
(try
3185
(let [result (apply f args)]

0 commit comments

Comments
 (0)