Improve error reporting of tasks.

This commit is contained in:
Andrey Antukh 2021-02-03 17:00:35 +01:00 committed by Hirunatan
parent 816db29f9c
commit 80309cbff3
5 changed files with 50 additions and 27 deletions

View file

@ -16,6 +16,7 @@
[app.http.errors :as errors] [app.http.errors :as errors]
[app.http.middleware :as middleware] [app.http.middleware :as middleware]
[app.metrics :as mtx] [app.metrics :as mtx]
[app.util.log4j :refer [update-thread-context!]]
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[integrant.core :as ig] [integrant.core :as ig]
@ -103,7 +104,7 @@
(catch Throwable e (catch Throwable e
(try (try
(let [cdata (errors/get-error-context request e)] (let [cdata (errors/get-error-context request e)]
(errors/update-thread-context! cdata) (update-thread-context! cdata)
(log/errorf e "Unhandled exception: %s (id: %s)" (ex-message e) (str (:id cdata))) (log/errorf e "Unhandled exception: %s (id: %s)" (ex-message e) (str (:id cdata)))
{:status 500 {:status 500
:body "internal server error"}) :body "internal server error"})

View file

@ -12,6 +12,7 @@
(:require (:require
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cfg] [app.config :as cfg]
[app.util.log4j :refer [update-thread-context!]]
[clojure.pprint :refer [pprint]] [clojure.pprint :refer [pprint]]
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[cuerdas.core :as str] [cuerdas.core :as str]
@ -19,19 +20,6 @@
(:import (:import
org.apache.logging.log4j.ThreadContext)) org.apache.logging.log4j.ThreadContext))
(defn update-thread-context!
[data]
(run! (fn [[key val]]
(ThreadContext/put
(name key)
(cond
(coll? val)
(binding [clojure.pprint/*print-right-margin* 120]
(with-out-str (pprint val)))
(instance? clojure.lang.Named val) (name val)
:else (str val))))
data))
(defn- explain-error (defn- explain-error
[error] [error]
(with-out-str (with-out-str
@ -48,10 +36,8 @@
:version (:full cfg/version) :version (:full cfg/version)
:host (:public-uri cfg/config) :host (:public-uri cfg/config)
:class (.getCanonicalName ^java.lang.Class (class error)) :class (.getCanonicalName ^java.lang.Class (class error))
:hint (ex-message error)} :hint (ex-message error)
:data edata}
(when (map? edata)
edata)
(when (and (map? edata) (:data edata)) (when (and (map? edata) (:data edata))
{:explain (explain-error edata)})))) {:explain (explain-error edata)}))))

View file

@ -10,7 +10,7 @@
(ns app.http.session (ns app.http.session
(:require (:require
[app.db :as db] [app.db :as db]
[app.http.errors :refer [update-thread-context!]] [app.util.log4j :refer [update-thread-context!]]
[buddy.core.codecs :as bc] [buddy.core.codecs :as bc]
[buddy.core.nonce :as bn] [buddy.core.nonce :as bn]
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]

View file

@ -0,0 +1,28 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2021 UXBOX Labs SL
(ns app.util.log4j
(:require
[clojure.pprint :refer [pprint]]
[clojure.tools.logging :as log])
(:import
org.apache.logging.log4j.ThreadContext))
(defn update-thread-context!
[data]
(run! (fn [[key val]]
(ThreadContext/put
(name key)
(cond
(coll? val)
(binding [clojure.pprint/*print-right-margin* 120]
(with-out-str (pprint val)))
(instance? clojure.lang.Named val) (name val)
:else (str val))))
data))

View file

@ -10,11 +10,13 @@
(ns app.worker (ns app.worker
"Async tasks abstraction (impl)." "Async tasks abstraction (impl)."
(:require (:require
[app.config :as cfg]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.db :as db] [app.db :as db]
[app.util.async :as aa] [app.util.async :as aa]
[app.util.time :as dt] [app.util.time :as dt]
[app.util.log4j :refer [update-thread-context!]]
[clojure.core.async :as a] [clojure.core.async :as a]
[clojure.pprint :refer [pprint]] [clojure.pprint :refer [pprint]]
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
@ -205,6 +207,17 @@
(log/warn "no task handler found for" (pr-str name))) (log/warn "no task handler found for" (pr-str name)))
{:status :completed :task item})) {:status :completed :task item}))
(defn get-error-context
[error item]
(let [edata (ex-data error)]
{:id (uuid/next)
:version (:full cfg/version)
:host (:public-uri cfg/config)
:class (.getCanonicalName ^java.lang.Class (class error))
:hint (ex-message error)
:data edata
:params item}))
(defn- handle-exception (defn- handle-exception
[error item] [error item]
(let [edata (ex-data error)] (let [edata (ex-data error)]
@ -218,14 +231,9 @@
(= ::noop (:strategy edata)) (= ::noop (:strategy edata))
(assoc :inc-by 0)) (assoc :inc-by 0))
(do (let [cdata (get-error-context error item)]
(log/errorf error (update-thread-context! cdata)
(str "Unhandled exception.\n" (log/errorf error "Unhandled exception on task (id: %s)" (:id cdata))
"=> task: " (:name item) "\n"
"=> retry: " (:retry-num item) "\n"
"=> props: \n"
(with-out-str
(pprint (:props item)))))
(if (>= (:retry-num item) (:max-retries item)) (if (>= (:retry-num item) (:max-retries item))
{:status :failed :task item :error error} {:status :failed :task item :error error}
{:status :retry :task item :error error}))))) {:status :retry :task item :error error})))))