/
ring.clj
64 lines (56 loc) · 1.95 KB
/
ring.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
(ns sentry-clj.ring
"Ring utility functions."
(:require
[ring.util.request :refer [request-url]]
[ring.util.response :as response]
[sentry-clj.core :as sentry]))
(set! *warn-on-reflection* true)
(defn ^:private request->http
"Converts a Ring request into an HTTP interface for an event."
[req]
{:url (request-url req)
:method (-> req :request-method name)
:data (:params req)
:query-string (:query-string req "")
:headers (:headers req)
:env {:session (-> req :session pr-str)
"REMOTE_ADDR" (:remote-addr req)}})
(defn ^:private request->user
"Converts a Ring request into a User interface for an event."
[req]
{:ip-address (:remote-addr req)})
(defn ^:private request->event
"Given a request and an exception, returns a Sentry event."
[req e]
{:throwable e
:request (request->http req)
:user (request->user req)})
(defn ^:private default-error
"A very bare-bones error message. Ignores the request and exception."
[_ _]
(-> (str "<html><head><title>Error</title></head>"
"<body><p>Internal Server Error</p></body></html>")
(response/response)
(response/content-type "text/html")
(response/status 500)))
(defn wrap-report-exceptions
"Wraps the given handler in error reporting.
Optionally takes three functions:
* `:preprocess-fn`, which is passed the request
* `:postprocess-fn`, which is passed the request and the Sentry event
* `:error-fn`, which is passed the request and the thrown exception and returns an appropriate Ring response
"
[handler {:keys [preprocess-fn postprocess-fn error-fn]
:or {preprocess-fn identity
postprocess-fn (comp second list)
error-fn default-error}}]
(fn [req]
(try
(handler req)
(catch Throwable e
(-> req
preprocess-fn
(request->event e)
(->> (postprocess-fn req)
sentry/send-event))
(error-fn req e)))))