-
Notifications
You must be signed in to change notification settings - Fork 0
/
metric.clj
122 lines (111 loc) · 4.26 KB
/
metric.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
(ns corbihttp.metric
(:import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics
io.micrometer.core.instrument.binder.jvm.JvmGcMetrics
io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics
io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics
io.micrometer.core.instrument.binder.system.FileDescriptorMetrics
io.micrometer.core.instrument.binder.system.UptimeMetrics
io.micrometer.core.instrument.binder.system.ProcessorMetrics
io.micrometer.core.instrument.Counter
io.micrometer.core.instrument.Gauge
io.micrometer.core.instrument.MeterRegistry
io.micrometer.core.instrument.MeterRegistry$Config
io.micrometer.core.instrument.Metrics
io.micrometer.core.instrument.Timer
io.micrometer.core.instrument.Timer$Builder
io.micrometer.prometheus.PrometheusConfig
io.micrometer.prometheus.PrometheusMeterRegistry
java.util.concurrent.TimeUnit)
(:import java.util.function.Supplier))
(defn ->tags
"Converts a map of tags to an array of string"
[tags]
(into-array String
(->> tags
(map (fn [[k v]] [(name k) (name v)]))
flatten)))
(defn registry-component
[tags]
(let [^PrometheusMeterRegistry registry (PrometheusMeterRegistry. PrometheusConfig/DEFAULT)]
(.commonTags ^MeterRegistry$Config
(.config registry)
^"[Ljava.lang.String;" (->tags tags))
(Metrics/addRegistry registry)
(.bindTo (ClassLoaderMetrics.) registry)
(.bindTo (JvmGcMetrics.) registry)
(.bindTo (JvmMemoryMetrics.) registry)
(.bindTo (JvmThreadMetrics.) registry)
(.bindTo (FileDescriptorMetrics.) registry)
(.bindTo (UptimeMetrics.) registry)
(.bindTo (ProcessorMetrics.) registry)
registry))
(defn get-timer!
"get a timer by name and tags"
[^MeterRegistry registry n tags]
(.register ^Timer$Builder (doto (Timer/builder (name n))
(.publishPercentiles (double-array [0.5 0.75 0.98 0.99]))
(.tags ^"[Ljava.lang.String;" (->tags tags)))
registry))
(defn record [^MeterRegistry registry n tags duration]
(when registry
(let [timer (get-timer! registry n tags)]
(.record ^Timer timer duration TimeUnit/MILLISECONDS))))
(defmacro with-time
[^MeterRegistry registry n tags & body]
`(if ~registry
(let [^Timer timer# (get-timer! ~registry ~n ~tags)
current# (java.time.Instant/now)]
(try
(do ~@body)
(finally
(let [end# (java.time.Instant/now)]
(.record timer# (java.time.Duration/between current# end#))))))
(do ~@body)))
(defn increment!
"increments a counter"
([^MeterRegistry registry counter tags]
(increment! registry counter tags 1))
([^MeterRegistry registry counter tags n]
(when registry
(let [builder (doto (Counter/builder (name counter))
(.tags ^"[Ljava.lang.String;" (->tags tags)))
counter (.register builder registry)]
(.increment counter n)))))
(defn ^Supplier gauge-fn [producer-fn]
(reify Supplier
(get [this]
(producer-fn))))
(defn gauge!
[^MeterRegistry registry gauge tags producer-fn]
(when registry
(doto (Gauge/builder (name gauge) (gauge-fn producer-fn))
(.strongReference true)
(.tags ^"[Ljava.lang.String;" (->tags tags))
(.register registry)))
)
(defn scrape [^PrometheusMeterRegistry registry]
(some-> registry .scrape))
(defn prom-handler
[registry]
(fn handler
[_]
{:status 200
:headers {"Content-Type" "text/plain"}
:body (.getBytes ^String (scrape registry))}))
(defn http-response
"updates the http response counter"
[registry ctx]
(when registry
(let [status (str (:status (:response ctx)))
uri (if (= "404" status)
"?"
(str (:uri (:request ctx))))
method (str (or (some-> (:request ctx)
:request-method
name)
"null"))]
(increment! registry
:http.responses.total
{"uri" uri
"method" method
"status" status}))))