master
go 461 lines 15.1 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package riakkv
4
5 import (
6 "slices"
7
8 "github.com/netdata/netdata/go/plugins/plugin/framework/collectorapi"
9 )
10
11 const (
12 prioKvNodeOperations = collectorapi.Priority + iota
13 prioDtVnodeUpdates
14 prioSearchQueries
15 prioSearchDocuments
16 prioConsistentOperations
17
18 prioKvLatencyGet
19 prioKvLatencyPut
20 prioDtLatencyCounter
21 prioDtLatencySet
22 prioDtLatencyMap
23 prioSearchLatencyQuery
24 prioSearchLatencyIndex
25 prioConsistentLatencyGet
26 prioConsistentLatencyPut
27
28 prioVmProcessesCount
29 prioVmProcessesMemory
30
31 prioKvSiblingsEncounteredGet
32 prioKvObjSizeGet
33 prioSearchVnodeqSize
34 prioSearchIndexErrors
35 prioCorePbc
36 prioCoreRepairs
37 prioCoreFsmActive
38 prioCoreFsmREjected
39 )
40
41 var charts = collectorapi.Charts{
42 kvNodeOperationsChart.Copy(),
43 dtVnodeUpdatesChart.Copy(),
44 searchQueriesChart.Copy(),
45 searchDocumentsChart.Copy(),
46 consistentOperationsChart.Copy(),
47
48 kvLatencyGetChart.Copy(),
49 kvLatencyPutChart.Copy(),
50 dtLatencyCounterChart.Copy(),
51 dtLatencySetChart.Copy(),
52 dtLatencyMapChart.Copy(),
53 searchLatencyQueryChart.Copy(),
54 searchLatencyIndexChart.Copy(),
55 consistentLatencyGetChart.Copy(),
56 consistentLatencyPutChart.Copy(),
57
58 vmProcessesCountChart.Copy(),
59 vmProcessesMemoryChart.Copy(),
60
61 kvSiblingsEncounteredGetChart.Copy(),
62 kvObjectSizeGetChart.Copy(),
63 searchVnodeqSizeChart.Copy(),
64 searchIndexErrorsChart.Copy(),
65 corePbsChart.Copy(),
66 coreRepairsChart.Copy(),
67 coreFsmActiveChart.Copy(),
68 coreFsmRejectedChart.Copy(),
69 }
70
71 /*
72 Throughput metrics
73 https://docs.riak.com/riak/kv/latest/using/reference/statistics-monitoring/index.html#throughput-metrics
74
75 Collected in totals
76 */
77 var (
78 kvNodeOperationsChart = collectorapi.Chart{
79 ID: "kv_node_operations",
80 Title: "Reads & writes coordinated by this node",
81 Units: "operations/s",
82 Fam: "throughput",
83 Ctx: "riak.kv.throughput",
84 Priority: prioKvNodeOperations,
85 Dims: collectorapi.Dims{
86 {ID: "node_gets_total", Name: "gets", Algo: collectorapi.Incremental},
87 {ID: "node_puts_total", Name: "puts", Algo: collectorapi.Incremental},
88 },
89 }
90 dtVnodeUpdatesChart = collectorapi.Chart{
91 ID: "dt_vnode_updates",
92 Title: "Update operations coordinated by local vnodes by data type",
93 Units: "operations/s",
94 Fam: "throughput",
95 Ctx: "riak.dt.vnode_updates",
96 Priority: prioDtVnodeUpdates,
97 Dims: collectorapi.Dims{
98 {ID: "vnode_counter_update_total", Name: "counters", Algo: collectorapi.Incremental},
99 {ID: "vnode_set_update_total", Name: "sets", Algo: collectorapi.Incremental},
100 {ID: "vnode_map_update_total", Name: "maps", Algo: collectorapi.Incremental},
101 },
102 }
103 searchQueriesChart = collectorapi.Chart{
104 ID: "dt_vnode_updates",
105 Title: "Search queries on the node",
106 Units: "queries/s",
107 Fam: "throughput",
108 Ctx: "riak.search",
109 Priority: prioSearchQueries,
110 Dims: collectorapi.Dims{
111 {ID: "search_query_throughput_count", Name: "queries", Algo: collectorapi.Incremental},
112 },
113 }
114 searchDocumentsChart = collectorapi.Chart{
115 ID: "search_documents",
116 Title: "Documents indexed by search",
117 Units: "documents/s",
118 Fam: "throughput",
119 Ctx: "riak.search.documents",
120 Priority: prioSearchDocuments,
121 Dims: collectorapi.Dims{
122 {ID: "search_index_throughput_count", Name: "indexed", Algo: collectorapi.Incremental},
123 },
124 }
125 consistentOperationsChart = collectorapi.Chart{
126 ID: "consistent_operations",
127 Title: "Consistent node operations",
128 Units: "operations/s",
129 Fam: "throughput",
130 Ctx: "riak.consistent.operations",
131 Priority: prioConsistentOperations,
132 Dims: collectorapi.Dims{
133 {ID: "consistent_gets_total", Name: "gets", Algo: collectorapi.Incremental},
134 {ID: "consistent_puts_total", Name: "puts", Algo: collectorapi.Incremental},
135 },
136 }
137 )
138
139 /*
140 Latency metrics
141 https://docs.riak.com/riak/kv/latest/using/reference/statistics-monitoring/index.html#throughput-metrics
142
143 Collected for the past minute in milliseconds and
144 returned from Riak in microseconds.
145 */
146 var (
147 kvLatencyGetChart = collectorapi.Chart{
148 ID: "kv_latency_get",
149 Title: "Time between reception of a client GET request and subsequent response to client",
150 Units: "ms",
151 Fam: "latency",
152 Ctx: "riak.kv.latency.get",
153 Priority: prioKvLatencyGet,
154 Dims: collectorapi.Dims{
155 {ID: "node_get_fsm_time_mean", Name: "mean", Div: 1000},
156 {ID: "node_get_fsm_time_median", Name: "median", Div: 1000},
157 {ID: "node_get_fsm_time_95", Name: "95", Div: 1000},
158 {ID: "node_get_fsm_time_99", Name: "99", Div: 1000},
159 {ID: "node_get_fsm_time_100", Name: "100", Div: 1000},
160 },
161 }
162 kvLatencyPutChart = collectorapi.Chart{
163 ID: "kv_latency_put",
164 Title: "Time between reception of a client PUT request and subsequent response to client",
165 Units: "ms",
166 Fam: "latency",
167 Ctx: "riak.kv.latency.put",
168 Priority: prioKvLatencyPut,
169 Dims: collectorapi.Dims{
170 {ID: "node_put_fsm_time_mean", Name: "mean", Div: 1000},
171 {ID: "node_put_fsm_time_median", Name: "median", Div: 1000},
172 {ID: "node_put_fsm_time_95", Name: "95", Div: 1000},
173 {ID: "node_put_fsm_time_99", Name: "99", Div: 1000},
174 {ID: "node_put_fsm_time_100", Name: "100", Div: 1000},
175 },
176 }
177 dtLatencyCounterChart = collectorapi.Chart{
178 ID: "dt_latency_counter",
179 Title: "Time it takes to perform an Update Counter operation",
180 Units: "ms",
181 Fam: "latency",
182 Ctx: "riak.dt.latency.counter_merge",
183 Priority: prioDtLatencyCounter,
184 Dims: collectorapi.Dims{
185 {ID: "object_counter_merge_time_mean", Name: "mean", Div: 1000},
186 {ID: "object_counter_merge_time_median", Name: "median", Div: 1000},
187 {ID: "object_counter_merge_time_95", Name: "95", Div: 1000},
188 {ID: "object_counter_merge_time_99", Name: "99", Div: 1000},
189 {ID: "object_counter_merge_time_100", Name: "100", Div: 1000},
190 },
191 }
192 dtLatencySetChart = collectorapi.Chart{
193 ID: "dt_latency_counter",
194 Title: "Time it takes to perform an Update Set operation",
195 Units: "ms",
196 Fam: "latency",
197 Ctx: "riak.dt.latency.set_merge",
198 Priority: prioDtLatencySet,
199 Dims: collectorapi.Dims{
200 {ID: "object_set_merge_time_mean", Name: "mean", Div: 1000},
201 {ID: "object_set_merge_time_median", Name: "median", Div: 1000},
202 {ID: "object_set_merge_time_95", Name: "95", Div: 1000},
203 {ID: "object_set_merge_time_99", Name: "99", Div: 1000},
204 {ID: "object_set_merge_time_100", Name: "100", Div: 1000},
205 },
206 }
207 dtLatencyMapChart = collectorapi.Chart{
208 ID: "dt_latency_map",
209 Title: "Time it takes to perform an Update Map operation",
210 Units: "ms",
211 Fam: "latency",
212 Ctx: "riak.dt.latency.map_merge",
213 Priority: prioDtLatencyMap,
214 Dims: collectorapi.Dims{
215 {ID: "object_map_merge_time_mean", Name: "mean", Div: 1000},
216 {ID: "object_map_merge_time_median", Name: "median", Div: 1000},
217 {ID: "object_map_merge_time_95", Name: "95", Div: 1000},
218 {ID: "object_map_merge_time_99", Name: "99", Div: 1000},
219 {ID: "object_map_merge_time_100", Name: "100", Div: 1000},
220 },
221 }
222 searchLatencyQueryChart = collectorapi.Chart{
223 ID: "search_latency_query",
224 Title: "Search query latency",
225 Units: "ms",
226 Fam: "latency",
227 Ctx: "riak.search.latency.query",
228 Priority: prioSearchLatencyQuery,
229 Dims: collectorapi.Dims{
230 {ID: "search_query_latency_median", Name: "median", Div: 1000},
231 {ID: "search_query_latency_min", Name: "min", Div: 1000},
232 {ID: "search_query_latency_95", Name: "95", Div: 1000},
233 {ID: "search_query_latency_99", Name: "99", Div: 1000},
234 {ID: "search_query_latency_999", Name: "999", Div: 1000},
235 {ID: "search_query_latency_max", Name: "max", Div: 1000},
236 },
237 }
238 searchLatencyIndexChart = collectorapi.Chart{
239 ID: "search_latency_index",
240 Title: "Time it takes Search to index a new document",
241 Units: "ms",
242 Fam: "latency",
243 Ctx: "riak.search.latency.index",
244 Priority: prioSearchLatencyIndex,
245 Dims: collectorapi.Dims{
246 {ID: "search_index_latency_median", Name: "median", Div: 1000},
247 {ID: "search_index_latency_min", Name: "min", Div: 1000},
248 {ID: "search_index_latency_95", Name: "95", Div: 1000},
249 {ID: "search_index_latency_99", Name: "99", Div: 1000},
250 {ID: "search_index_latency_999", Name: "999", Div: 1000},
251 {ID: "search_index_latency_max", Name: "max", Div: 1000},
252 },
253 }
254 consistentLatencyGetChart = collectorapi.Chart{
255 ID: "consistent_latency_get",
256 Title: "Strongly consistent read latency",
257 Units: "ms",
258 Fam: "latency",
259 Ctx: "riak.consistent.latency.get",
260 Priority: prioConsistentLatencyGet,
261 Dims: collectorapi.Dims{
262 {ID: "consistent_get_time_mean", Name: "mean", Div: 1000},
263 {ID: "consistent_get_time_median", Name: "median", Div: 1000},
264 {ID: "consistent_get_time_95", Name: "95", Div: 1000},
265 {ID: "consistent_get_time_99", Name: "99", Div: 1000},
266 {ID: "consistent_get_time_100", Name: "100", Div: 1000},
267 },
268 }
269 consistentLatencyPutChart = collectorapi.Chart{
270 ID: "consistent_latency_put",
271 Title: "Strongly consistent write latency",
272 Units: "ms",
273 Fam: "latency",
274 Ctx: "riak.consistent.latency.put",
275 Priority: prioConsistentLatencyPut,
276 Dims: collectorapi.Dims{
277 {ID: "consistent_put_time_mean", Name: "mean", Div: 1000},
278 {ID: "consistent_put_time_median", Name: "median", Div: 1000},
279 {ID: "consistent_put_time_95", Name: "95", Div: 1000},
280 {ID: "consistent_put_time_99", Name: "99", Div: 1000},
281 {ID: "consistent_put_time_100", Name: "100", Div: 1000},
282 },
283 }
284 )
285
286 /*
287 Erlang's resource usage metrics
288 https://docs.riak.com/riak/kv/latest/using/reference/statistics-monitoring/index.html#erlang-resource-usage-metrics
289
290 Processes collected as a gauge.
291 Memory collected as Megabytes, returned as bytes from Riak.
292 */
293 var (
294 vmProcessesCountChart = collectorapi.Chart{
295 ID: "vm_processes",
296 Title: "Total processes running in the Erlang VM",
297 Units: "processes",
298 Fam: "vm",
299 Ctx: "riak.vm.processes.count",
300 Priority: prioVmProcessesCount,
301 Dims: collectorapi.Dims{
302 {ID: "sys_processes", Name: "processes"},
303 },
304 }
305 vmProcessesMemoryChart = collectorapi.Chart{
306 ID: "vm_processes",
307 Title: "Memory allocated & used by Erlang processes",
308 Units: "bytes",
309 Fam: "vm",
310 Ctx: "riak.vm.processes.memory",
311 Priority: prioVmProcessesMemory,
312 Dims: collectorapi.Dims{
313 {ID: "memory_processes", Name: "allocated"},
314 {ID: "memory_processes_used", Name: "used"},
315 },
316 }
317 )
318
319 /*
320 General Riak Load / Health metrics
321 https://docs.riak.com/riak/kv/latest/using/reference/statistics-monitoring/index.html#general-riak-load-health-metrics
322 */
323 var (
324 // General Riak Load / Health metrics
325 // https://docs.riak.com/riak/kv/latest/using/reference/statistics-monitoring/index.html#general-riak-load-health-metrics
326 // Collected by Riak over the past minute
327
328 kvSiblingsEncounteredGetChart = collectorapi.Chart{
329 ID: "kv_siblings_encountered_get",
330 Title: "Siblings encountered during GET operations by this node during the past minute",
331 Units: "siblings",
332 Fam: "load",
333 Ctx: "riak.kv.siblings_encountered.get",
334 Priority: prioKvSiblingsEncounteredGet,
335 Dims: collectorapi.Dims{
336 {ID: "node_get_fsm_siblings_mean", Name: "mean"},
337 {ID: "node_get_fsm_siblings_median", Name: "median"},
338 {ID: "node_get_fsm_siblings_95", Name: "95"},
339 {ID: "node_get_fsm_siblings_99", Name: "99"},
340 {ID: "node_get_fsm_siblings_100", Name: "100"},
341 },
342 }
343 kvObjectSizeGetChart = collectorapi.Chart{
344 ID: "kv_siblings_encountered_get",
345 Title: "Object size encountered by this node during the past minute",
346 Units: "bytes",
347 Fam: "load",
348 Ctx: "riak.kv.objsize.get",
349 Priority: prioKvObjSizeGet,
350 Dims: collectorapi.Dims{
351 {ID: "node_get_fsm_objsize_mean", Name: "mean"},
352 {ID: "node_get_fsm_objsize_median", Name: "median"},
353 {ID: "node_get_fsm_objsize_95", Name: "95"},
354 {ID: "node_get_fsm_objsize_99", Name: "99"},
355 {ID: "node_get_fsm_objsize_100", Name: "100"},
356 },
357 }
358 searchVnodeqSizeChart = collectorapi.Chart{
359 ID: "kv_siblings_encountered_get",
360 Title: "Unprocessed messages in the vnode message queues of Search in the past minute",
361 Units: "messages",
362 Fam: "load",
363 Ctx: "riak.search.vnodeq_size",
364 Priority: prioSearchVnodeqSize,
365 Dims: collectorapi.Dims{
366 {ID: "riak_search_vnodeq_mean", Name: "mean"},
367 {ID: "riak_search_vnodeq_median", Name: "median"},
368 {ID: "riak_search_vnodeq_95", Name: "95"},
369 {ID: "riak_search_vnodeq_99", Name: "99"},
370 {ID: "riak_search_vnodeq_100", Name: "100"},
371 },
372 }
373
374 // General Riak Search Load / Health metrics
375 // https://docs.riak.com/riak/kv/latest/using/reference/statistics-monitoring/index.html#general-riak-search-load-health-metrics
376 // https://docs.riak.com/riak/kv/latest/using/reference/statistics-monitoring/index.html#general-riak-search-load-health-metrics
377 // Reported as counters.
378
379 searchIndexErrorsChart = collectorapi.Chart{
380 ID: "search_index_errors",
381 Title: "Errors encountered by Search",
382 Units: "errors",
383 Fam: "load",
384 Ctx: "riak.search.index.errors",
385 Priority: prioSearchIndexErrors,
386 Dims: collectorapi.Dims{
387 {ID: "search_index_fail_count", Name: "index_fail"},
388 {ID: "search_index_bad_entry_count", Name: "bad_entry"},
389 {ID: "search_index_extract_fail_count", Name: "extract_fail"},
390 },
391 }
392 corePbsChart = collectorapi.Chart{
393 ID: "core_pbc",
394 Title: "Protocol buffer connections by status",
395 Units: "connections",
396 Fam: "load",
397 Ctx: "riak.core.protobuf_connections",
398 Priority: prioCorePbc,
399 Dims: collectorapi.Dims{
400 {ID: "pbc_active", Name: "active"},
401 },
402 }
403 coreRepairsChart = collectorapi.Chart{
404 ID: "core_repairs",
405 Title: "Number of repair operations this node has coordinated",
406 Units: "repairs",
407 Fam: "load",
408 Ctx: "riak.core.protobuf_connections",
409 Priority: prioCoreRepairs,
410 Dims: collectorapi.Dims{
411 {ID: "read_repairs", Name: "read"},
412 },
413 }
414 coreFsmActiveChart = collectorapi.Chart{
415 ID: "core_fsm_active",
416 Title: "Active finite state machines by kind",
417 Units: "fsms",
418 Fam: "load",
419 Ctx: "riak.core.fsm_active",
420 Priority: prioCoreFsmActive,
421 Dims: collectorapi.Dims{
422 {ID: "node_get_fsm_active", Name: "get"},
423 {ID: "node_put_fsm_active", Name: "put"},
424 {ID: "index_fsm_active", Name: "secondary_index"},
425 {ID: "list_fsm_active", Name: "list_keys"},
426 },
427 }
428 coreFsmRejectedChart = collectorapi.Chart{
429 ID: "core_fsm_rejected",
430 Title: "Finite state machines being rejected by Sidejobs overload protection",
431 Units: "fsms",
432 Fam: "load",
433 Ctx: "riak.core.fsm_rejected",
434 Priority: prioCoreFsmREjected,
435 Dims: collectorapi.Dims{
436 {ID: "node_get_fsm_rejected", Name: "get"},
437 {ID: "node_put_fsm_rejected", Name: "put"},
438 },
439 }
440 )
441
442 func (c *Collector) adjustCharts(mx map[string]int64) {
443 var i int
444 for _, chart := range *c.Charts() {
445 chart.Dims = slices.DeleteFunc(chart.Dims, func(dim *collectorapi.Dim) bool {
446 _, ok := mx[dim.ID]
447 if !ok {
448 c.Debugf("removing dimension '%s' from chart '%s': metric not found", dim.ID, chart.ID)
449 }
450 return !ok
451 })
452
453 if len(chart.Dims) == 0 {
454 c.Debugf("removing chart '%s': no metrics found", chart.ID)
455 continue
456 }
457
458 (*c.Charts())[i] = chart
459 i++
460 }
461 }