Skip to content

Commit

Permalink
Add extra-labels to Ring collector
Browse files Browse the repository at this point in the history
  • Loading branch information
psalaberria002 committed Mar 30, 2017
1 parent ac7d028 commit 14e5790
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 53 deletions.
70 changes: 39 additions & 31 deletions src/iapetos/collector/ring.clj
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,28 @@
;; ## Initialization

(defn- make-latency-collector
[buckets]
(prometheus/histogram
:http/request-latency-seconds
{:description "the response latency for HTTP requests."
:labels [:method :status :statusClass :path]}))
([buckets extra-labels]
(prometheus/histogram
:http/request-latency-seconds
{:description "the response latency for HTTP requests."
:labels (concat [:method :status :statusClass :path] extra-labels)}))
([buckets]
(make-latency-collector buckets [])))

(defn- make-count-collector
[]
(prometheus/counter
:http/requests-total
{:description "the total number of HTTP requests processed."
:labels [:method :status :statusClass :path]}))
([extra-labels]
(prometheus/counter
:http/requests-total
{:description "the total number of HTTP requests processed."
:labels (concat [:method :status :statusClass :path] extra-labels)}))
([] (make-count-collector [])))

(defn- make-exception-collector
[]
(ex/exception-counter
:http/exceptions-total
{:description "the total number of exceptions encountered during HTTP processing."
:labels [:method :path]}))
([]
(ex/exception-counter
:http/exceptions-total
{:description "the total number of exceptions encountered during HTTP processing."
:labels [:method :path]})))

(defn initialize
"Initialize all collectors for Ring handler instrumentation. This includes:
Expand All @@ -56,12 +59,13 @@
- `http_exceptions_total`
"
[registry
& [{:keys [latency-histogram-buckets]
& [{:keys [latency-histogram-buckets
extra-labels]
:or {latency-histogram-buckets [0.001 0.005 0.01 0.02 0.05 0.1 0.2 0.3 0.5 0.75 1 5]}}]]
(prometheus/register
registry
(make-latency-collector latency-histogram-buckets)
(make-count-collector)
(make-latency-collector latency-histogram-buckets extra-labels)
(make-count-collector extra-labels)
(make-exception-collector)))

;; ## Response
Expand Down Expand Up @@ -94,30 +98,34 @@
(str status))

(defn- record-metrics!
[registry delta {:keys [request-method ::path]} response]
(let [labels {:method (-> request-method name string/upper-case)
:status (status response)
:statusClass (status-class response)
:path path}
[registry delta {:keys [request-method ::path] :as request} extra-labels-request extra-labels-response response]
(let [labels-request (select-keys request extra-labels-request)
labels-response (select-keys response extra-labels-response)
default-labels {:method (-> request-method name string/upper-case)
:status (status response)
:statusClass (status-class response)
:path path}
labels (merge default-labels labels-request labels-response)
delta-in-seconds (/ delta 1e9)]
(-> registry
(prometheus/inc :http/requests-total labels)
(prometheus/observe :http/request-latency-seconds labels delta-in-seconds))))

(defn- exception-counter-for
[registry {:keys [request-method ::path]}]
(let [labels {:method (-> request-method name string/upper-case)
[registry {:keys [request-method ::path] :as request} extra-labels-request]
(let [labels-request (select-keys request extra-labels-request)
labels {:method (-> request-method name string/upper-case)
:path path}]
(registry :http/exceptions-total labels)))

(defn- run-instrumented
[registry handler request]
(ex/with-exceptions (exception-counter-for registry request)
[registry handler extra-labels-request extra-labels-response request]
(ex/with-exceptions (exception-counter-for registry request extra-labels-request)
(let [start-time (System/nanoTime)
response (handler request)
delta (- (System/nanoTime) start-time)]
(->> (ensure-response-map response)
(record-metrics! registry delta request))
(record-metrics! registry delta request extra-labels-request extra-labels-response))
response)))

(defn wrap-instrumentation
Expand All @@ -134,10 +142,10 @@
the `:path` label) if you have any kind of ID in your URIs – since otherwise
there will be one timeseries created for each observed ID."
[handler registry
& [{:keys [path-fn] :or {path-fn :uri}}]]
& [{:keys [path-fn extra-labels-request extra-labels-response] :or {path-fn :uri}}]]
(fn [request]
(->> (assoc request ::path (path-fn request))
(run-instrumented registry handler))))
(run-instrumented registry handler extra-labels-request extra-labels-response))))

;; ### Metrics Endpoint

Expand Down Expand Up @@ -172,7 +180,7 @@
the `:path` label) if you have any kind of ID in your URIs – since otherwise
there will be one timeseries created for each observed ID."
[handler registry
& [{:keys [path path-fn on-request]
& [{:keys [path path-fn on-request extra-labels-request extra-labels-response]
:or {path "/metrics"
path-fn :uri}
:as options}]]
Expand Down
51 changes: 29 additions & 22 deletions test/iapetos/collector/ring_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,47 @@

(def gen-handler
(gen/one-of
[(->> (gen/elements
(concat
(range 200 205)
(range 300 308)
(range 400 429)
(range 500 505)))
(gen/fmap
(fn [status]
{:handler (constantly {:status status})
:exception? false
:labels {:status (str status)
:statusClass (str (quot status 100) "XX")}})))
[(gen/let [status (gen/elements
(concat
(range 200 205)
(range 300 308)
(range 400 429)
(range 500 505)))
extra-field-in-response gen/string-alpha-numeric]
(gen/return
{:handler (constantly {:status status :extra-field-in-response extra-field-in-response})
:exception? false
:labels {:status (str status)
:statusClass (str (quot status 100) "XX")
:extra-field-in-response extra-field-in-response}}))
(gen/return
{:handler (fn [_] (throw (Exception.)))
:exception? true})]))

(def gen-request
(gen/let [path (gen/fmap #(str "/" %) gen/string-alpha-numeric)
method (gen/elements [:get :post :put :delete :patch :options :head])]
(gen/let [path (gen/fmap #(str "/" %) gen/string-alpha-numeric)
method (gen/elements [:get :post :put :delete :patch :options :head])
extra-field-in-request gen/string-alpha-numeric]
(gen/return
{:request-method method
:uri path
:labels {:method (-> method name .toUpperCase)
:path path}})))
:extra-field-in-request extra-field-in-request
:labels {:method (-> method name .toUpperCase)
:path path
:extra-field-in-request extra-field-in-request}})))

;; ## Tests

(defspec t-wrap-instrumentation 100
(prop/for-all
[registry-fn (g/registry-fn ring/initialize)
[registry-fn (g/registry-fn #(ring/initialize % {:extra-labels [:extra-field-in-response
:extra-field-in-request]}))
{:keys [handler exception? labels]} gen-handler
{labels' :labels, :as request} gen-request
wrap (gen/elements [ring/wrap-instrumentation ring/wrap-metrics])]
(let [registry (registry-fn)
handler' (wrap handler registry)
handler' (wrap handler registry {:extra-labels-request [:extra-field-in-request]
:extra-labels-response [:extra-field-in-response]})
start-time (System/nanoTime)
response (try
(handler' request)
Expand All @@ -60,10 +66,11 @@
histogram (registry :http/request-latency-seconds labels)
ex-counter (registry :http/exceptions-total ex-labels)]
(if exception?
(and (= response ::error)
(= 0.0 (prometheus/value counter))
(= 0.0 (:count (prometheus/value histogram)))
(= 1.0 (prometheus/value ex-counter)))
(do (println (prometheus/value ex-counter))
(and (= response ::error)
(= 0.0 (prometheus/value counter))
(= 0.0 (:count (prometheus/value histogram)))
(= 1.0 (prometheus/value ex-counter))))
(and (map? response)
(= 0.0 (prometheus/value ex-counter))
(< 0.0 (:sum (prometheus/value histogram)) delta)
Expand Down

0 comments on commit 14e5790

Please sign in to comment.