Improved eexception-handler to provide more contextual info

This commit is contained in:
Julien Eluard 2017-09-05 15:14:27 +02:00 committed by Roman Volosovskyi
parent 2fc6854543
commit c3f38249e5
4 changed files with 64 additions and 22 deletions

View File

@ -9,7 +9,7 @@
[status-im.ui.screens.views :as views]
[status-im.components.react :as react]
[status-im.components.status :as status]
[status-im.utils.utils :as utils]))
[status-im.utils.error-handler :as error-handler]))
(defn init-back-button-handler! []
(let [new-listener (fn []
@ -70,7 +70,7 @@
:reagent-render views/main})))
(defn init []
(utils/register-exception-handler)
(error-handler/register-exception-handler!)
(status/call-module status/init-jail)
(.registerComponent react/app-registry "StatusIm" #(reagent/reactify-component app-root))
(status/set-soft-input-mode status/adjust-resize)

View File

@ -9,7 +9,7 @@
[status-im.ui.screens.views :as views]
[status-im.components.react :as react]
[status-im.components.status :as status]
[status-im.utils.utils :as utils]))
[status-im.utils.error-handler :as error-handler]))
(defn orientation->keyword [o]
(keyword (.toLowerCase o)))
@ -44,7 +44,7 @@
:reagent-render views/main})))
(defn init []
(utils/register-exception-handler)
(error-handler/register-exception-handler!)
(status/call-module status/init-jail)
(.registerComponent react/app-registry "StatusIm" #(reagent/reactify-component app-root))
(dispatch-sync [:initialize-app]))

View File

@ -0,0 +1,57 @@
(ns status-im.utils.error-handler
(:require [clojure.string :as string]
[status-im.utils.utils :as utils]))
;; Error handling code based on https://gist.github.com/pesterhazy/e6846be1b6712a9038537022d131ce46
(defonce !handler-set (atom false))
(defn downgrade-reagent-errors!
"Downgrade reagent error to warning
Reagent uses console.error to notify the user that an exception occurs while
rendering. Unfortunately, react-native can only show one RedBox at a time and
discards all subsequent ones. This obscures the actual exception. By
downgrading the first screen to a warning, the second screen is actually shown
to the user."
[]
(when-not @!handler-set
(reset! !handler-set true)
(let [original-error (.-error js/console)]
(set! (.-error js/console)
(fn [& [head :as args]]
(if (and (string? head) (string/starts-with? head "Error rendering component"))
(apply (.-warn js/console) "Additional exception info:" args)
(apply original-error args)))))))
(defn format-error [e]
(if (instance? js/Error e)
{:name (.-name e) :message (.-message e) :stack (.-stack e)}
{:message (pr-str e)}))
(defn handle-error [e is-fatal]
(let [f (format-error e)]
(js/console.log (str "PRETTY PRINTED EXCEPTION"
"\n\n***\nNAME: "
(pr-str (:name f))
"\nMESSAGE: "
(:message f)
"\n\n"
(:stack f)
"\n\n***"))))
(defonce !error-handler-set? (atom false))
(defn register-exception-handler!
"Improve error messages printed to console.
When js/goog.DEBUG is false, show a popup with an error summary; else rely on default `red` screen."
[]
(downgrade-reagent-errors!)
(when-not @!error-handler-set?
(reset! !error-handler-set? true)
(let [orig-handler (some-> js/ErrorUtils .-getGlobalHandler (.call))]
(js/ErrorUtils.setGlobalHandler
(fn [e isFatal]
(handle-error e isFatal)
(if js/goog.DEBUG
(some-> orig-handler (.call nil e isFatal))
(utils/show-popup "Error" (.-message e))))))))

View File

@ -1,7 +1,6 @@
(ns status-im.utils.utils
(:require [status-im.constants :as const]
[status-im.i18n :refer [label]]
[reagent.core :as r]
[status-im.i18n :as i18n]
[clojure.string :as str]
[taoensso.timbre :as log]
[status-im.react-native.js-dependencies :as rn-dependencies]))
@ -22,7 +21,7 @@
content
;; Styles are only relevant on iOS. On Android first button is 'neutral' and second is 'positive'
(clj->js
(vector (merge {:text (label :t/cancel) :style "cancel"}
(vector (merge {:text (i18n/label :t/cancel) :style "cancel"}
(when on-cancel {:onPress on-cancel}))
{:text (or s "OK") :onPress on-accept :style "destructive"})))))
@ -115,17 +114,3 @@
(if (contains? m k)
(apply update m k f args)
m))
(defn default-alert-handler
[error fatal?]
(show-popup "Error" (.-message error)))
(defn register-exception-handler
"Register a function that will be called for each exception thrown.
When `dev?` is true, always register; otherwise only register when goog.DEBUG is false.
Default function shows error details in an alert box."
([] (register-exception-handler default-alert-handler))
([f] (register-exception-handler true f))
([dev? f]
(if (and dev? (not js/goog.DEBUG))
(.setGlobalHandler js/ErrorUtils f dev?))))