diff --git a/src/iapetos/collector/ring.clj b/src/iapetos/collector/ring.clj index f36ddc9..f3c916d 100644 --- a/src/iapetos/collector/ring.clj +++ b/src/iapetos/collector/ring.clj @@ -142,14 +142,21 @@ ;; ### Metrics Endpoint (defn wrap-metrics-expose - "Expose Prometheus metrics at the given constant URI using the text format." + "Expose Prometheus metrics at the given constant URI using the text format. + + If `:on-request` is given, it will be called with the collector registry + whenever a request comes in (the result will be ignored). This lets you use + the Prometheus scraper as a trigger for metrics collection." [handler registry - & [{:keys [path] - :or {path "/metrics"}}]] + & [{:keys [path on-request] + :or {path "/metrics" + on-request identity}}]] (fn [{:keys [request-method uri] :as request}] (if (= uri path) (if (= request-method :get) - (metrics-response registry) + (do + (on-request registry) + (metrics-response registry)) {:status 405}) (handler request)))) @@ -165,7 +172,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] + & [{:keys [path path-fn on-request] :or {path "/metrics" path-fn :uri} :as options}]] diff --git a/test/iapetos/collector/ring_test.clj b/test/iapetos/collector/ring_test.clj index 96cb3d5..25ceb1c 100644 --- a/test/iapetos/collector/ring_test.clj +++ b/test/iapetos/collector/ring_test.clj @@ -87,3 +87,20 @@ (contains? headers "Content-Type") (re-matches #"text/plain(;.*)?" (headers "Content-Type")) (= (export/text-format registry) body))))))) + +(defspec t-wrap-metrics-expose-with-on-request-hook 10 + (prop/for-all + [registry-fn (g/registry-fn ring/initialize) + path (gen/fmap #(str "/" %) gen/string-alpha-numeric) + wrap (gen/elements [ring/wrap-metrics-expose ring/wrap-metrics])] + (let [registry (-> (registry-fn) + (prometheus/register + (prometheus/counter :http/requests-total))) + on-request-fn #(prometheus/inc % :http/requests-total) + handler (-> (constantly {:status 200}) + (wrap registry + {:path path + :on-request on-request-fn}))] + (and (zero? (prometheus/value (registry :http/requests-total))) + (= 200 (:status (handler {:request-method :get, :uri path}))) + (= 1.0 (prometheus/value (registry :http/requests-total)))))))