From ca02999ae9a5280efdada27da846e68f659fe886 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 1 Apr 2022 17:16:59 +0200 Subject: [PATCH] :sparkles: Improve error reporting --- backend/src/app/http/errors.clj | 25 +++++++++++++++++++----- backend/src/app/rpc.clj | 8 ++++++-- common/src/app/common/exceptions.cljc | 28 +++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/backend/src/app/http/errors.clj b/backend/src/app/http/errors.clj index fee8f2336..f7533306e 100644 --- a/backend/src/app/http/errors.clj +++ b/backend/src/app/http/errors.clj @@ -15,6 +15,8 @@ [yetti.request :as yrq] [yetti.response :as yrs])) +(def ^:dynamic *context* {}) + (defn- parse-client-ip [request] (or (some-> (yrq/get-header request "x-forwarded-for") (str/split ",") first) @@ -24,6 +26,7 @@ (defn get-context [request] (merge + *context* {:path (:path request) :method (:method request) :params (:params request) @@ -137,9 +140,21 @@ :code :unhandled :hint (ex-message error) :data edata}))))) + (defn handle - [error request] - (if (or (instance? java.util.concurrent.CompletionException error) - (instance? java.util.concurrent.ExecutionException error)) - (handle-exception (.getCause ^Throwable error) request) - (handle-exception error request))) + [cause request] + + (cond + (or (instance? java.util.concurrent.CompletionException cause) + (instance? java.util.concurrent.ExecutionException cause)) + (handle-exception (.getCause ^Throwable cause) request) + + + (ex/wrapped? cause) + (let [context (meta cause) + cause (deref cause)] + (binding [*context* context] + (handle-exception cause request))) + + :else + (handle-exception cause request))) diff --git a/backend/src/app/rpc.clj b/backend/src/app/rpc.clj index 3cdef422c..9e53af92e 100644 --- a/backend/src/app/rpc.clj +++ b/backend/src/app/rpc.clj @@ -59,7 +59,9 @@ (-> (method data) (p/then handle-response) (p/then respond) - (p/catch raise))))) + (p/catch (fn [cause] + (let [context {:profile-id profile-id}] + (raise (ex/wrap-with-context cause context))))))))) (defn- rpc-mutation-handler "Ring handler that dispatches mutation requests and convert between @@ -81,7 +83,9 @@ (-> (method data) (p/then handle-response) (p/then respond) - (p/catch raise))))) + (p/catch (fn [cause] + (let [context {:profile-id profile-id}] + (raise (ex/wrap-with-context cause context))))))))) (defn- wrap-metrics "Wrap service method with metrics measurement." diff --git a/common/src/app/common/exceptions.cljc b/common/src/app/common/exceptions.cljc index b3b73e5a9..d76f943e5 100644 --- a/common/src/app/common/exceptions.cljc +++ b/common/src/app/common/exceptions.cljc @@ -57,3 +57,31 @@ (defn exception? [v] (instance? #?(:clj java.lang.Throwable :cljs js/Error) v)) + + +#?(:cljs + (deftype WrappedException [cause meta] + cljs.core/IMeta + (-meta [_] meta) + + cljs.core/IDeref + (-deref [_] cause)) + :clj + (deftype WrappedException [cause meta] + clojure.lang.IMeta + (meta [_] meta) + + clojure.lang.IDeref + (deref [_] cause))) + + +(ns-unmap 'app.common.exceptions '->WrappedException) +(ns-unmap 'app.common.exceptions 'map->WrappedException) + +(defn wrapped? + [o] + (instance? WrappedException o)) + +(defn wrap-with-context + [cause context] + (WrappedException. cause context))