Improve performance on error formating and reporting

This commit is contained in:
Andrey Antukh 2023-11-27 09:50:47 +01:00
parent c64e14859c
commit 2295d085d3
9 changed files with 56 additions and 69 deletions

View file

@ -9,7 +9,7 @@
(:require (:require
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.logging :as l] [app.common.logging :as l]
[app.common.schema :as sm] [app.common.schema :as-alias sm]
[app.config :as cf] [app.config :as cf]
[app.http :as-alias http] [app.http :as-alias http]
[app.http.access-token :as-alias actoken] [app.http.access-token :as-alias actoken]
@ -79,29 +79,15 @@
[err request parent-cause] [err request parent-cause]
(let [{:keys [code] :as data} (ex-data err)] (let [{:keys [code] :as data} (ex-data err)]
(cond (cond
(= code :spec-validation) (or (= code :spec-validation)
(= code :params-validation)
(= code :data-validation))
(let [explain (ex/explain data)] (let [explain (ex/explain data)]
{::rres/status 400 {::rres/status 400
::rres/body (-> data ::rres/body (-> data
(dissoc ::s/problems ::s/value ::s/spec) (dissoc ::s/problems ::s/value ::s/spec ::sm/explain)
(cond-> explain (assoc :explain explain)))}) (cond-> explain (assoc :explain explain)))})
(= code :params-validation)
(let [explain (::sm/explain data)
explain (sm/humanize-data explain)]
{::rres/status 400
::rres/body (-> data
(dissoc ::sm/explain)
(assoc :explain explain))})
(= code :data-validation)
(let [explain (::sm/explain data)
explain (sm/humanize-data explain)]
{::rres/status 400
::rres/body (-> data
(dissoc ::sm/explain)
(assoc :explain explain))})
(= code :request-body-too-large) (= code :request-body-too-large)
{::rres/status 413 ::rres/body data} {::rres/status 413 ::rres/body data}

View file

@ -56,22 +56,22 @@
(dissoc :request/params :value :params :data))] (dissoc :request/params :value :params :data))]
(merge (merge
{:context (-> (into (sorted-map) ctx) {:context (-> (into (sorted-map) ctx)
(pp/pprint-str :width 200 :length 50 :level 10)) (pp/pprint-str :length 50))
:props (pp/pprint-str props :width 200 :length 50) :props (pp/pprint-str props :length 50)
:hint (or (ex-message cause) @message) :hint (or (ex-message cause) @message)
:trace (or (::trace record) :trace (or (::trace record)
(ex/format-throwable cause :data? false :explain? false :header? false :summary? false))} (ex/format-throwable cause :data? false :explain? false :header? false :summary? false))}
(when-let [params (or (:request/params context) (:params context))] (when-let [params (or (:request/params context) (:params context))]
{:params (pp/pprint-str params :width 200 :length 50 :level 10)}) {:params (pp/pprint-str params :length 30 :level 12)})
(when-let [value (:value context)] (when-let [value (:value context)]
{:value (pp/pprint-str value :width 200 :length 50 :level 10)}) {:value (pp/pprint-str value :length 30 :level 12)})
(when-let [data (some-> data (dissoc ::s/problems ::s/value ::s/spec ::sm/explain :hint))] (when-let [data (some-> data (dissoc ::s/problems ::s/value ::s/spec ::sm/explain :hint))]
{:data (pp/pprint-str data :width 200)}) {:data (pp/pprint-str data :length 30 :level 12)})
(when-let [explain (ex/explain data {:level 8 :length 20})] (when-let [explain (ex/explain data :length 30 :level 12)]
{:explain explain}))))) {:explain explain})))))
(defn error-record? (defn error-record?
@ -96,11 +96,11 @@
(defmethod ig/init-key ::reporter (defmethod ig/init-key ::reporter
[_ cfg] [_ cfg]
(let [input (sp/chan :buf (sp/sliding-buffer 32) (let [input (sp/chan :buf (sp/sliding-buffer 64)
:xf (filter error-record?))] :xf (filter error-record?))]
(add-watch l/log-record ::reporter #(sp/put! input %4)) (add-watch l/log-record ::reporter #(sp/put! input %4))
(px/thread {:name "penpot/database-reporter" :virtual true} (px/thread {:name "penpot/database-reporter"}
(l/info :hint "initializing database error persistence") (l/info :hint "initializing database error persistence")
(try (try
(loop [] (loop []

View file

@ -429,11 +429,11 @@
(= :params-validation (:code data)) (= :params-validation (:code data))
(app.common.pprint/pprint (app.common.pprint/pprint
(sm/humanize-data (::sm/explain data))) (sm/humanize-explain (::sm/explain data)))
(= :data-validation (:code data)) (= :data-validation (:code data))
(app.common.pprint/pprint (app.common.pprint/pprint
(sm/humanize-data (::sm/explain data))) (sm/humanize-explain (::sm/explain data)))
(= :service-error (:type data)) (= :service-error (:type data))
(print-error! (.getCause ^Throwable error)) (print-error! (.getCause ^Throwable error))

View file

@ -48,6 +48,10 @@
;; exception printing ;; exception printing
fipp/fipp {:mvn/version "0.6.26"} fipp/fipp {:mvn/version "0.6.26"}
io.github.eerohele/pp
{:git/tag "2023-11-25.47"
:git/sha "15d572c"}
io.aviso/pretty {:mvn/version "1.4.4"} io.aviso/pretty {:mvn/version "1.4.4"}
environ/environ {:mvn/version "1.2.0"}} environ/environ {:mvn/version "1.2.0"}}
:paths ["src" "vendor" "target/classes"] :paths ["src" "vendor" "target/classes"]

View file

@ -65,8 +65,7 @@
(instance? RuntimeException v))) (instance? RuntimeException v)))
(defn explain (defn explain
([data] (explain data nil)) [data & {:as opts}]
([data 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)
@ -81,7 +80,7 @@
(s/explain-out (update data ::s/problems #(take (:length opts 10) %))))) (s/explain-out (update data ::s/problems #(take (:length opts 10) %)))))
(contains? data ::sm/explain) (contains? data ::sm/explain)
(sm/humanize-data (::sm/explain data) opts)))) (sm/humanize-explain (::sm/explain data) opts)))
#?(:clj #?(:clj
(defn format-throwable (defn format-throwable
@ -92,8 +91,8 @@
data? true data? true
explain? true explain? true
chain? true chain? true
data-length 10 data-length 8
data-level 4}}] data-level 5}}]
(letfn [(print-trace-element [^StackTraceElement e] (letfn [(print-trace-element [^StackTraceElement e]
(let [class (.getClassName e) (let [class (.getClassName e)
@ -115,7 +114,7 @@
(print-data [data] (print-data [data]
(when (seq data) (when (seq data)
(print " dt: ") (print " dt: ")
(let [[line & lines] (str/lines (pp/pprint-str data :level data-level :length data-length ))] (let [[line & lines] (str/lines (pp/pprint-str data :level data-level :length data-length))]
(print line) (print line)
(newline) (newline)
(doseq [line lines] (doseq [line lines]

View file

@ -50,7 +50,7 @@
(when-not valid? (when-not valid?
(let [explain (sm/explain ::ch/change change)] (let [explain (sm/explain ::ch/change change)]
(pp/pprint (sm/humanize-data explain)) (pp/pprint (sm/humanize-explain explain))
(when fail-on-spec? (when fail-on-spec?
(ex/raise :type :assertion (ex/raise :type :assertion
:code :data-validation :code :data-validation

View file

@ -7,16 +7,16 @@
(ns app.common.pprint (ns app.common.pprint
(:refer-clojure :exclude [prn]) (:refer-clojure :exclude [prn])
(:require (:require
[fipp.edn :as fpp])) [me.flowthing.pp :as pp]))
(defn pprint-str
[expr & {:keys [width level length]
:or {width 110 level 8 length 25}}]
(binding [*print-level* level
*print-length* length]
(with-out-str
(fpp/pprint expr {:width width}))))
(defn pprint (defn pprint
[expr & {:keys [width level length]
:or {width 120 level 8 length 25}}]
(binding [*print-level* level
*print-length* length]
(pp/pprint expr {:max-width width})))
(defn pprint-str
[expr & {:as opts}] [expr & {:as opts}]
(println (pprint-str expr opts))) (with-out-str
(pprint expr opts)))

View file

@ -152,19 +152,18 @@
(let [vfn (delay (decoder (if (delay? s) (deref s) s) transformer))] (let [vfn (delay (decoder (if (delay? s) (deref s) s) transformer))]
(fn [v] (@vfn v)))) (fn [v] (@vfn v))))
(defn humanize-data (defn humanize-explain
[{:keys [schema errors value]} & {:keys [length level]}] [{:keys [schema errors value]} & {:keys [length level]}]
(let [errors (mapv #(update % :schema form) errors)] (let [errors (mapv #(update % :schema form) errors)]
(with-out-str (with-out-str
(println "Schema: ") (println "Schema: ")
(println (pp/pprint-str (form schema) {:level (d/nilv level 10) (println (pp/pprint-str (form schema) {:width 100 :level 15 :length 20}))
:length (d/nilv length 10)}))
(println "Errors:") (println "Errors:")
(println (pp/pprint-str errors {:level (d/nilv level 10) (println (pp/pprint-str errors {:width 100 :level 15 :length 20}))
:length (d/nilv length 10)}))
(println "Value:") (println "Value:")
(println (pp/pprint-str value {:level (d/nilv level 5) (println (pp/pprint-str value {:width 160
:length (d/nilv length 10)}))))) :level (d/nilv level 8)
:length (d/nilv length 12)})))))
(defn pretty-explain (defn pretty-explain
[s d] [s d]

View file

@ -9,7 +9,7 @@
(:require (:require
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.pprint :as pp] [app.common.pprint :as pp]
[app.common.schema :as sm] [app.common.schema :as-alias sm]
[app.main.data.messages :as msg] [app.main.data.messages :as msg]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.users :as du] [app.main.data.users :as du]
@ -33,9 +33,8 @@
(defn- print-explain! (defn- print-explain!
[data] [data]
(when-let [explain (::sm/explain data)] (when-let [explain (or (ex/explain data)
(js/console.log (sm/humanize-data explain))) (:explain data))]
(when-let [explain (:explain data)]
(js/console.log explain))) (js/console.log explain)))
(defn- print-trace! (defn- print-trace!