Skip to content

Commit 2b838b9

Browse files
committed
(PDB-5216) Add with-log-mdc to manage the MDC log context
Add a with-log-mdc macro that establishes new MDC contexts during the execution of its body, and ensures the original values (if any) of those contexts are always restored in the end.
1 parent 7614234 commit 2b838b9

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

src/puppetlabs/puppetdb/utils.clj

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
[java.net MalformedURLException URISyntaxException URL]
1818
[java.nio ByteBuffer CharBuffer]
1919
[java.nio.charset Charset CoderResult StandardCharsets]
20-
(java.util.concurrent ScheduledThreadPoolExecutor TimeUnit)))
20+
(java.util.concurrent ScheduledThreadPoolExecutor TimeUnit)
21+
(org.apache.log4j MDC)))
2122

2223
(defmacro with-captured-throw [& body]
2324
`(try [(do ~@body)] (catch Throwable ex# ex#)))
@@ -34,6 +35,36 @@
3435
(apply print args)
3536
(flush)))
3637

38+
(defmacro with-log-mdc
39+
"Establishes the MDC contexts given by the alternating-kvs key value
40+
pairs during the execution of the body, and ensures that the
41+
original values (if any) are always restored before returning."
42+
[alternating-kvs & body]
43+
;; For now, assume this isn't used in performance-critical code,
44+
;; i.e. within tight loops.
45+
(when-not (even? (count alternating-kvs))
46+
(throw (RuntimeException. "Odd number of MDC key value pairs")))
47+
(when-not (every? string? (take-nth 2 alternating-kvs))
48+
(throw (RuntimeException. "MDC keys are not all strings")))
49+
(loop [[k v & alternating-kvs] alternating-kvs
50+
expansion `(do ~@body)]
51+
(if-not k
52+
expansion
53+
(recur alternating-kvs
54+
;; We know k is a string, so it's fine to repeat ~k
55+
`(let [v# ~v]
56+
(if (nil? v#)
57+
~expansion
58+
(let [orig# (MDC/get ~k)]
59+
(try
60+
(MDC/put ~k v#)
61+
~expansion
62+
(finally
63+
;; After you put a nil value MDC/getContext crashes
64+
(if (nil? orig#)
65+
(MDC/remove ~k)
66+
(MDC/put ~k orig#)))))))))))
67+
3768
(defn flush-and-exit
3869
"Attempts to flush *out* and *err*, reporting any failures to *err*,
3970
if possible, and then invokes (System/exit status)."

test/puppetlabs/puppetdb/utils_test.clj

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
(:require [puppetlabs.puppetdb.utils :refer :all]
33
[clojure.test :refer :all]
44
[puppetlabs.puppetdb.testutils :as tu]
5-
[clojure.walk :as walk]))
5+
[clojure.walk :as walk])
6+
(:import
7+
(org.apache.log4j MDC)))
68

79
(deftest test-println-err
810
(is (= "foo\n"
@@ -17,6 +19,23 @@
1719
(is (= "foo bar"
1820
(tu/with-err-str (print-err "foo" "bar")))))
1921

22+
(deftest with-log-mdc-behavior
23+
(with-log-mdc ["foo" "bar"]
24+
(is (= "bar" (MDC/get "foo"))))
25+
(with-log-mdc ["foo" nil]
26+
(is (= {} (MDC/getContext))))
27+
(with-log-mdc ["foo" nil "bar" 1]
28+
(is (= {"bar" "1"} (MDC/getContext))))
29+
(with-log-mdc ["foo" 1 "bar" nil]
30+
(is (= {"foo" "1"} (MDC/getContext))))
31+
(with-log-mdc ["foo" "x" "bar" "y"]
32+
(is (= {"foo" "x" "bar" "y"} (MDC/getContext))))
33+
(with-log-mdc ["foo" "x" "bar" nil "baz" "z"]
34+
(is (= {"foo" "x" "baz" "z"} (MDC/getContext)))
35+
(with-log-mdc ["foo" "x" "bar" "y" "baz" "z"]
36+
(is (= {"foo" "x" "bar" "y" "baz" "z"} (MDC/getContext))))
37+
(is (= {"foo" "x" "baz" "z"} (MDC/getContext)))))
38+
2039
(deftest test-assoc-when
2140
(is (= {:a 1 :b 2}
2241
(assoc-when {:a 1 :b 2} :b 100)))

0 commit comments

Comments
 (0)