♻️ Add labels support to metrics module.

And improve the rpc metrics using labels.
This commit is contained in:
Andrey Antukh 2021-01-25 20:14:40 +01:00 committed by Hirunatan
parent 9f581ed10b
commit f8b349814c
2 changed files with 142 additions and 80 deletions

View file

@ -109,11 +109,13 @@
(tdown# (/ (- (System/nanoTime) start#) 1000000)))))) (tdown# (/ (- (System/nanoTime) start#) 1000000))))))
(defn make-counter (defn make-counter
[{:keys [name help registry reg] :as props}] [{:keys [name help registry reg labels] :as props}]
(let [registry (or registry reg) (let [registry (or registry reg)
instance (doto (Counter/build) instance (.. (Counter/build)
(.name name) (name name)
(.help help)) (help help))
_ (when (seq labels)
(.labelNames instance (into-array String labels)))
instance (.register instance registry)] instance (.register instance registry)]
(reify (reify
clojure.lang.IDeref clojure.lang.IDeref
@ -121,14 +123,21 @@
clojure.lang.IFn clojure.lang.IFn
(invoke [_ cmd] (invoke [_ cmd]
(.inc ^Counter instance))))) (.inc ^Counter instance))
(invoke [_ cmd labels]
(.. ^Counter instance
(labels labels)
(inc))))))
(defn make-gauge (defn make-gauge
[{:keys [name help registry reg] :as props}] [{:keys [name help registry reg labels] :as props}]
(let [registry (or registry reg) (let [registry (or registry reg)
instance (doto (Gauge/build) instance (.. (Gauge/build)
(.name name) (name name)
(.help help)) (help help))
_ (when (seq labels)
(.labelNames instance (into-array String labels)))
instance (.register instance registry)] instance (.register instance registry)]
(reify (reify
@ -139,17 +148,23 @@
(invoke [_ cmd] (invoke [_ cmd]
(case cmd (case cmd
:inc (.inc ^Gauge instance) :inc (.inc ^Gauge instance)
:dec (.dec ^Gauge instance)))))) :dec (.dec ^Gauge instance)))
(invoke [_ cmd labels]
(case cmd
:inc (.. ^Gauge instance (labels labels) (inc))
:dec (.. ^Gauge instance (labels labels) (dec)))))))
(defn make-summary (defn make-summary
[{:keys [name help registry reg] :as props}] [{:keys [name help registry reg labels] :as props}]
(let [registry (or registry reg) (let [registry (or registry reg)
instance (doto (Summary/build) instance (doto (Summary/build)
(.name name) (.name name)
(.help help) (.help help)
(.quantile 0.5 0.05) (.quantile 0.75 0.02)
(.quantile 0.9 0.01)
(.quantile 0.99 0.001)) (.quantile 0.99 0.001))
_ (when (seq labels)
(.labelNames instance (into-array String labels)))
instance (.register instance registry)] instance (.register instance registry)]
(reify (reify
clojure.lang.IDeref clojure.lang.IDeref
@ -157,51 +172,92 @@
clojure.lang.IFn clojure.lang.IFn
(invoke [_ cmd val] (invoke [_ cmd val]
(.observe ^Summary instance val))))) (.observe ^Summary instance val))
(invoke [_ cmd val labels]
(.. ^Summary instance
(labels labels)
(observe val))))))
(defn create (defn create
[{:keys [type name] :as props}] [{:keys [type name] :as props}]
(case type (case type
:counter (make-counter props) :counter (make-counter props)
:gauge (make-gauge props) :gauge (make-gauge props)
:summary (make-summary props))) :summary (make-summary props)))
(defn wrap-counter (defn wrap-counter
[rootf mobj] ([rootf mobj]
(let [mdata (meta rootf) (let [mdata (meta rootf)
origf (::original mdata rootf)] origf (::original mdata rootf)]
(with-meta (with-meta
(fn (fn
([a] ([a]
(mobj :inc) (mobj :inc)
(origf a)) (origf a))
([a b] ([a b]
(mobj :inc) (mobj :inc)
(origf a b)) (origf a b))
([a b & more] ([a b & more]
(mobj :inc) (mobj :inc)
(apply origf a b more))) (apply origf a b more)))
(assoc mdata ::original origf)))) (assoc mdata ::original origf))))
([rootf mobj labels]
(let [mdata (meta rootf)
labels (into-array String labels)
origf (::original mdata rootf)]
(with-meta
(fn
([a]
(mobj :inc)
(origf a))
([a b]
(mobj :inc)
(origf a b))
([a b & more]
(mobj :inc)
(apply origf a b more)))
(assoc mdata ::original origf)))))
(defn wrap-summary (defn wrap-summary
[rootf mobj] ([rootf mobj]
(let [mdata (meta rootf) (let [mdata (meta rootf)
origf (::original mdata rootf)] origf (::original mdata rootf)]
(with-meta (with-meta
(fn (fn
([a] ([a]
(with-measure (with-measure
:expr (origf a) :expr (origf a)
:cb #(mobj :observe %))) :cb #(mobj :observe %)))
([a b] ([a b]
(with-measure
:expr (origf a b)
:cb #(mobj :observe %)))
([a b & more]
(with-measure
:expr (apply origf a b more)
:cb #(mobj :observe %))))
(assoc mdata ::original origf))))
([rootf mobj labels]
(let [mdata (meta rootf)
labels (into-array String labels)
origf (::original mdata rootf)]
(with-meta
(fn
([a]
(with-measure (with-measure
:expr (origf a b) :expr (origf a)
:cb #(mobj :observe %))) :cb #(mobj :observe % labels)))
([a b & more] ([a b]
(with-measure (with-measure
:expr (apply origf a b more) :expr (origf a b)
:cb #(mobj :observe %)))) :cb #(mobj :observe % labels)))
(assoc mdata ::original origf)))) ([a b & more]
(with-measure
:expr (apply origf a b more)
:cb #(mobj :observe % labels))))
(assoc mdata ::original origf)))))
(defn instrument-vars! (defn instrument-vars!
[vars {:keys [wrap] :as props}] [vars {:keys [wrap] :as props}]

View file

@ -53,15 +53,8 @@
(fn? (:transform-response mdata)) ((:transform-response mdata) request)))) (fn? (:transform-response mdata)) ((:transform-response mdata) request))))
(defn- wrap-with-metrics (defn- wrap-with-metrics
[cfg f mdata prefix] [cfg f mdata]
(let [mreg (get-in cfg [:metrics :registry]) (mtx/wrap-summary f (::mobj cfg) [(::sv/name mdata)]))
mobj (mtx/create
{:name (-> (str "rpc_" (name prefix) "_" (::sv/name mdata) "_response_millis")
(str/replace "-" "_"))
:registry mreg
:type :summary
:help (str/fmt "Service '%s' response time in milliseconds." (::sv/name mdata))})]
(mtx/wrap-summary f mobj)))
;; Wrap the rpc handler with a semaphore if it is specified in the ;; Wrap the rpc handler with a semaphore if it is specified in the
;; metadata asocciated with the handler. ;; metadata asocciated with the handler.
@ -79,11 +72,10 @@
f)) f))
(defn- wrap-impl (defn- wrap-impl
[cfg f mdata prefix] [cfg f mdata]
(let [f (wrap-with-rlimits cfg f mdata) (let [f (wrap-with-rlimits cfg f mdata)
f (wrap-with-metrics cfg f mdata prefix) f (wrap-with-metrics cfg f mdata)
spec (or (::sv/spec mdata) spec (or (::sv/spec mdata) (s/spec any?))]
(s/spec any?))]
(log/debugf "Registering '%s' command to rpc service." (::sv/name mdata)) (log/debugf "Registering '%s' command to rpc service." (::sv/name mdata))
(fn [params] (fn [params]
(when (and (:auth mdata true) (not (uuid? (:profile-id params)))) (when (and (:auth mdata true) (not (uuid? (:profile-id params))))
@ -93,36 +85,50 @@
(f cfg (us/conform spec params))))) (f cfg (us/conform spec params)))))
(defn- process-method (defn- process-method
[cfg prefix vfn] [cfg vfn]
(let [mdata (meta vfn)] (let [mdata (meta vfn)]
[(keyword (::sv/name mdata)) [(keyword (::sv/name mdata))
(wrap-impl cfg (deref vfn) mdata prefix)])) (wrap-impl cfg (deref vfn) mdata)]))
(defn- resolve-query-methods (defn- resolve-query-methods
[cfg] [cfg]
(->> (sv/scan-ns 'app.rpc.queries.projects (let [mobj (mtx/create
'app.rpc.queries.files {:name "rpc_query_timing"
'app.rpc.queries.teams :labels ["name"]
'app.rpc.queries.comments :registry (get-in cfg [:metrics :registry])
'app.rpc.queries.profile :type :summary
'app.rpc.queries.recent-files :help "Timing of query services."})
'app.rpc.queries.viewer) cfg (assoc cfg ::mobj mobj)]
(map (partial process-method cfg :query)) (->> (sv/scan-ns 'app.rpc.queries.projects
(into {}))) 'app.rpc.queries.files
'app.rpc.queries.teams
'app.rpc.queries.comments
'app.rpc.queries.profile
'app.rpc.queries.recent-files
'app.rpc.queries.viewer)
(map (partial process-method cfg))
(into {}))))
(defn- resolve-mutation-methods (defn- resolve-mutation-methods
[cfg] [cfg]
(->> (sv/scan-ns 'app.rpc.mutations.demo (let [mobj (mtx/create
'app.rpc.mutations.media {:name "rpc_mutation_timing"
'app.rpc.mutations.profile :labels ["name"]
'app.rpc.mutations.files :registry (get-in cfg [:metrics :registry])
'app.rpc.mutations.comments :type :summary
'app.rpc.mutations.projects :help "Timing of mutation services."})
'app.rpc.mutations.viewer cfg (assoc cfg ::mobj mobj)]
'app.rpc.mutations.teams (->> (sv/scan-ns 'app.rpc.mutations.demo
'app.rpc.mutations.verify-token) 'app.rpc.mutations.media
(map (partial process-method cfg :mutation)) 'app.rpc.mutations.profile
(into {}))) 'app.rpc.mutations.files
'app.rpc.mutations.comments
'app.rpc.mutations.projects
'app.rpc.mutations.viewer
'app.rpc.mutations.teams
'app.rpc.mutations.verify-token)
(map (partial process-method cfg))
(into {}))))
(s/def ::storage some?) (s/def ::storage some?)
(s/def ::session map?) (s/def ::session map?)