0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-22 22:49:01 -05:00

Add efficiency improvements to backend error reporting

This commit is contained in:
Andrey Antukh 2023-11-11 00:07:19 +01:00
parent 9d05e2260c
commit 3c64955b93
7 changed files with 63 additions and 29 deletions

View file

@ -88,11 +88,19 @@
(= code :params-validation) (= code :params-validation)
(let [explain (::sm/explain data) (let [explain (::sm/explain data)
payload (sm/humanize-data explain)] explain (sm/humanize-data explain)]
{::yrs/status 400 {::yrs/status 400
::yrs/body (-> data ::yrs/body (-> data
(dissoc ::sm/explain) (dissoc ::sm/explain)
(assoc :data payload))}) (assoc :explain explain))})
(= code :data-validation)
(let [explain (::sm/explain data)
explain (sm/humanize-data explain)]
{::yrs/status 400
::yrs/body (-> data
(dissoc ::sm/explain)
(assoc :explain explain))})
(= code :request-body-too-large) (= code :request-body-too-large)
{::yrs/status 413 ::yrs/body data} {::yrs/status 413 ::yrs/body data}
@ -114,18 +122,18 @@
(cond (cond
(= code :data-validation) (= code :data-validation)
(let [explain (::sm/explain data) (let [explain (::sm/explain data)
payload (sm/humanize-data explain)] explain (sm/humanize-data explain)]
(l/error :hint "data assertion error" :message (ex-message error) :cause cause) (l/error :hint "data assertion error" :cause cause)
{::yrs/status 500 {::yrs/status 500
::yrs/body {:type :server-error ::yrs/body {:type :server-error
:code :assertion :code :assertion
:data (-> data :data (-> data
(dissoc ::sm/explain) (dissoc ::sm/explain)
(assoc :data payload))}}) (assoc :explain explain))}})
(= code :spec-validation) (= code :spec-validation)
(let [explain (ex/explain data)] (let [explain (ex/explain data)]
(l/error :hint "spec assertion error" :message (ex-message error) :cause cause) (l/error :hint "spec assertion error" :cause cause)
{::yrs/status 500 {::yrs/status 500
::yrs/body {:type :server-error ::yrs/body {:type :server-error
:code :assertion :code :assertion
@ -135,7 +143,7 @@
:else :else
(do (do
(l/error :hint "assertion error" :message (ex-message error) :cause cause) (l/error :hint "assertion error" :cause cause)
{::yrs/status 500 {::yrs/status 500
::yrs/body {:type :server-error ::yrs/body {:type :server-error
:code :assertion :code :assertion
@ -150,7 +158,7 @@
[error request parent-cause] [error request parent-cause]
(binding [l/*context* (request->context request)] (binding [l/*context* (request->context request)]
(let [cause (or parent-cause error)] (let [cause (or parent-cause error)]
(l/error :hint "internal error" :message (ex-message error) :cause cause) (l/error :hint "internal error" :cause cause)
{::yrs/status 500 {::yrs/status 500
::yrs/body {:type :server-error ::yrs/body {:type :server-error
:code :unhandled :code :unhandled
@ -175,7 +183,7 @@
(let [state (.getSQLState ^java.sql.SQLException error) (let [state (.getSQLState ^java.sql.SQLException error)
cause (or parent-cause error)] cause (or parent-cause error)]
(binding [l/*context* (request->context request)] (binding [l/*context* (request->context request)]
(l/error :hint "PSQL error" :message (ex-message error) (l/error :hint "PSQL error"
:cause cause) :cause cause)
(cond (cond
(= state "57014") (= state "57014")
@ -205,7 +213,7 @@
;; This means that exception is not a controlled exception. ;; This means that exception is not a controlled exception.
(nil? edata) (nil? edata)
(binding [l/*context* (request->context request)] (binding [l/*context* (request->context request)]
(l/error :hint "unexpected error" :message (ex-message error) :cause cause) (l/error :hint "unexpected error" :cause cause)
{::yrs/status 500 {::yrs/status 500
::yrs/body {:type :server-error ::yrs/body {:type :server-error
:code :unexpected :code :unexpected
@ -213,7 +221,7 @@
:else :else
(binding [l/*context* (request->context request)] (binding [l/*context* (request->context request)]
(l/error :hint "unhandled error" :message (ex-message error) :cause cause) (l/error :hint "unhandled error" :cause cause)
{::yrs/status 500 {::yrs/status 500
::yrs/body {:type :server-error ::yrs/body {:type :server-error
:code :unhandled :code :unhandled

View file

@ -973,7 +973,6 @@
:import-id id :import-id id
:elapsed (dt/format-duration (tp)) :elapsed (dt/format-duration (tp))
:error? (some? @cs) :error? (some? @cs)
:cause @cs
))))) )))))
;; --- Command: export-binfile ;; --- Command: export-binfile

View file

@ -66,9 +66,9 @@
(defn explain (defn explain
([data] (explain data nil)) ([data] (explain data nil))
([data {:keys [level length] :or {level 8 length 10} :as opts}] ([data {:keys [level length] :or {level 8 length 12} :as opts}]
(cond (cond
;; ;; NOTE: a special case for spec validation errors on integrant ;; NOTE: a special case for spec validation errors on integrant
(and (= (:reason data) :integrant.core/build-failed-spec) (and (= (:reason data) :integrant.core/build-failed-spec)
(contains? data :explain)) (contains? data :explain))
(explain (:explain data) opts) (explain (:explain data) opts)
@ -81,8 +81,7 @@
(s/explain-out (update data ::s/problems #(take length %))))) (s/explain-out (update data ::s/problems #(take length %)))))
(contains? data ::sm/explain) (contains? data ::sm/explain)
(-> (sm/humanize-data (::sm/explain data)) (sm/humanize-data (::sm/explain data) :level level :length length))))
(pp/pprint-str {:level level :length length})))))
#?(:clj #?(:clj
(defn format-throwable (defn format-throwable

View file

@ -271,7 +271,7 @@
(js/console.error n (pr-str v)) (js/console.error n (pr-str v))
(js/console.error n v)))) (js/console.error n v))))
(when cause (when (ex/exception? cause)
(let [data (ex-data cause) (let [data (ex-data cause)
explain (ex/explain data)] explain (ex/explain data)]
(when explain (when explain

View file

@ -8,7 +8,9 @@
(:refer-clojure :exclude [deref merge parse-uuid]) (:refer-clojure :exclude [deref merge parse-uuid])
#?(:cljs (:require-macros [app.common.schema :refer [ignoring]])) #?(:cljs (:require-macros [app.common.schema :refer [ignoring]]))
(:require (:require
[app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.pprint :as pp]
[app.common.schema.generators :as sg] [app.common.schema.generators :as sg]
[app.common.schema.openapi :as-alias oapi] [app.common.schema.openapi :as-alias oapi]
[app.common.schema.registry :as sr] [app.common.schema.registry :as sr]
@ -142,10 +144,19 @@
(m/decoder s options transformer))) (m/decoder s options transformer)))
(defn humanize-data (defn humanize-data
[explain-data] [{:keys [schema errors value]} & {:keys [length level]}]
(-> explain-data (let [errors (mapv #(update % :schema form) errors)]
(update :schema form) (with-out-str
(update :errors (fn [errors] (map #(update % :schema form) errors))))) (println "Schema: ")
(println (pp/pprint-str (form schema)) {:level (d/nilv level 10)
:length (d/nilv length 10)})
(println)
(println "Errors:")
(println (pp/pprint-str errors {:level (d/nilv level 10)
:length (d/nilv length 10)}))
(println "Value:")
(println (pp/pprint-str value {:level (d/nilv level 5)
:length (d/nilv length 10)})))))
(defn pretty-explain (defn pretty-explain
[s d] [s d]
@ -191,7 +202,7 @@
(fn [v] (fn [v]
(let [result (v-fn v)] (let [result (v-fn v)]
(when (and (not result) (true? dm/*assert-context*)) (when (and (not result) (true? dm/*assert-context*))
(let [hint (str "schema assert: " (pr-str (form s))) (let [hint "schema validation"
exp (e-fn v)] exp (e-fn v)]
(throw (ex-info hint {:type :assertion (throw (ex-info hint {:type :assertion
:code :data-validation :code :data-validation
@ -204,7 +215,7 @@
[s v] [s v]
(let [result (validate s v)] (let [result (validate s v)]
(when (and (not result) (true? dm/*assert-context*)) (when (and (not result) (true? dm/*assert-context*))
(let [hint (str "schema assert: " (pr-str (form s))) (let [hint "schema validation"
exp (explain s v)] exp (explain s v)]
(throw (ex-info hint {:type :assertion (throw (ex-info hint {:type :assertion
:code :data-validation :code :data-validation

View file

@ -25,7 +25,7 @@
[data] [data]
(-> data (-> data
(dissoc ::sm/explain) (dissoc ::sm/explain)
(dissoc :hint) (dissoc :explain)
(dissoc ::trace) (dissoc ::trace)
(dissoc ::instance) (dissoc ::instance)
(pp/pprint {:width 70}))) (pp/pprint {:width 70})))
@ -33,8 +33,9 @@
(defn- print-explain! (defn- print-explain!
[data] [data]
(when-let [explain (::sm/explain data)] (when-let [explain (::sm/explain data)]
(-> (sm/humanize-data explain) (js/console.log (sm/humanize-data explain)))
(pp/pprint {:width 70})))) (when-let [explain (:explain data)]
(js/console.log explain)))
(defn- print-trace! (defn- print-trace!
[data] [data]
@ -98,7 +99,8 @@
(print-group! "Validation Error" (print-group! "Validation Error"
(fn [] (fn []
(print-data! error)))) (print-data! error)
(print-explain! error))))
;; This is a pure frontend error that can be caused by an active ;; This is a pure frontend error that can be caused by an active
@ -223,7 +225,22 @@
(print-group! "Server Error" (print-group! "Server Error"
(fn [] (fn []
(print-data! error)))) (print-data! (dissoc error :data))
(when-let [werror (:data error)]
(cond
(= :assertion (:type werror))
(print-group! "Assertion Error"
(fn []
(print-data! werror)
(print-explain! werror)))
:else
(print-group! "Unexpected"
(fn []
(print-data! werror)
(print-explain! werror))))))))
(defonce uncaught-error-handler (defonce uncaught-error-handler
(letfn [(is-ignorable-exception? [cause] (letfn [(is-ignorable-exception? [cause]

View file

@ -258,9 +258,9 @@
{:cmd :analyze-import {:cmd :analyze-import
:files files}) :files files})
(rx/delay-emit emit-delay) (rx/delay-emit emit-delay)
(rx/filter some?)
(rx/subs (rx/subs
(fn [{:keys [uri data error type] :as msg}] (fn [{:keys [uri data error type] :as msg}]
(log/debug :uri uri :data data :error error)
(if (some? error) (if (some? error)
(swap! state update :files set-analyze-error uri) (swap! state update :files set-analyze-error uri)
(swap! state update :files set-analyze-result uri type data))))))) (swap! state update :files set-analyze-result uri type data)))))))