Skip to content

Commit 3a68319

Browse files
committed
log with clojure.tools.logging if it's installed. Run tests with and without the c.t.l dependency. Fixes #172
1 parent 577145e commit 3a68319

4 files changed

Lines changed: 48 additions & 34 deletions

File tree

project.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
[lein-ring "0.9.7"]
3131
[funcool/codeina "0.3.0"]]
3232
:dependencies [[org.clojure/clojure "1.7.0"]
33-
[org.clojure/tools.logging "0.3.1"]
3433
[peridot "0.4.1"]
3534
[javax.servlet/servlet-api "2.5"]
3635
[midje "1.8.2"]
@@ -44,14 +43,15 @@
4443
:reload-paths ["src" "examples/src"]}
4544
:source-paths ["examples/src" "examples/dev-src"]
4645
:main examples.server}
46+
:logging {:dependencies [[org.clojure/tools.logging "0.3.1"]]}
4747
:1.8 {:dependencies [[org.clojure/clojure "1.8.0-RC2"]]}}
4848
:eastwood {:namespaces [:source-paths]
4949
:add-linters [:unused-namespaces]}
5050
:codeina {:sources ["src"]
5151
:target "gh-pages/doc"
5252
:src-dir-uri "http://github.com/metosin/compojure-api/blob/master/"
5353
:src-linenum-anchor-prefix "L"}
54-
:aliases {"all" ["with-profile" "dev:dev,1.8"]
54+
:aliases {"all" ["with-profile" "dev:dev,logging:dev,1.8"]
5555
"start-thingie" ["run"]
5656
"aot-uberjar" ["with-profile" "uberjar" "do" "clean," "ring" "uberjar"]
5757
"test-ancient" ["midje"]

src/compojure/api/exception.clj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns compojure.api.exception
22
(:require [ring.util.http-response :refer [internal-server-error bad-request]]
33
[clojure.walk :refer [postwalk]]
4+
[compojure.api.logging :as log]
45
[schema.utils :as su])
56
(:import [schema.utils ValidationError NamedError]
67
[com.fasterxml.jackson.core JsonParseException]
@@ -11,12 +12,12 @@
1112
;;
1213

1314
(defn safe-handler
14-
"Prints stacktrace to console and returns safe error response.
15+
"Writes :error to log with the exception message & stacktrace.
1516
1617
Error response only contains class of the Exception so that it won't accidentally
1718
expose secret details."
1819
[^Exception e _ _]
19-
(.printStackTrace e)
20+
(log/log! :error e (.getMessage e))
2021
(internal-server-error {:type "unknown-exception"
2122
:class (.getName (.getClass e))}))
2223

src/compojure/api/logging.clj

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-
(ns compojure.api.logging)
1+
(ns compojure.api.logging
2+
(:require [clojure.string :as str]))
23

3-
(defn resolve-logger []
4-
(if (find-ns 'clojure.tools.logging)
5-
(do
6-
(require 'clojure.tools.logging)
7-
(fn [level x]
8-
(clojure.tools.logging/spy level x)))
9-
(fn [level x & more]
10-
(let [log (fn [level more]
11-
(println (.toUpperCase (name level)) (apply str more)))]
12-
(if (instance? Throwable x)
13-
(do
14-
(log level (cons (.getMessage x) more))
15-
(.printStackTrace x))
16-
(log level (cons x more)))))))
4+
;; default to console logging
5+
(defn log! [level x & more]
6+
(let [log (fn [level more] (println (.toUpperCase (name level)) (str/join " - " more)))]
7+
(if (instance? Throwable x)
8+
(do
9+
(log level more)
10+
(.printStackTrace x))
11+
(log level (into [x] more)))))
1712

18-
(def log (resolve-logger))
19-
20-
(comment
21-
(log :info (RuntimeException. "kosh")))
13+
;; use c.t.l logging if available
14+
(if (find-ns 'clojure.tools.logging)
15+
(eval
16+
`(do
17+
(require 'clojure.tools.logging)
18+
(defmacro ~'log! [& ~'args]
19+
`(do
20+
(clojure.tools.logging/log ~@~'args))))))

test/compojure/api/middleware_test.clj

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,21 @@
33
[midje.sweet :refer :all]
44
[ring.util.http-response :refer [ok]]
55
[ring.util.http-status :as status]
6-
ring.util.test))
6+
ring.util.test)
7+
(:import [java.io PrintStream ByteArrayOutputStream]))
8+
9+
(defmacro without-err
10+
"Evaluates exprs in a context in which *err* is bound to a fresh
11+
StringWriter. Returns the string created by any nested printing
12+
calls."
13+
[& body]
14+
`(let [s# (PrintStream. (ByteArrayOutputStream.))
15+
err# (System/err)]
16+
(System/setErr s#)
17+
(try
18+
~@body
19+
(finally
20+
(System/setErr err#)))))
721

822
(facts serializable?
923
(tabular
@@ -25,14 +39,14 @@
2539
(ring.util.test/string-input-stream "foobar") false false))
2640

2741
(facts "wrap-exceptions"
28-
(let [exception (proxy [RuntimeException] [] (printStackTrace []))
29-
exception-class (.getName (.getClass exception))
30-
failure (fn [_] (throw exception))
31-
success (fn [_] (ok "SUCCESS"))
32-
request irrelevant]
42+
(with-out-str
43+
(without-err
44+
(let [exception (RuntimeException. "kosh")
45+
exception-class (.getName (.getClass exception))
46+
failure (fn [_] (throw exception))]
3347

34-
(fact "converts exceptions into safe internal server errors"
35-
((wrap-exceptions failure (:handlers (:exceptions api-middleware-defaults))) request)
36-
=> (contains {:status status/internal-server-error
37-
:body (contains {:class exception-class
38-
:type "unknown-exception"})}))))
48+
(fact "converts exceptions into safe internal server errors"
49+
((wrap-exceptions failure (:handlers (:exceptions api-middleware-defaults))) ..request..)
50+
=> (contains {:status status/internal-server-error
51+
:body (contains {:class exception-class
52+
:type "unknown-exception"})}))))))

0 commit comments

Comments
 (0)