i'm trying to set up ring middleware to log all exceptions, but i can't seem to trigger the catch block in my middleware handler. any ideas?
(defn wrap-exception-handler [handler]
(fn [request]
(try (handler request)
(catch Exception e
(println "logged error")
(timbre/error e)
{:status 500 :body "An error occurred"}))))
@lucian303 I have a wrapper to handle exceptions just like yours in my current project and it works. But there's one thing that it's worth looking into, the thing trowing inherits from Error
or Exception
? there's a difference in those two types of errors in Java and the ones inheriting from Error
will not be caught in a catch
for Exception
@zignd i have defined a route with the below throw statement for testing. it's just a regular Exception ... i also tried modifying the handler to take a Throwable, but it won't catch the exception:
(throw (Exception. "An error has occurred"))
@lucian303 in this case I'd check the order in which you're registering your wrappers, can you post it?
sure. i've tried it as both the first and last handlers in the chain below. also without the wrap-defaults
:
(defn wrap-base [handler]
(-> ((:middleware defaults) handler)
(wrap-sentry (environ/env :sentry-url) ["api-proxy"])
(wrap-defaults
(-> api-defaults
(assoc-in [:security :anti-forgery] false)
(dissoc :session)))
wrap-exception-handler))
i'm kind of confused here, i'm still kind of beginner, but
(-> api-defaults
(assoc-in [:security :anti-forgery] false)
(dissoc :session))
works as expected? because api-defaults
from ring.middleware.defaults
doesn't seem to have :session
key. but still, i don't think this would be the issueyou're right about that. that was left over from when the app was using site-defaults
i've changed that call to simply (wrap-defaults api-defaults)
but yeah, it's not the issue
i wonder if it even gets called:
(defn wrap-exception-handler [handler]
(fn [request]
(println "called") ; <----- here
(try (handler request)
(catch Exception e
(println "logged error")
(timbre/error e)
{:status 500 :body "An error occurred"}))))
@lucian303 do your request reaches that point i indicated in the snippet above?
cause, maybe it's not a problem with the error handling, but something related to the other wrappers
@lucian303 does the sentry wrapper attempts to catch exceptions?
@zignd yes, the handler is called, it's just that the exception is never caught. the sentry handler does catch exceptions but rethrows them. i've actually removed the other handlers including wrap-defaults
but it still won't catch exceptions
the wrap-sentry
handler seems to actually be very similar to mine, but it is also not working (which is why i'm trying to write my own). very strange ...
(defn wrap-sentry [handler dsn & [opts]]
(fn [req]
(let [alter-fn (or (:http-alter-fn opts)
identity)]
(try
(handler req)
(catch Exception e
(capture-error dsn req e (:extra opts) (:namespaces opts) alter-fn)
(throw e))
(catch AssertionError e
(capture-error dsn req e (:extra opts) (:namespaces opts) alter-fn)
(throw e))))))
that's weird, my last bet would be on the handler returned from this call ((:middleware defaults) handler)
, maybe there's something in it worth investigating