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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
local time = require "util.time".now;
local new_metric_registry = require "util.openmetrics".new_metric_registry;
local render_histogram_le = require "util.openmetrics".render_histogram_le;
-- BEGIN of Metric implementations
-- Gauges
local gauge_metric_mt = {}
gauge_metric_mt.__index = gauge_metric_mt
local function new_gauge_metric()
local metric = { value = 0 }
setmetatable(metric, gauge_metric_mt)
return metric
end
function gauge_metric_mt:set(value)
self.value = value
end
function gauge_metric_mt:add(delta)
self.value = self.value + delta
end
function gauge_metric_mt:reset()
self.value = 0
end
function gauge_metric_mt:iter_samples()
local done = false
return function(_s)
if done then
return nil, true
end
done = true
return "", nil, _s.value
end, self
end
-- Counters
local counter_metric_mt = {}
counter_metric_mt.__index = counter_metric_mt
local function new_counter_metric()
local metric = {
_created = time(),
value = 0,
}
setmetatable(metric, counter_metric_mt)
return metric
end
function counter_metric_mt:set(value)
self.value = value
end
function counter_metric_mt:add(value)
self.value = (self.value or 0) + value
end
function counter_metric_mt:iter_samples()
local step = 0
return function(_s)
step = step + 1
if step == 1 then
return "_created", nil, _s._created
elseif step == 2 then
return "_total", nil, _s.value
else
return nil, nil, true
end
end, self
end
function counter_metric_mt:reset()
self.value = 0
end
-- Histograms
local histogram_metric_mt = {}
histogram_metric_mt.__index = histogram_metric_mt
local function new_histogram_metric(buckets)
local metric = {
_created = time(),
_sum = 0,
_count = 0,
}
-- the order of buckets matters unfortunately, so we cannot directly use
-- the thresholds as table keys
for i, threshold in ipairs(buckets) do
metric[i] = {
threshold = threshold,
threshold_s = render_histogram_le(threshold),
count = 0
}
end
setmetatable(metric, histogram_metric_mt)
return metric
end
function histogram_metric_mt:sample(value)
-- According to the I-D, values must be part of all buckets
for i, bucket in pairs(self) do
if "number" == type(i) and value <= bucket.threshold then
bucket.count = bucket.count + 1
end
end
self._sum = self._sum + value
self._count = self._count + 1
end
function histogram_metric_mt:iter_samples()
local key = nil
return function (_s)
local data
key, data = next(_s, key)
if key == "_created" or key == "_sum" or key == "_count" then
return key, nil, data
elseif key ~= nil then
return "_bucket", {["le"] = data.threshold_s}, data.count
else
return nil, nil, nil
end
end, self
end
function histogram_metric_mt:reset()
self._created = time()
self._count = 0
self._sum = 0
for i, bucket in pairs(self) do
if "number" == type(i) then
bucket.count = 0
end
end
end
-- Summary
local summary_metric_mt = {}
summary_metric_mt.__index = summary_metric_mt
local function new_summary_metric()
-- quantiles are not supported yet
local metric = {
_created = time(),
_sum = 0,
_count = 0,
}
setmetatable(metric, summary_metric_mt)
return metric
end
function summary_metric_mt:sample(value)
self._sum = self._sum + value
self._count = self._count + 1
end
function summary_metric_mt:iter_samples()
local key = nil
return function (_s)
local data
key, data = next(_s, key)
return key, nil, data
end, self
end
function summary_metric_mt:reset()
self._created = time()
self._count = 0
self._sum = 0
end
local pull_backend = {
gauge = new_gauge_metric,
counter = new_counter_metric,
histogram = new_histogram_metric,
summary = new_summary_metric,
}
-- END of Metric implementations
local function new()
return {
metric_registry = new_metric_registry(pull_backend),
}
end
return {
new = new;
}
|