Fork me on GitHub
#ring
<
2017-11-15
>
lucian30322:11:55

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"}))))

zignd22:11:07

@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

lucian30322:11:00

@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"))

zignd22:11:35

@lucian303 in this case I'd check the order in which you're registering your wrappers, can you post it?

lucian30322:11:17

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))

zignd23:11:15

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 issue

lucian30323:11:41

you'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)

lucian30323:11:07

but yeah, it's not the issue

zignd23:11:39

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"}))))

zignd23:11:45

@lucian303 do your request reaches that point i indicated in the snippet above?

zignd23:11:53

cause, maybe it's not a problem with the error handling, but something related to the other wrappers

zignd23:11:34

@lucian303 does the sentry wrapper attempts to catch exceptions?

lucian30323:11:31

@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

lucian30323:11:54

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))))))

zignd23:11:51

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