-
Notifications
You must be signed in to change notification settings - Fork 31
/
collector.clj
137 lines (122 loc) · 4.09 KB
/
collector.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
(ns iapetos.collector
(:require [iapetos.metric :as metric])
(:import [io.prometheus.client
Collector$MetricFamilySamples
CollectorRegistry
SimpleCollector
SimpleCollector$Builder]))
;; ## Protocol
(defprotocol Collector
"Protocol for Collectors to be registered with a iapetos registry."
(instantiate [this registry-options]
"Return a collector instance that can be registered with collector
registries.")
(metric [this]
"Return a `iapetos.metric/Metric` for this collector.")
(label-instance [this instance values]
"Add labels to the given collector instance produced by `instantiate`."))
;; ## Labels
(defn- label-array
^"[Ljava.lang.String;"
[labels]
(into-array String (map metric/sanitize labels)))
(defn- label-names
[labels]
(map metric/dasherize labels))
(defn- set-labels
"Attach labels to the given `SimpleCollector` instance."
[^SimpleCollector instance labels values]
(let [label->value (->> (for [[k v] values]
[(-> k metric/dasherize) v])
(into {})
(comp str))
ordered-labels (->> labels (map label->value) (into-array String))]
(.labels instance ordered-labels)))
;; ## Record
(defn- check-subsystem
[{subsystem :subsystem} {subsystem' :subsystem}]
(when (and subsystem subsystem' (not= subsystem subsystem'))
(throw
(IllegalArgumentException.
(format
"collector subsystem (%s) is conflicting with registry subsystem (%s)."
(pr-str subsystem')
(pr-str subsystem)))))
(or subsystem subsystem'))
(defrecord SimpleCollectorImpl [type
namespace
name
description
subsystem
labels
builder-constructor
lazy?]
Collector
(instantiate [this registry-options]
(let [subsystem (check-subsystem this registry-options)]
(-> ^SimpleCollector$Builder
(builder-constructor)
(.name name)
(.namespace namespace)
(.help description)
(.labelNames (label-array labels))
(cond-> subsystem (.subsystem subsystem))
(.create))))
(metric [_]
{:name name
:namespace namespace})
(label-instance [_ instance values]
(set-labels instance labels values)))
(defn make-simple-collector
"Create a new simple collector representation to be instantiated and
registered with a iapetos registry."
[{:keys [^String name
^String namespace
^String subsystem
^String description
labels
lazy?]}
collector-type
builder-constructor]
{:pre [type name namespace description]}
(map->SimpleCollectorImpl
{:type collector-type
:namespace namespace
:name name
:description description
:subsystem subsystem
:labels (label-names labels)
:builder-constructor builder-constructor
:lazy? lazy?}))
;; ## Implementation for Raw Collectors
(defn- raw-metric
[^io.prometheus.client.Collector v]
(if-let [n (some-> (.collect v)
^Collector$MetricFamilySamples (first)
(.name))]
(let [[a b] (.split n "_" 2)]
(if b
{:name b, :namespace a}
{:name a, :namespace "raw"}))
{:name (str (.getSimpleName (class v)) "_" (hash v))
:namespace "raw"}))
(extend-protocol Collector
io.prometheus.client.Collector
(instantiate [this _]
this)
(metric [this]
(raw-metric this))
(label-instance [_ instance values]
(if-not (empty? values)
(throw (UnsupportedOperationException.))
instance)))
;; ## Named Collector
(defn named
[metric collector]
(reify Collector
(instantiate [_ options]
(instantiate collector options))
(metric [_]
metric)
(label-instance [_ instance values]
(label-instance collector instance values))))