Skip to content

Commit 0134b71

Browse files
committed
Merge pull request #176 from metosin/clojure.tools.logging
Clojure.tools.logging
2 parents ccd501c + 942e42d commit 0134b71

File tree

5 files changed

+56
-17
lines changed

5 files changed

+56
-17
lines changed

CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
## 0.24.1-SNAPSHOT
22

3-
* Fixes [#159](https://github.com/metosin/compojure-api/issues/159)
4-
* allow any swagger data to be overriden either via swagger-docs or via middlewares, fixes
5-
[#170](https://github.com/metosin/compojure-api/issues/170).
3+
* `clojure.tools.logging` is used with default uncaugt exception handling if it's found
4+
on the classpath. Fixes [#172](https://github.com/metosin/compojure-api/issues/172).
5+
* Both `api` and `defapi` produce identical swagger-docs. Fixes [#159](https://github.com/metosin/compojure-api/issues/159)
6+
* allow any swagger data to be overriden at runtime either via swagger-docs or via middlewares. Fixes [#170](https://github.com/metosin/compojure-api/issues/170).
67

78
```clojure
89
[prismatic/plumbing "0.5.2] is available but we use "0.5.1"

project.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@
4343
:reload-paths ["src" "examples/src"]}
4444
:source-paths ["examples/src" "examples/dev-src"]
4545
:main examples.server}
46+
:logging {:dependencies [[org.clojure/tools.logging "0.3.1"]]}
4647
:1.8 {:dependencies [[org.clojure/clojure "1.8.0-RC2"]]}}
4748
:eastwood {:namespaces [:source-paths]
4849
:add-linters [:unused-namespaces]}
4950
:codeina {:sources ["src"]
5051
:target "gh-pages/doc"
5152
:src-dir-uri "http://github.com/metosin/compojure-api/blob/master/"
5253
:src-linenum-anchor-prefix "L"}
53-
:aliases {"all" ["with-profile" "dev:dev,1.8"]
54+
:aliases {"all" ["with-profile" "dev:dev,logging:dev,1.8"]
5455
"start-thingie" ["run"]
5556
"aot-uberjar" ["with-profile" "uberjar" "do" "clean," "ring" "uberjar"]
5657
"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.impl.logging :as logging]
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+
(logging/log! :error e (.getMessage e))
2021
(internal-server-error {:type "unknown-exception"
2122
:class (.getName (.getClass e))}))
2223

src/compojure/api/impl/logging.clj

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
(ns ^:no-doc compojure.api.impl.logging
2+
"Internal Compojure-api logging utility"
3+
(:require [clojure.string :as str]))
4+
5+
;; Cursive-users
6+
(declare log!)
7+
8+
;; use c.t.l logging if available, default to console logging
9+
(if (find-ns 'clojure.tools.logging)
10+
(eval
11+
`(do
12+
(require 'clojure.tools.logging)
13+
(defmacro ~'log! [& ~'args]
14+
`(do
15+
(clojure.tools.logging/log ~@~'args)))))
16+
(let [log (fn [level more] (println (.toUpperCase (name level)) (str/join " " more)))]
17+
(defn log! [level x & more]
18+
(if (instance? Throwable x)
19+
(do
20+
(log level more)
21+
(.printStackTrace x))
22+
(log level (into [x] more))))))

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)