Skip to content

Commit db04e5e

Browse files
Merge pull request #134 from mping/async-mw-support
Support async middleware for ring async servers
2 parents 2433412 + 1b05239 commit db04e5e

File tree

3 files changed

+109
-47
lines changed

3 files changed

+109
-47
lines changed

Diff for: metrics-clojure-ring/src/metrics/ring/expose.clj

+38-15
Original file line numberDiff line numberDiff line change
@@ -114,18 +114,31 @@
114114
(into {} (map #(render-metric % unit-context) (->> registry
115115
(all-metrics)
116116
(filter-metrics filter))))))
117-
118-
(defn serve-metrics
119-
([request]
120-
(serve-metrics request default-registry))
121-
([request registry]
122-
(serve-metrics request registry false))
117+
(defn- serve-metrics*
123118
([request registry {:keys [pretty-print? filter rate-unit duration-unit]}]
124119
(let [metrics-map (render-metrics registry filter (unit/build-options rate-unit duration-unit))
125120
json (generate-string metrics-map {:pretty pretty-print?})]
126121
(-> (response json)
127122
(header "Content-Type" "application/json")))))
128123

124+
(defn serve-metrics
125+
([request]
126+
(let [^String filter (get-in request [:params :filter])]
127+
(serve-metrics* request default-registry {:pretty-print? false
128+
:filter filter
129+
:rate-unit TimeUnit/SECONDS
130+
:duration-unit TimeUnit/NANOSECONDS})))
131+
([request respond raise]
132+
(let [^String filter (get-in request [:params :filter])]
133+
(try
134+
(respond
135+
(serve-metrics* request default-registry {:pretty-print? false
136+
:filter filter
137+
:rate-unit TimeUnit/SECONDS
138+
:duration-unit TimeUnit/NANOSECONDS}))
139+
(catch Exception e (raise e))))))
140+
141+
129142
(defn expose-metrics-as-json
130143
([handler]
131144
(expose-metrics-as-json handler "/metrics"))
@@ -134,12 +147,22 @@
134147
([handler uri registry]
135148
(expose-metrics-as-json handler uri registry {:pretty-print? false}))
136149
([handler uri registry opts]
137-
(fn [request]
138-
(let [^String request-uri (:uri request)
139-
^String filter (get-in request [:params :filter])]
140-
(if (or (.startsWith request-uri (sanitize-uri uri))
141-
(= request-uri uri))
142-
(serve-metrics request registry (merge {:filter filter
143-
:rate-unit TimeUnit/SECONDS
144-
:duration-unit TimeUnit/NANOSECONDS} opts))
145-
(handler request))))))
150+
(fn
151+
([request]
152+
(let [^String request-uri (:uri request)
153+
^String filter (get-in request [:params :filter])]
154+
(if (or (.startsWith request-uri (sanitize-uri uri))
155+
(= request-uri uri))
156+
(serve-metrics* request registry (merge {:filter filter
157+
:rate-unit TimeUnit/SECONDS
158+
:duration-unit TimeUnit/NANOSECONDS} opts))
159+
(handler request))))
160+
([request respond raise]
161+
(let [^String request-uri (:uri request)
162+
^String filter (get-in request [:params :filter])]
163+
(if (or (.startsWith request-uri (sanitize-uri uri))
164+
(= request-uri uri))
165+
(serve-metrics* request registry (merge {:filter filter
166+
:rate-unit TimeUnit/SECONDS
167+
:duration-unit TimeUnit/NANOSECONDS} opts))
168+
(handler request respond raise)))))))

Diff for: metrics-clojure-ring/src/metrics/ring/instrument.clj

+44-27
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
(:require [metrics.core :refer [default-registry]]
33
[metrics.counters :refer (counter inc! dec!)]
44
[metrics.meters :refer (meter mark!)]
5-
[metrics.timers :refer (timer time!)]
5+
[metrics.timers :refer (timer time! start stop)]
66
[clojure.string :as string])
77
(:import [com.codahale.metrics MetricRegistry]))
88

@@ -51,23 +51,31 @@
5151
:times times
5252
:request-methods request-methods}))
5353

54-
(defn handle-request [handler metrics request]
55-
(let [{:keys [active-requests requests responses
56-
schemes statuses times request-methods]} metrics]
57-
(inc! active-requests)
58-
(try
59-
(let [request-method (:request-method request)
60-
request-scheme (:scheme request)]
61-
(mark! requests)
62-
(mark-in! request-methods request-method)
63-
(mark-in! schemes request-scheme)
64-
(let [resp (time! (times request-method (times :other))
65-
(handler request))
66-
^{:tag "int"} status-code (or (:status resp) 404)]
67-
(mark! responses)
68-
(mark-in! statuses (int (/ status-code 100)))
69-
resp))
70-
(finally (dec! active-requests)))))
54+
(defn- time-request [thunk metrics request]
55+
(let [{:keys [active-requests requests responses
56+
schemes statuses times request-methods]} metrics]
57+
(inc! active-requests)
58+
(try
59+
(let [request-method (:request-method request)
60+
request-scheme (:scheme request)]
61+
(mark! requests)
62+
(mark-in! request-methods request-method)
63+
(mark-in! schemes request-scheme)
64+
(let [resp (time! (times request-method (times :other))
65+
(thunk))
66+
^{:tag "int"} status-code (or (:status resp) 404)]
67+
(mark! responses)
68+
(mark-in! statuses (int (/ status-code 100)))
69+
resp))
70+
(finally (dec! active-requests)))))
71+
72+
(defn handle-request
73+
([handler metrics request]
74+
(time-request #(handler request) metrics request))
75+
([handler metrics request respond raise]
76+
(try
77+
(time-request #(handler request respond raise) metrics request)
78+
(catch Exception e (raise e)))))
7179

7280
(defn metrics-for
7381
[metrics-db prefix registry]
@@ -87,10 +95,15 @@
8795
([handler]
8896
(instrument handler default-registry))
8997
([handler ^MetricRegistry reg]
90-
(fn [request]
91-
(handle-request handler
92-
(ring-metrics reg {:prefix []})
93-
request))))
98+
(fn
99+
([request]
100+
(handle-request handler
101+
(ring-metrics reg {:prefix []})
102+
request))
103+
([request respond raise]
104+
(handle-request handler
105+
(ring-metrics reg {:prefix []})
106+
request respond raise)))))
94107

95108
(defn instrument-by
96109
"Instrument a ring handler using the metrics returned by the `metrics-for`
@@ -107,8 +120,12 @@
107120
(instrument-by handler default-registry metrics-prefix))
108121
([handler ^MetricRegistry reg metrics-prefix]
109122
(let [metrics-db (atom {})]
110-
(fn [request]
111-
(let [prefix (metrics-prefix request)]
112-
(handle-request handler
113-
(metrics-for metrics-db prefix reg)
114-
request))))))
123+
(fn
124+
([request]
125+
(handle-request handler
126+
(metrics-for metrics-db (metrics-prefix request) reg)
127+
request))
128+
([request respond raise]
129+
(handle-request handler
130+
(metrics-for metrics-db (metrics-prefix request) reg)
131+
request respond raise))))))

Diff for: metrics-clojure-ring/test/metrics/test/instrument_test.clj

+27-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
(def dummy-handler (fn [req]
99
req))
1010

11+
(def dummy-handler-async (fn [req respond raise]
12+
(respond req)))
13+
1114
(defn tracked? [^MetricRegistry reg metric]
1215
(->> (.getMetrics reg)
1316
(map (fn [[k v]] k))
@@ -54,6 +57,15 @@
5457

5558
(app (mock/request :get "/yolo" {}))
5659

60+
(doseq [m expected-metrics]
61+
(is (tracked? reg m)))))
62+
63+
(testing "instrument without custom prefix and async handler"
64+
(let [reg (MetricRegistry. )
65+
app (instrument dummy-handler-async reg)]
66+
67+
(app (mock/request :get "/yolo" {}) identity identity)
68+
5769
(doseq [m expected-metrics]
5870
(is (tracked? reg m))))))
5971

@@ -64,10 +76,20 @@
6476
(uri-prefix (mock/request :get "/foo/bar/baz")))))
6577

6678
(deftest test-instrument-by-uri-prefix
67-
(let [reg (MetricRegistry.)
68-
app (instrument-by dummy-handler reg uri-prefix)]
79+
(testing "instrument by uri prefix"
80+
(let [reg (MetricRegistry.)
81+
app (instrument-by dummy-handler reg uri-prefix)]
6982

70-
(app (mock/request :get "/yolo" {}))
83+
(app (mock/request :get "/yolo" {}))
84+
85+
(doseq [m expected-metrics]
86+
(is (tracked? reg (str "yolo." m))))))
7187

72-
(doseq [m expected-metrics]
73-
(is (tracked? reg (str "yolo." m))))))
88+
(testing "instrument by uri prefix and async handler"
89+
(let [reg (MetricRegistry.)
90+
app (instrument-by dummy-handler-async reg uri-prefix)]
91+
92+
(app (mock/request :get "/yolo" {}) identity identity)
93+
94+
(doseq [m expected-metrics]
95+
(is (tracked? reg (str "yolo." m)))))))

0 commit comments

Comments
 (0)