@cryptotaxi247 / netdata-1 / commits / 09e9f4e37

go.d riakkv (#18330)

Ilya Mashchenko committed Aug 14, 2024 at 14:33 UTC 09e9f4e37a6b9da3b028484d095c170f4ead89cb
16 files changed +2142 -1
src/collectors/python.d.plugin/python.d.conf
+1 -1
@@ -39,7 +39,6 @@ go_expvar: no
39 # oracledb: yes
40 # pandas: yes
41 # retroshare: yes
42 -# riakkv: yes
42 # samba: yes
43 # smartd_log: yes
44 # spigotmc: yes
@@ -77,6 +76,7 @@ postgres: no # Removed (replaced with go.d/postgres).
76 proxysql: no # Removed (replaced with go.d/proxysql).
77 redis: no # Removed (replaced with go.d/redis).
78 rethinkdbs: no # Removed (replaced with go.d/rethinkdb).
79 +riakkv: no # Removed (replaced with go.d/riak).
80 sensors: no # Removed (replaced with go.d/sensors).
81 squid: no # Removed (replaced with go.d/squid).
82 tomcat: no # Removed (replaced with go.d/tomcat)
src/go/plugin/go.d/README.md
+1
@@ -128,6 +128,7 @@ see the appropriate collector readme.
128 | [rabbitmq](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/rabbitmq) | RabbitMQ |
129 | [redis](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/redis) | Redis |
130 | [rethinkdb](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/rethinkdb) | RethinkDB |
131 +| [riakkv](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/riakkv) | Riak KV |
132 | [rspamd](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/rspamd) | Rspamd |
133 | [scaleio](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/scaleio) | Dell EMC ScaleIO |
134 | [sensors](https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/sensors) | Hardware Sensors |
src/go/plugin/go.d/config/go.d.conf
+1
@@ -92,6 +92,7 @@ modules:
92 # rabbitmq: yes
93 # redis: yes
94 # rethinkdb: yes
95 +# riakkv: yes
96 # rspamd: yes
97 # scaleio: yes
98 # sensors: yes
src/go/plugin/go.d/config/go.d/riakkv.conf new
+6
@@ -0,0 +1,6 @@
1 +## All available configuration options, their descriptions and default values:
2 +## https://github.com/netdata/netdata/tree/master/src/go/plugin/go.d/modules/riakkv#readme
3 +
4 +#jobs:
5 +# - name: local
6 +# url: http://127.0.0.1:8098/stats
src/go/plugin/go.d/config/go.d/sd/net_listeners.conf
+7
@@ -110,6 +110,8 @@ classify:
110 expr: '{{ or (eq .Port "6379") (eq .Comm "redis-server") }}'
111 - tags: "rethinkdb"
112 expr: '{{ and (eq .Port "28015") (eq .Comm "rethinkdb") }}'
113 + - tags: "riak"
114 + expr: '{{ and (eq .Port "8098") (glob .Cmdline "*riak*") }}'
115 - tags: "rspamd"
116 expr: '{{ and (eq .Port "11334") (eq .Comm "rspamd") }}'
117 - tags: "squid"
@@ -387,6 +389,11 @@ compose:
389 module: rethinkdb
390 name: local
391 address: {{.Address}}
392 + - selector: "riak"
393 + template: |
394 + module: riakkv
395 + name: local
396 + url: http://{{.Address}}/stats
397 - selector: "rspamd"
398 template: |
399 module: rspamd
src/go/plugin/go.d/modules/init.go
+1
@@ -84,6 +84,7 @@ import (
84 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/rabbitmq"
85 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/redis"
86 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/rethinkdb"
87 + _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/riakkv"
88 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/rspamd"
89 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/scaleio"
90 _ "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/sensors"
src/go/plugin/go.d/modules/riakkv/charts.go new
+461
@@ -0,0 +1,461 @@
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/go.d/agent/module"
9 +)
10 +
11 +const (
12 + prioKvNodeOperations = module.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 = module.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 = module.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: module.Dims{
86 + {ID: "node_gets_total", Name: "gets", Algo: module.Incremental},
87 + {ID: "node_puts_total", Name: "puts", Algo: module.Incremental},
88 + },
89 + }
90 + dtVnodeUpdatesChart = module.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: module.Dims{
98 + {ID: "vnode_counter_update_total", Name: "counters", Algo: module.Incremental},
99 + {ID: "vnode_set_update_total", Name: "sets", Algo: module.Incremental},
100 + {ID: "vnode_map_update_total", Name: "maps", Algo: module.Incremental},
101 + },
102 + }
103 + searchQueriesChart = module.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: module.Dims{
111 + {ID: "search_query_throughput_count", Name: "queries", Algo: module.Incremental},
112 + },
113 + }
114 + searchDocumentsChart = module.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: module.Dims{
122 + {ID: "search_index_throughput_count", Name: "indexed", Algo: module.Incremental},
123 + },
124 + }
125 + consistentOperationsChart = module.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: module.Dims{
133 + {ID: "consistent_gets_total", Name: "gets", Algo: module.Incremental},
134 + {ID: "consistent_puts_total", Name: "puts", Algo: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.Dims{
302 + {ID: "sys_processes", Name: "processes"},
303 + },
304 + }
305 + vmProcessesMemoryChart = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.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 = module.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: module.Dims{
400 + {ID: "pbc_active", Name: "active"},
401 + },
402 + }
403 + coreRepairsChart = module.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: module.Dims{
411 + {ID: "read_repairs", Name: "read"},
412 + },
413 + }
414 + coreFsmActiveChart = module.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: module.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 = module.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: module.Dims{
436 + {ID: "node_get_fsm_rejected", Name: "get"},
437 + {ID: "node_put_fsm_rejected", Name: "put"},
438 + },
439 + }
440 +)
441 +
442 +func (r *RiakKv) adjustCharts(mx map[string]int64) {
443 + var i int
444 + for _, chart := range *r.Charts() {
445 + chart.Dims = slices.DeleteFunc(chart.Dims, func(dim *module.Dim) bool {
446 + _, ok := mx[dim.ID]
447 + if !ok {
448 + r.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 + r.Debugf("removing chart '%s': no metrics found", chart.ID)
455 + continue
456 + }
457 +
458 + (*r.Charts())[i] = chart
459 + i++
460 + }
461 +}
src/go/plugin/go.d/modules/riakkv/collect.go new
+74
@@ -0,0 +1,74 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package riakkv
4 +
5 +import (
6 + "encoding/json"
7 + "errors"
8 + "fmt"
9 + "io"
10 + "net/http"
11 +
12 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/stm"
13 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
14 +)
15 +
16 +func (r *RiakKv) collect() (map[string]int64, error) {
17 + stats, err := r.getStats()
18 + if err != nil {
19 + return nil, err
20 + }
21 +
22 + mx := stm.ToMap(stats)
23 +
24 + if len(mx) == 0 {
25 + return nil, errors.New("no stats")
26 + }
27 +
28 + r.once.Do(func() { r.adjustCharts(mx) })
29 +
30 + return mx, nil
31 +}
32 +
33 +func (r *RiakKv) getStats() (*riakStats, error) {
34 + req, err := web.NewHTTPRequest(r.Request)
35 + if err != nil {
36 + return nil, err
37 + }
38 +
39 + var stats riakStats
40 + if err := r.doOKDecode(req, &stats); err != nil {
41 + return nil, err
42 + }
43 +
44 + return &stats, nil
45 +}
46 +
47 +func (r *RiakKv) doOKDecode(req *http.Request, in interface{}) error {
48 + resp, err := r.httpClient.Do(req)
49 + if err != nil {
50 + return fmt.Errorf("error on HTTP request '%s': %v", req.URL, err)
51 + }
52 + defer closeBody(resp)
53 +
54 + if resp.StatusCode != http.StatusOK {
55 + msg := fmt.Sprintf("'%s' returned HTTP status code: %d", req.URL, resp.StatusCode)
56 + if resp.StatusCode == http.StatusNotFound {
57 + msg = fmt.Sprintf("%s (riak_kv_stat is not enabled)", msg)
58 + }
59 + return errors.New(msg)
60 + }
61 +
62 + if err := json.NewDecoder(resp.Body).Decode(in); err != nil {
63 + return fmt.Errorf("error on decoding response from '%s': %v", req.URL, err)
64 + }
65 +
66 + return nil
67 +}
68 +
69 +func closeBody(resp *http.Response) {
70 + if resp != nil && resp.Body != nil {
71 + _, _ = io.Copy(io.Discard, resp.Body)
72 + _ = resp.Body.Close()
73 + }
74 +}
src/go/plugin/go.d/modules/riakkv/config_schema.json new
+186
@@ -0,0 +1,186 @@
1 +{
2 + "jsonSchema": {
3 + "$schema": "http://json-schema.org/draft-07/schema#",
4 + "title": "RiakKV collector configuration.",
5 + "type": "object",
6 + "properties": {
7 + "update_every": {
8 + "title": "Update every",
9 + "description": "Data collection interval, measured in seconds.",
10 + "type": "integer",
11 + "minimum": 1,
12 + "default": 2
13 + },
14 + "url": {
15 + "title": "URL",
16 + "description": "The URL of the RiakKV [Stat](https://docs.riak.com/riak/kv/2.2.3/developing/api/http/status.1.html) endpoint.",
17 + "type": "string",
18 + "default": "http://127.0.0.1:8098/stats",
19 + "format": "uri"
20 + },
21 + "timeout": {
22 + "title": "Timeout",
23 + "description": "The timeout in seconds for the HTTP request.",
24 + "type": "number",
25 + "minimum": 0.5,
26 + "default": 1
27 + },
28 + "not_follow_redirects": {
29 + "title": "Not follow redirects",
30 + "description": "If set, the client will not follow HTTP redirects automatically.",
31 + "type": "boolean"
32 + },
33 + "username": {
34 + "title": "Username",
35 + "description": "The username for basic authentication.",
36 + "type": "string",
37 + "sensitive": true
38 + },
39 + "password": {
40 + "title": "Password",
41 + "description": "The password for basic authentication.",
42 + "type": "string",
43 + "sensitive": true
44 + },
45 + "proxy_url": {
46 + "title": "Proxy URL",
47 + "description": "The URL of the proxy server.",
48 + "type": "string"
49 + },
50 + "proxy_username": {
51 + "title": "Proxy username",
52 + "description": "The username for proxy authentication.",
53 + "type": "string",
54 + "sensitive": true
55 + },
56 + "proxy_password": {
57 + "title": "Proxy password",
58 + "description": "The password for proxy authentication.",
59 + "type": "string",
60 + "sensitive": true
61 + },
62 + "headers": {
63 + "title": "Headers",
64 + "description": "Additional HTTP headers to include in the request.",
65 + "type": [
66 + "object",
67 + "null"
68 + ],
69 + "additionalProperties": {
70 + "type": "string"
71 + }
72 + },
73 + "tls_skip_verify": {
74 + "title": "Skip TLS verification",
75 + "description": "If set, TLS certificate verification will be skipped.",
76 + "type": "boolean"
77 + },
78 + "tls_ca": {
79 + "title": "TLS CA",
80 + "description": "The path to the CA certificate file for TLS verification.",
81 + "type": "string",
82 + "pattern": "^$|^/"
83 + },
84 + "tls_cert": {
85 + "title": "TLS certificate",
86 + "description": "The path to the client certificate file for TLS authentication.",
87 + "type": "string",
88 + "pattern": "^$|^/"
89 + },
90 + "tls_key": {
91 + "title": "TLS key",
92 + "description": "The path to the client key file for TLS authentication.",
93 + "type": "string",
94 + "pattern": "^$|^/"
95 + },
96 + "body": {
97 + "title": "Body",
98 + "type": "string"
99 + },
100 + "method": {
101 + "title": "Method",
102 + "type": "string"
103 + }
104 + },
105 + "required": [
106 + "url"
107 + ],
108 + "additionalProperties": false,
109 + "patternProperties": {
110 + "^name$": {}
111 + }
112 + },
113 + "uiSchema": {
114 + "uiOptions": {
115 + "fullPage": true
116 + },
117 + "body": {
118 + "ui:widget": "hidden"
119 + },
120 + "method": {
121 + "ui:widget": "hidden"
122 + },
123 + "update_every": {
124 + "ui:help": "Riak updates metrics on the `/stats` endpoint every second. To ensure accurate data representation, a polling interval of 2 seconds or more is suggested."
125 + },
126 + "timeout": {
127 + "ui:help": "Accepts decimals for precise control (e.g., type 1.5 for 1.5 seconds)."
128 + },
129 + "username": {
130 + "ui:widget": "password"
131 + },
132 + "proxy_username": {
133 + "ui:widget": "password"
134 + },
135 + "password": {
136 + "ui:widget": "password"
137 + },
138 + "proxy_password": {
139 + "ui:widget": "password"
140 + },
141 + "ui:flavour": "tabs",
142 + "ui:options": {
143 + "tabs": [
144 + {
145 + "title": "Base",
146 + "fields": [
147 + "update_every",
148 + "url",
149 + "timeout",
150 + "not_follow_redirects"
151 + ]
152 + },
153 + {
154 + "title": "Auth",
155 + "fields": [
156 + "username",
157 + "password"
158 + ]
159 + },
160 + {
161 + "title": "TLS",
162 + "fields": [
163 + "tls_skip_verify",
164 + "tls_ca",
165 + "tls_cert",
166 + "tls_key"
167 + ]
168 + },
169 + {
170 + "title": "Proxy",
171 + "fields": [
172 + "proxy_url",
173 + "proxy_username",
174 + "proxy_password"
175 + ]
176 + },
177 + {
178 + "title": "Headers",
179 + "fields": [
180 + "headers"
181 + ]
182 + }
183 + ]
184 + }
185 + }
186 +}
src/go/plugin/go.d/modules/riakkv/metadata.yaml new
+390
@@ -0,0 +1,390 @@
1 +plugin_name: go.d.plugin
2 +modules:
3 + - meta:
4 + id: collector-go.d.plugin-riakkv
5 + plugin_name: go.d.plugin
6 + module_name: riakkv
7 + monitored_instance:
8 + name: Riak KV
9 + link: https://riak.com/products/riak-kv/index.html
10 + categories:
11 + - data-collection.database-servers
12 + icon_filename: "riak.svg"
13 + related_resources:
14 + integrations:
15 + list: []
16 + alternative_monitored_instances: []
17 + info_provided_to_referring_integrations:
18 + description: ""
19 + keywords:
20 + - database
21 + - nosql
22 + - big data
23 + most_popular: false
24 + overview:
25 + data_collection:
26 + metrics_description: |
27 + This collector monitors RiakKV metrics about throughput, latency, resources and more.
28 + method_description: |
29 + It sends HTTP requests to the Riak [/stats](https://docs.riak.com/riak/kv/2.2.3/developing/api/http/status.1.html) endpoint.
30 + default_behavior:
31 + auto_detection:
32 + description: |
33 + By default, it detects Riak instances running on localhost that are listening on port 8098.
34 + On startup, it tries to collect metrics from:
35 +
36 + - http://127.0.0.1:8098/stats
37 + limits:
38 + description: ""
39 + performance_impact:
40 + description: ""
41 + additional_permissions:
42 + description: ""
43 + multi_instance: true
44 + supported_platforms:
45 + include: []
46 + exclude: []
47 + setup:
48 + prerequisites:
49 + list:
50 + - title: Enable /stats endpoint
51 + description: |
52 + See the RiakKV [configuration reference](https://docs.riak.com/riak/kv/2.2.3/developing/api/http/status.1.html).
53 + configuration:
54 + file:
55 + name: go.d/riakkv.conf
56 + options:
57 + description: |
58 + The following options can be defined globally: update_every, autodetection_retry.
59 + folding:
60 + title: Config options
61 + enabled: true
62 + list:
63 + - name: update_every
64 + description: Data collection frequency.
65 + default_value: 1
66 + required: false
67 + - name: autodetection_retry
68 + description: Recheck interval in seconds. Zero means no recheck will be scheduled.
69 + default_value: 0
70 + required: false
71 + - name: url
72 + description: Server URL.
73 + default_value: http://127.0.0.1:8098/stats
74 + required: true
75 + - name: timeout
76 + description: HTTP request timeout.
77 + default_value: 1
78 + required: false
79 + - name: username
80 + description: Username for basic HTTP authentication.
81 + default_value: ""
82 + required: false
83 + - name: password
84 + description: Password for basic HTTP authentication.
85 + default_value: ""
86 + required: false
87 + - name: proxy_url
88 + description: Proxy URL.
89 + default_value: ""
90 + required: false
91 + - name: proxy_username
92 + description: Username for proxy basic HTTP authentication.
93 + default_value: ""
94 + required: false
95 + - name: proxy_password
96 + description: Password for proxy basic HTTP authentication.
97 + default_value: ""
98 + required: false
99 + - name: method
100 + description: HTTP request method.
101 + default_value: GET
102 + required: false
103 + - name: body
104 + description: HTTP request body.
105 + default_value: ""
106 + required: false
107 + - name: headers
108 + description: HTTP request headers.
109 + default_value: ""
110 + required: false
111 + - name: not_follow_redirects
112 + description: Redirect handling policy. Controls whether the client follows redirects.
113 + default_value: false
114 + required: false
115 + - name: tls_skip_verify
116 + description: Server certificate chain and hostname validation policy. Controls whether the client performs this check.
117 + default_value: false
118 + required: false
119 + - name: tls_ca
120 + description: Certification authority that the client uses when verifying the server's certificates.
121 + default_value: ""
122 + required: false
123 + - name: tls_cert
124 + description: Client TLS certificate.
125 + default_value: ""
126 + required: false
127 + - name: tls_key
128 + description: Client TLS key.
129 + default_value: ""
130 + required: false
131 + examples:
132 + folding:
133 + title: Config
134 + enabled: true
135 + list:
136 + - name: Basic
137 + description: A basic example configuration.
138 + folding:
139 + enabled: false
140 + config: |
141 + jobs:
142 + - name: local
143 + url: http://127.0.0.1:8098/stats
144 + - name: HTTP authentication
145 + description: Basic HTTP authentication.
146 + config: |
147 + jobs:
148 + - name: local
149 + url: http://127.0.0.1:8098/stats
150 + username: username
151 + password: password
152 + - name: HTTPS with self-signed certificate
153 + description: With enabled HTTPS and self-signed certificate.
154 + config: |
155 + jobs:
156 + - name: local
157 + url: http://127.0.0.1:8098/stats
158 + tls_skip_verify: yes
159 + - name: Multi-instance
160 + description: |
161 + > **Note**: When you define multiple jobs, their names must be unique.
162 +
163 + Collecting metrics from local and remote instances.
164 + config: |
165 + jobs:
166 + - name: local
167 + url: http://127.0.0.1:8098/stats
168 +
169 + - name: remote
170 + url: http://192.0.2.1:8098/stats
171 + troubleshooting:
172 + problems:
173 + list: []
174 + alerts: []
175 + metrics:
176 + folding:
177 + title: Metrics
178 + enabled: false
179 + description: ""
180 + availability: []
181 + scopes:
182 + - name: global
183 + description: These metrics refer to the entire monitored application.
184 + labels: []
185 + metrics:
186 + - name: riak.kv.throughput
187 + description: Reads & writes coordinated by this node
188 + unit: "operations/s"
189 + chart_type: line
190 + dimensions:
191 + - name: gets
192 + - name: puts
193 + - name: riak.dt.vnode_updates
194 + description: Update operations coordinated by local vnodes by data type
195 + unit: "operations/s"
196 + chart_type: line
197 + dimensions:
198 + - name: counters
199 + - name: sets
200 + - name: maps
201 + - name: riak.search
202 + description: Search queries on the node
203 + unit: "queries/s"
204 + chart_type: line
205 + dimensions:
206 + - name: queries
207 + - name: riak.search.documents
208 + description: Documents indexed by search
209 + unit: "documents/s"
210 + chart_type: line
211 + dimensions:
212 + - name: indexed
213 + - name: riak.consistent.operations
214 + description: Consistent node operations
215 + unit: "operations/s"
216 + chart_type: line
217 + dimensions:
218 + - name: gets
219 + - name: puts
220 + - name: riak.kv.latency.get
221 + description: Time between reception of a client GET request and subsequent response to client
222 + unit: "ms"
223 + chart_type: line
224 + dimensions:
225 + - name: mean
226 + - name: median
227 + - name: "95"
228 + - name: "99"
229 + - name: "100"
230 + - name: riak.kv.latency.put
231 + description: Time between reception of a client PUT request and subsequent response to client
232 + unit: "ms"
233 + chart_type: line
234 + dimensions:
235 + - name: mean
236 + - name: median
237 + - name: "95"
238 + - name: "99"
239 + - name: "100"
240 + - name: riak.dt.latency.counter_merge
241 + description: Time it takes to perform an Update Counter operation
242 + unit: "ms"
243 + chart_type: line
244 + dimensions:
245 + - name: mean
246 + - name: median
247 + - name: "95"
248 + - name: "99"
249 + - name: "100"
250 + - name: riak.dt.latency.set_merge
251 + description: Time it takes to perform an Update Set operation
252 + unit: "ms"
253 + chart_type: line
254 + dimensions:
255 + - name: mean
256 + - name: median
257 + - name: "95"
258 + - name: "99"
259 + - name: "100"
260 + - name: riak.dt.latency.map_merge
261 + description: Time it takes to perform an Update Map operation
262 + unit: "ms"
263 + chart_type: line
264 + dimensions:
265 + - name: mean
266 + - name: median
267 + - name: "95"
268 + - name: "99"
269 + - name: "100"
270 + - name: riak.search.latency.query
271 + description: Search query latency
272 + unit: "ms"
273 + chart_type: line
274 + dimensions:
275 + - name: median
276 + - name: min
277 + - name: "95"
278 + - name: "99"
279 + - name: "999"
280 + - name: max
281 + - name: riak.search.latency.index
282 + description: Time it takes Search to index a new document
283 + unit: "ms"
284 + chart_type: line
285 + dimensions:
286 + - name: median
287 + - name: min
288 + - name: "95"
289 + - name: "99"
290 + - name: "999"
291 + - name: max
292 + - name: riak.consistent.latency.get
293 + description: Strongly consistent read latency
294 + unit: "ms"
295 + chart_type: line
296 + dimensions:
297 + - name: mean
298 + - name: median
299 + - name: "95"
300 + - name: "99"
301 + - name: "100"
302 + - name: riak.consistent.latency.put
303 + description: Strongly consistent write latency
304 + unit: "ms"
305 + chart_type: line
306 + dimensions:
307 + - name: mean
308 + - name: median
309 + - name: "95"
310 + - name: "99"
311 + - name: "100"
312 + - name: riak.vm
313 + description: Total processes running in the Erlang VM
314 + unit: "total"
315 + chart_type: line
316 + dimensions:
317 + - name: processes
318 + - name: riak.vm.memory.processes
319 + description: Memory allocated & used by Erlang processes
320 + unit: "MB"
321 + chart_type: line
322 + dimensions:
323 + - name: allocated
324 + - name: used
325 + - name: riak.kv.siblings_encountered.get
326 + description: Number of siblings encountered during GET operations by this node during the past minute
327 + unit: "siblings"
328 + chart_type: line
329 + dimensions:
330 + - name: mean
331 + - name: median
332 + - name: "95"
333 + - name: "99"
334 + - name: "100"
335 + - name: riak.kv.objsize.get
336 + description: Object size encountered by this node during the past minute
337 + unit: "KB"
338 + chart_type: line
339 + dimensions:
340 + - name: mean
341 + - name: median
342 + - name: "95"
343 + - name: "99"
344 + - name: "100"
345 + - name: riak.search.vnodeq_size
346 + description: Number of unprocessed messages in the vnode message queues of Search on this node in the past minute
347 + unit: "messages"
348 + chart_type: line
349 + dimensions:
350 + - name: mean
351 + - name: median
352 + - name: "95"
353 + - name: "99"
354 + - name: "100"
355 + - name: riak.search.index
356 + description: Errors encountered by Search
357 + unit: "errors"
358 + chart_type: line
359 + dimensions:
360 + - name: index_fail
361 + - name: bad_entry
362 + - name: extract_fail
363 + - name: riak.core.protobuf_connections
364 + description: Protocol buffer connections by status
365 + unit: "connections"
366 + chart_type: line
367 + dimensions:
368 + - name: active
369 + - name: riak.core.repairs
370 + description: Number of repair operations this node has coordinated
371 + unit: "repairs"
372 + chart_type: line
373 + dimensions:
374 + - name: read
375 + - name: riak.core.fsm_active
376 + description: Active finite state machines by kind
377 + unit: "fsms"
378 + chart_type: line
379 + dimensions:
380 + - name: get
381 + - name: put
382 + - name: secondary index
383 + - name: list keys
384 + - name: riak.core.fsm_rejected
385 + description: Finite state machines being rejected by Sidejobs overload protection
386 + unit: "fsms"
387 + chart_type: line
388 + dimensions:
389 + - name: get
390 + - name: put
src/go/plugin/go.d/modules/riakkv/riakkv.go new
+122
@@ -0,0 +1,122 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package riakkv
4 +
5 +import (
6 + _ "embed"
7 + "errors"
8 + "net/http"
9 + "sync"
10 + "time"
11 +
12 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
13 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
14 +)
15 +
16 +//go:embed "config_schema.json"
17 +var configSchema string
18 +
19 +func init() {
20 + module.Register("riakkv", module.Creator{
21 + Create: func() module.Module { return New() },
22 + // Riak updates the metrics on the /stats endpoint every 1 second.
23 + // If we use 1 here, it means we might get weird jitter in the graph,
24 + // so the default is set to 2 seconds to prevent that.
25 + Defaults: module.Defaults{
26 + UpdateEvery: 2,
27 + },
28 + JobConfigSchema: configSchema,
29 + Config: func() any { return &Config{} },
30 + })
31 +}
32 +
33 +func New() *RiakKv {
34 + return &RiakKv{
35 + Config: Config{
36 + HTTP: web.HTTP{
37 + Request: web.Request{
38 + // https://docs.riak.com/riak/kv/2.2.3/developing/api/http/status.1.html
39 + URL: "http://127.0.0.1:8098/stats",
40 + },
41 + Client: web.Client{
42 + Timeout: web.Duration(time.Second),
43 + },
44 + },
45 + },
46 + once: &sync.Once{},
47 + charts: charts.Copy(),
48 + }
49 +}
50 +
51 +type Config struct {
52 + UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
53 + web.HTTP `yaml:",inline" json:""`
54 +}
55 +
56 +type RiakKv struct {
57 + module.Base
58 + Config `yaml:",inline" json:""`
59 +
60 + once *sync.Once
61 + charts *module.Charts
62 +
63 + httpClient *http.Client
64 +}
65 +
66 +func (r *RiakKv) Configuration() any {
67 + return r.Config
68 +}
69 +
70 +func (r *RiakKv) Init() error {
71 + if r.URL == "" {
72 + r.Errorf("url required but not set")
73 + return errors.New("url not set")
74 + }
75 +
76 + httpClient, err := web.NewHTTPClient(r.Client)
77 + if err != nil {
78 + r.Errorf("init HTTP client: %v", err)
79 + return err
80 + }
81 + r.httpClient = httpClient
82 +
83 + r.Debugf("using URL %s", r.URL)
84 + r.Debugf("using timeout: %s", r.Timeout)
85 +
86 + return nil
87 +}
88 +
89 +func (r *RiakKv) Check() error {
90 + mx, err := r.collect()
91 + if err != nil {
92 + r.Error(err)
93 + return err
94 + }
95 + if len(mx) == 0 {
96 + return errors.New("no metrics collected")
97 +
98 + }
99 + return nil
100 +}
101 +
102 +func (r *RiakKv) Charts() *module.Charts {
103 + return r.charts
104 +}
105 +
106 +func (r *RiakKv) Collect() map[string]int64 {
107 + mx, err := r.collect()
108 + if err != nil {
109 + r.Error(err)
110 + }
111 +
112 + if len(mx) == 0 {
113 + return nil
114 + }
115 + return mx
116 +}
117 +
118 +func (r *RiakKv) Cleanup() {
119 + if r.httpClient != nil {
120 + r.httpClient.CloseIdleConnections()
121 + }
122 +}
src/go/plugin/go.d/modules/riakkv/riakkv_test.go new
+265
@@ -0,0 +1,265 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package riakkv
4 +
5 +import (
6 + "net/http"
7 + "net/http/httptest"
8 + "os"
9 + "testing"
10 +
11 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/module"
12 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
13 +
14 + "github.com/stretchr/testify/assert"
15 + "github.com/stretchr/testify/require"
16 +)
17 +
18 +var (
19 + dataConfigJSON, _ = os.ReadFile("testdata/config.json")
20 + dataConfigYAML, _ = os.ReadFile("testdata/config.yaml")
21 +
22 + dataStats, _ = os.ReadFile("testdata/stats.json")
23 +)
24 +
25 +func Test_testDataIsValid(t *testing.T) {
26 + for name, data := range map[string][]byte{
27 + "dataConfigJSON": dataConfigJSON,
28 + "dataConfigYAML": dataConfigYAML,
29 + "dataStats": dataStats,
30 + } {
31 + require.NotNil(t, data, name)
32 +
33 + }
34 +}
35 +
36 +func TestRiakKv_ConfigurationSerialize(t *testing.T) {
37 + module.TestConfigurationSerialize(t, &RiakKv{}, dataConfigJSON, dataConfigYAML)
38 +}
39 +
40 +func TestRiakKv_Init(t *testing.T) {
41 + tests := map[string]struct {
42 + wantFail bool
43 + config Config
44 + }{
45 + "success with default": {
46 + wantFail: false,
47 + config: New().Config,
48 + },
49 + "fail when URL not set": {
50 + wantFail: true,
51 + config: Config{
52 + HTTP: web.HTTP{
53 + Request: web.Request{URL: ""},
54 + },
55 + },
56 + },
57 + }
58 +
59 + for name, test := range tests {
60 + t.Run(name, func(t *testing.T) {
61 + riak := New()
62 + riak.Config = test.config
63 +
64 + if test.wantFail {
65 + assert.Error(t, riak.Init())
66 + } else {
67 + assert.NoError(t, riak.Init())
68 + }
69 + })
70 + }
71 +}
72 +
73 +func TestRiakKv_Check(t *testing.T) {
74 + tests := map[string]struct {
75 + wantFail bool
76 + prepare func(t *testing.T) (riak *RiakKv, cleanup func())
77 + }{
78 + "success on valid response": {
79 + wantFail: false,
80 + prepare: caseOkResponse,
81 + },
82 + "fail on invalid data response": {
83 + wantFail: true,
84 + prepare: caseInvalidDataResponse,
85 + },
86 + "fail on connection refused": {
87 + wantFail: true,
88 + prepare: caseConnectionRefused,
89 + },
90 + "fail on 404 response": {
91 + wantFail: true,
92 + prepare: case404,
93 + },
94 + }
95 +
96 + for name, test := range tests {
97 + t.Run(name, func(t *testing.T) {
98 + riak, cleanup := test.prepare(t)
99 + defer cleanup()
100 +
101 + if test.wantFail {
102 + assert.Error(t, riak.Check())
103 + } else {
104 + assert.NoError(t, riak.Check())
105 + }
106 + })
107 + }
108 +}
109 +
110 +func TestRiakKv_Charts(t *testing.T) {
111 + assert.NotNil(t, New().Charts())
112 +}
113 +
114 +func TestRiakKv_Collect(t *testing.T) {
115 + tests := map[string]struct {
116 + prepare func(t *testing.T) (riak *RiakKv, cleanup func())
117 + wantMetrics map[string]int64
118 + }{
119 + "success on valid response": {
120 + prepare: caseOkResponse,
121 + wantMetrics: map[string]int64{
122 + "consistent_get_time_100": 1,
123 + "consistent_get_time_95": 1,
124 + "consistent_get_time_99": 1,
125 + "consistent_get_time_mean": 1,
126 + "consistent_get_time_median": 1,
127 + "consistent_gets_total": 1,
128 + "consistent_put_time_100": 1,
129 + "consistent_put_time_95": 1,
130 + "consistent_put_time_99": 1,
131 + "consistent_put_time_mean": 1,
132 + "consistent_put_time_median": 1,
133 + "consistent_puts_total": 1,
134 + "index_fsm_active": 1,
135 + "list_fsm_active": 1,
136 + "memory_processes": 274468041,
137 + "memory_processes_used": 274337336,
138 + "node_get_fsm_active": 1,
139 + "node_get_fsm_objsize_100": 1037,
140 + "node_get_fsm_objsize_95": 1,
141 + "node_get_fsm_objsize_99": 1025,
142 + "node_get_fsm_objsize_mean": 791,
143 + "node_get_fsm_objsize_median": 669,
144 + "node_get_fsm_rejected": 1,
145 + "node_get_fsm_siblings_100": 1,
146 + "node_get_fsm_siblings_95": 1,
147 + "node_get_fsm_siblings_99": 1,
148 + "node_get_fsm_siblings_mean": 1,
149 + "node_get_fsm_siblings_median": 1,
150 + "node_get_fsm_time_100": 678351,
151 + "node_get_fsm_time_95": 1,
152 + "node_get_fsm_time_99": 10148,
153 + "node_get_fsm_time_mean": 2161,
154 + "node_get_fsm_time_median": 1022,
155 + "node_gets_total": 422626,
156 + "node_put_fsm_active": 1,
157 + "node_put_fsm_rejected": 1,
158 + "node_put_fsm_time_100": 1049568,
159 + "node_put_fsm_time_95": 19609,
160 + "node_put_fsm_time_99": 37735,
161 + "node_put_fsm_time_mean": 11828,
162 + "node_put_fsm_time_median": 5017,
163 + "node_puts_total": 490965,
164 + "object_counter_merge_time_100": 1,
165 + "object_counter_merge_time_95": 1,
166 + "object_counter_merge_time_99": 1,
167 + "object_counter_merge_time_mean": 1,
168 + "object_counter_merge_time_median": 1,
169 + "object_map_merge_time_100": 1,
170 + "object_map_merge_time_95": 1,
171 + "object_map_merge_time_99": 1,
172 + "object_map_merge_time_mean": 1,
173 + "object_map_merge_time_median": 1,
174 + "object_set_merge_time_100": 1,
175 + "object_set_merge_time_95": 1,
176 + "object_set_merge_time_99": 1,
177 + "object_set_merge_time_mean": 1,
178 + "object_set_merge_time_median": 1,
179 + "pbc_active": 46,
180 + "read_repairs": 1,
181 + "vnode_counter_update_total": 1,
182 + "vnode_map_update_total": 1,
183 + "vnode_set_update_total": 1,
184 + },
185 + },
186 + "fail on invalid data response": {
187 + prepare: caseInvalidDataResponse,
188 + wantMetrics: nil,
189 + },
190 + "fail on connection refused": {
191 + prepare: caseConnectionRefused,
192 + wantMetrics: nil,
193 + },
194 + "fail on 404 response": {
195 + prepare: case404,
196 + wantMetrics: nil,
197 + },
198 + }
199 +
200 + for name, test := range tests {
201 + t.Run(name, func(t *testing.T) {
202 + riak, cleanup := test.prepare(t)
203 + defer cleanup()
204 +
205 + _ = riak.Check()
206 +
207 + mx := riak.Collect()
208 +
209 + require.Equal(t, test.wantMetrics, mx)
210 +
211 + if len(test.wantMetrics) > 0 {
212 + require.True(t, len(*riak.Charts()) > 0, "charts > 0")
213 + module.TestMetricsHasAllChartsDims(t, riak.Charts(), mx)
214 + }
215 + })
216 + }
217 +}
218 +
219 +func caseOkResponse(t *testing.T) (*RiakKv, func()) {
220 + t.Helper()
221 + srv := httptest.NewServer(http.HandlerFunc(
222 + func(w http.ResponseWriter, r *http.Request) {
223 + _, _ = w.Write(dataStats)
224 + }))
225 + riak := New()
226 + riak.URL = srv.URL
227 + require.NoError(t, riak.Init())
228 +
229 + return riak, srv.Close
230 +}
231 +
232 +func caseInvalidDataResponse(t *testing.T) (*RiakKv, func()) {
233 + t.Helper()
234 + srv := httptest.NewServer(http.HandlerFunc(
235 + func(w http.ResponseWriter, r *http.Request) {
236 + _, _ = w.Write([]byte("hello and\n goodbye"))
237 + }))
238 + riak := New()
239 + riak.URL = srv.URL
240 + require.NoError(t, riak.Init())
241 +
242 + return riak, srv.Close
243 +}
244 +
245 +func caseConnectionRefused(t *testing.T) (*RiakKv, func()) {
246 + t.Helper()
247 + rk := New()
248 + rk.URL = "http://127.0.0.1:65001"
249 + require.NoError(t, rk.Init())
250 +
251 + return rk, func() {}
252 +}
253 +
254 +func case404(t *testing.T) (*RiakKv, func()) {
255 + t.Helper()
256 + srv := httptest.NewServer(http.HandlerFunc(
257 + func(w http.ResponseWriter, r *http.Request) {
258 + w.WriteHeader(http.StatusNotFound)
259 + }))
260 + riak := New()
261 + riak.URL = srv.URL
262 + require.NoError(t, riak.Init())
263 +
264 + return riak, srv.Close
265 +}
src/go/plugin/go.d/modules/riakkv/stats.go new
+112
@@ -0,0 +1,112 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package riakkv
4 +
5 +// FIXME: old data (likely wrong) from https://github.com/netdata/netdata/issues/2413#issuecomment-500867044
6 +type riakStats struct {
7 + NodeGetsTotal *int64 `json:"node_gets_total" stm:"node_gets_total"`
8 + NodePutsTotal *int64 `json:"node_puts_total" stm:"node_puts_total"`
9 +
10 + VnodeCounterUpdateTotal *int64 `json:"vnode_counter_update_total" stm:"vnode_counter_update_total"`
11 + VnodeSetUpdateTotal *int64 `json:"vnode_set_update_total" stm:"vnode_set_update_total"`
12 + VnodeMapUpdateTotal *int64 `json:"vnode_map_update_total" stm:"vnode_map_update_total"`
13 +
14 + SearchQueryThroughputCount *int64 `json:"search_query_throughput_count" stm:"search_query_throughput_count"`
15 + SearchIndexThroughputCount *int64 `json:"search_index_throughput_count" stm:"search_index_throughput_count"`
16 +
17 + ConsistentGetsTotal *int64 `json:"consistent_gets_total" stm:"consistent_gets_total"`
18 + ConsistentPutsTotal *int64 `json:"consistent_puts_total" stm:"consistent_puts_total"`
19 +
20 + NodeGetFsmTimeMean *int64 `json:"node_get_fsm_time_mean" stm:"node_get_fsm_time_mean"`
21 + NodeGetFsmTimeMedian *int64 `json:"node_get_fsm_time_median" stm:"node_get_fsm_time_median"`
22 + NodeGetFsmTime95 *int64 `json:"node_get_fsm_time_95" stm:"node_get_fsm_time_95"`
23 + NodeGetFsmTime99 *int64 `json:"node_get_fsm_time_99" stm:"node_get_fsm_time_99"`
24 + NodeGetFsmTime100 *int64 `json:"node_get_fsm_time_100" stm:"node_get_fsm_time_100"`
25 +
26 + NodePutFsmTimeMean *int64 `json:"node_put_fsm_time_mean" stm:"node_put_fsm_time_mean"`
27 + NodePutFsmTimeMedian *int64 `json:"node_put_fsm_time_median" stm:"node_put_fsm_time_median"`
28 + NodePutFsmTime95 *int64 `json:"node_put_fsm_time_95" stm:"node_put_fsm_time_95"`
29 + NodePutFsmTime99 *int64 `json:"node_put_fsm_time_99" stm:"node_put_fsm_time_99"`
30 + NodePutFsmTime100 *int64 `json:"node_put_fsm_time_100" stm:"node_put_fsm_time_100"`
31 +
32 + ObjectCounterMergeTimeMean *int64 `json:"object_counter_merge_time_mean" stm:"object_counter_merge_time_mean"`
33 + ObjectCounterMergeTimeMedian *int64 `json:"object_counter_merge_time_median" stm:"object_counter_merge_time_median"`
34 + ObjectCounterMergeTime95 *int64 `json:"object_counter_merge_time_95" stm:"object_counter_merge_time_95"`
35 + ObjectCounterMergeTime99 *int64 `json:"object_counter_merge_time_99" stm:"object_counter_merge_time_99"`
36 + ObjectCounterMergeTime100 *int64 `json:"object_counter_merge_time_100" stm:"object_counter_merge_time_100"`
37 +
38 + ObjectSetMergeTimeMean *int64 `json:"object_set_merge_time_mean" stm:"object_set_merge_time_mean"`
39 + ObjectSetMergeTimeMedian *int64 `json:"object_set_merge_time_median" stm:"object_set_merge_time_median"`
40 + ObjectSetMergeTime95 *int64 `json:"object_set_merge_time_95" stm:"object_set_merge_time_95"`
41 + ObjectSetMergeTime99 *int64 `json:"object_set_merge_time_99" stm:"object_set_merge_time_99"`
42 + ObjectSetMergeTime100 *int64 `json:"object_set_merge_time_100" stm:"object_set_merge_time_100"`
43 +
44 + ObjectMapMergeTimeMean *int64 `json:"object_map_merge_time_mean" stm:"object_map_merge_time_mean"`
45 + ObjectMapMergeTimeMedian *int64 `json:"object_map_merge_time_median" stm:"object_map_merge_time_median"`
46 + ObjectMapMergeTime95 *int64 `json:"object_map_merge_time_95" stm:"object_map_merge_time_95"`
47 + ObjectMapMergeTime99 *int64 `json:"object_map_merge_time_99" stm:"object_map_merge_time_99"`
48 + ObjectMapMergeTime100 *int64 `json:"object_map_merge_time_100" stm:"object_map_merge_time_100"`
49 +
50 + SearchQueryLatencyMin *int64 `json:"search_query_latency_min" stm:"search_query_latency_min"`
51 + SearchQueryLatencyMedian *int64 `json:"search_query_latency_median" stm:"search_query_latency_median"`
52 + SearchQueryLatency95 *int64 `json:"search_query_latency_95" stm:"search_query_latency_95"`
53 + SearchQueryLatency99 *int64 `json:"search_query_latency_99" stm:"search_query_latency_99"`
54 + SearchQueryLatency999 *int64 `json:"search_query_latency_999" stm:"search_query_latency_999"`
55 + SearchQueryLatencyMax *int64 `json:"search_query_latency_max" stm:"search_query_latency_max"`
56 +
57 + SearchIndexLatencyMin *int64 `json:"search_index_latency_min" stm:"search_index_latency_min"`
58 + SearchIndexLatencyMedian *int64 `json:"search_index_latency_median" stm:"search_index_latency_median"`
59 + SearchIndexLatency95 *int64 `json:"search_index_latency_95" stm:"search_index_latency_95"`
60 + SearchIndexLatency99 *int64 `json:"search_index_latency_99" stm:"search_index_latency_99"`
61 + SearchIndexLatency999 *int64 `json:"search_index_latency_999" stm:"search_index_latency_999"`
62 + SearchIndexLatencyMax *int64 `json:"search_index_latency_max" stm:"search_index_latency_max"`
63 +
64 + ConsistentGetTimeMean *int64 `json:"consistent_get_time_mean" stm:"consistent_get_time_mean"`
65 + ConsistentGetTimeMedian *int64 `json:"consistent_get_time_median" stm:"consistent_get_time_median"`
66 + ConsistentGetTime95 *int64 `json:"consistent_get_time_95" stm:"consistent_get_time_95"`
67 + ConsistentGetTime99 *int64 `json:"consistent_get_time_99" stm:"consistent_get_time_99"`
68 + ConsistentGetTime100 *int64 `json:"consistent_get_time_100" stm:"consistent_get_time_100"`
69 +
70 + ConsistentPutTimeMean *int64 `json:"consistent_put_time_mean" stm:"consistent_put_time_mean"`
71 + ConsistentPutTimeMedian *int64 `json:"consistent_put_time_median" stm:"consistent_put_time_median"`
72 + ConsistentPutTime95 *int64 `json:"consistent_put_time_95" stm:"consistent_put_time_95"`
73 + ConsistentPutTime99 *int64 `json:"consistent_put_time_99" stm:"consistent_put_time_99"`
74 + ConsistentPutTime100 *int64 `json:"consistent_put_time_100" stm:"consistent_put_time_100"`
75 +
76 + SysProcesses *int64 `json:"sys_processes" stm:"sys_processes"`
77 + MemoryProcesses *int64 `json:"memory_processes" stm:"memory_processes"`
78 + MemoryProcessesUsed *int64 `json:"memory_processes_used" stm:"memory_processes_used"`
79 +
80 + NodeGetFsmSiblingsMean *int64 `json:"node_get_fsm_siblings_mean" stm:"node_get_fsm_siblings_mean"`
81 + NodeGetFsmSiblingsMedian *int64 `json:"node_get_fsm_siblings_median" stm:"node_get_fsm_siblings_median"`
82 + NodeGetFsmSiblings99 *int64 `json:"node_get_fsm_siblings_99" stm:"node_get_fsm_siblings_99"`
83 + NodeGetFsmSiblings95 *int64 `json:"node_get_fsm_siblings_95" stm:"node_get_fsm_siblings_95"`
84 + NodeGetFsmSiblings100 *int64 `json:"node_get_fsm_siblings_100" stm:"node_get_fsm_siblings_100"`
85 +
86 + NodeGetFsmObjsizeMean *int64 `json:"node_get_fsm_objsize_mean" stm:"node_get_fsm_objsize_mean"`
87 + NodeGetFsmObjsizeMedian *int64 `json:"node_get_fsm_objsize_median" stm:"node_get_fsm_objsize_median"`
88 + NodeGetFsmObjsize95 *int64 `json:"node_get_fsm_objsize_95" stm:"node_get_fsm_objsize_95"`
89 + NodeGetFsmObjsize99 *int64 `json:"node_get_fsm_objsize_99" stm:"node_get_fsm_objsize_99"`
90 + NodeGetFsmObjsize100 *int64 `json:"node_get_fsm_objsize_100" stm:"node_get_fsm_objsize_100"`
91 +
92 + RiakSearchVnodeqMean *int64 `json:"riak_search_vnodeq_mean" stm:"riak_search_vnodeq_mean"`
93 + RiakSearchVnodeqMedian *int64 `json:"riak_search_vnodeq_median" stm:"riak_search_vnodeq_median"`
94 + RiakSearchVnodeq95 *int64 `json:"riak_search_vnodeq_95" stm:"riak_search_vnodeq_95"`
95 + RiakSearchVnodeq99 *int64 `json:"riak_search_vnodeq_99" stm:"riak_search_vnodeq_99"`
96 + RiakSearchVnodeq100 *int64 `json:"riak_search_vnodeq_100" stm:"riak_search_vnodeq_100"`
97 +
98 + SearchIndexFailCount *int64 `json:"search_index_fail_count" stm:"search_index_fail_count"`
99 + PbcActive *int64 `json:"pbc_active" stm:"pbc_active"`
100 + ReadRepairs *int64 `json:"read_repairs" stm:"read_repairs"`
101 +
102 + NodeGetFsmActive *int64 `json:"node_get_fsm_active" stm:"node_get_fsm_active"`
103 + NodePutFsmActive *int64 `json:"node_put_fsm_active" stm:"node_put_fsm_active"`
104 + IndexFsmActive *int64 `json:"index_fsm_active" stm:"index_fsm_active"`
105 + ListFsmActive *int64 `json:"list_fsm_active" stm:"list_fsm_active"`
106 +
107 + NodeGetFsmRejected *int64 `json:"node_get_fsm_rejected" stm:"node_get_fsm_rejected"`
108 + NodePutFsmRejected *int64 `json:"node_put_fsm_rejected" stm:"node_put_fsm_rejected"`
109 +
110 + SearchIndexBadEntryCount *int64 `json:"search_index_bad_entry_count" stm:"search_index_bad_entry_count"`
111 + SearchIndexExtractFailCount *int64 `json:"search_index_extract_fail_count" stm:"search_index_extract_fail_count"`
112 +}
src/go/plugin/go.d/modules/riakkv/testdata/config.json new
+20
@@ -0,0 +1,20 @@
1 +{
2 + "update_every": 123,
3 + "url": "ok",
4 + "body": "ok",
5 + "method": "ok",
6 + "headers": {
7 + "ok": "ok"
8 + },
9 + "username": "ok",
10 + "password": "ok",
11 + "proxy_url": "ok",
12 + "proxy_username": "ok",
13 + "proxy_password": "ok",
14 + "timeout": 123.123,
15 + "not_follow_redirects": true,
16 + "tls_ca": "ok",
17 + "tls_cert": "ok",
18 + "tls_key": "ok",
19 + "tls_skip_verify": true
20 +}
src/go/plugin/go.d/modules/riakkv/testdata/config.yaml new
+17
@@ -0,0 +1,17 @@
1 +update_every: 123
2 +url: "ok"
3 +body: "ok"
4 +method: "ok"
5 +headers:
6 + ok: "ok"
7 +username: "ok"
8 +password: "ok"
9 +proxy_url: "ok"
10 +proxy_username: "ok"
11 +proxy_password: "ok"
12 +timeout: 123.123
13 +not_follow_redirects: yes
14 +tls_ca: "ok"
15 +tls_cert: "ok"
16 +tls_key: "ok"
17 +tls_skip_verify: yes
src/go/plugin/go.d/modules/riakkv/testdata/stats.json new
+478
@@ -0,0 +1,478 @@
1 +{
2 + "connected_nodes": [],
3 + "consistent_get_objsize_100": 1,
4 + "consistent_get_objsize_95": 1,
5 + "consistent_get_objsize_99": 1,
6 + "consistent_get_objsize_mean": 1,
7 + "consistent_get_objsize_median": 1,
8 + "consistent_get_time_100": 1,
9 + "consistent_get_time_95": 1,
10 + "consistent_get_time_99": 1,
11 + "consistent_get_time_mean": 1,
12 + "consistent_get_time_median": 1,
13 + "consistent_gets": 1,
14 + "consistent_gets_total": 1,
15 + "consistent_put_objsize_100": 1,
16 + "consistent_put_objsize_95": 1,
17 + "consistent_put_objsize_99": 1,
18 + "consistent_put_objsize_mean": 1,
19 + "consistent_put_objsize_median": 1,
20 + "consistent_put_time_100": 1,
21 + "consistent_put_time_95": 1,
22 + "consistent_put_time_99": 1,
23 + "consistent_put_time_mean": 1,
24 + "consistent_put_time_median": 1,
25 + "consistent_puts": 1,
26 + "consistent_puts_total": 1,
27 + "converge_delay_last": 1,
28 + "converge_delay_max": 1,
29 + "converge_delay_mean": 1,
30 + "converge_delay_min": 1,
31 + "coord_redirs_total": 1,
32 + "counter_actor_counts_100": 1,
33 + "counter_actor_counts_95": 1,
34 + "counter_actor_counts_99": 1,
35 + "counter_actor_counts_mean": 1,
36 + "counter_actor_counts_median": 1,
37 + "cpu_avg1": 2276,
38 + "cpu_avg15": 661,
39 + "cpu_avg5": 1267,
40 + "cpu_nprocs": 1443,
41 + "dropped_vnode_requests_total": 1,
42 + "executing_mappers": 1,
43 + "gossip_received": 1,
44 + "handoff_timeouts": 1,
45 + "hll_bytes": 1,
46 + "hll_bytes_100": 1,
47 + "hll_bytes_95": 1,
48 + "hll_bytes_99": 1,
49 + "hll_bytes_mean": 1,
50 + "hll_bytes_median": 1,
51 + "hll_bytes_total": 1,
52 + "ignored_gossip_total": 1,
53 + "index_fsm_active": 1,
54 + "index_fsm_create": 1,
55 + "index_fsm_create_error": 1,
56 + "late_put_fsm_coordinator_ack": 1,
57 + "leveldb_read_block_error": "undefined",
58 + "list_fsm_active": 1,
59 + "list_fsm_create": 1,
60 + "list_fsm_create_error": 1,
61 + "list_fsm_create_error_total": 1,
62 + "list_fsm_create_total": 1,
63 + "map_actor_counts_100": 1,
64 + "map_actor_counts_95": 1,
65 + "map_actor_counts_99": 1,
66 + "map_actor_counts_mean": 1,
67 + "map_actor_counts_median": 1,
68 + "mem_allocated": 14529916928,
69 + "mem_total": 16728453121,
70 + "memory_atom": 695185,
71 + "memory_atom_used": 670675,
72 + "memory_binary": 15413608,
73 + "memory_code": 15375111,
74 + "memory_ets": 7728584,
75 + "memory_processes": 274468041,
76 + "memory_processes_used": 274337336,
77 + "memory_system": 126058328,
78 + "memory_total": 400526368,
79 + "node_get_fsm_active": 1,
80 + "node_get_fsm_active_60s": 20079,
81 + "node_get_fsm_counter_objsize_100": 1,
82 + "node_get_fsm_counter_objsize_95": 1,
83 + "node_get_fsm_counter_objsize_99": 1,
84 + "node_get_fsm_counter_objsize_mean": 1,
85 + "node_get_fsm_counter_objsize_median": 1,
86 + "node_get_fsm_counter_siblings_100": 1,
87 + "node_get_fsm_counter_siblings_95": 1,
88 + "node_get_fsm_counter_siblings_99": 1,
89 + "node_get_fsm_counter_siblings_mean": 1,
90 + "node_get_fsm_counter_siblings_median": 1,
91 + "node_get_fsm_counter_time_100": 1,
92 + "node_get_fsm_counter_time_95": 1,
93 + "node_get_fsm_counter_time_99": 1,
94 + "node_get_fsm_counter_time_mean": 1,
95 + "node_get_fsm_counter_time_median": 1,
96 + "node_get_fsm_errors": 1,
97 + "node_get_fsm_errors_total": 1,
98 + "node_get_fsm_hll_objsize_100": 1,
99 + "node_get_fsm_hll_objsize_95": 1,
100 + "node_get_fsm_hll_objsize_99": 1,
101 + "node_get_fsm_hll_objsize_mean": 1,
102 + "node_get_fsm_hll_objsize_median": 1,
103 + "node_get_fsm_hll_siblings_100": 1,
104 + "node_get_fsm_hll_siblings_95": 1,
105 + "node_get_fsm_hll_siblings_99": 1,
106 + "node_get_fsm_hll_siblings_mean": 1,
107 + "node_get_fsm_hll_siblings_median": 1,
108 + "node_get_fsm_hll_time_100": 1,
109 + "node_get_fsm_hll_time_95": 1,
110 + "node_get_fsm_hll_time_99": 1,
111 + "node_get_fsm_hll_time_mean": 1,
112 + "node_get_fsm_hll_time_median": 1,
113 + "node_get_fsm_in_rate": 181,
114 + "node_get_fsm_map_objsize_100": 1,
115 + "node_get_fsm_map_objsize_95": 1,
116 + "node_get_fsm_map_objsize_99": 1,
117 + "node_get_fsm_map_objsize_mean": 1,
118 + "node_get_fsm_map_objsize_median": 1,
119 + "node_get_fsm_map_siblings_100": 1,
120 + "node_get_fsm_map_siblings_95": 1,
121 + "node_get_fsm_map_siblings_99": 1,
122 + "node_get_fsm_map_siblings_mean": 1,
123 + "node_get_fsm_map_siblings_median": 1,
124 + "node_get_fsm_map_time_100": 1,
125 + "node_get_fsm_map_time_95": 1,
126 + "node_get_fsm_map_time_99": 1,
127 + "node_get_fsm_map_time_mean": 1,
128 + "node_get_fsm_map_time_median": 1,
129 + "node_get_fsm_objsize_100": 1037,
130 + "node_get_fsm_objsize_95": 1,
131 + "node_get_fsm_objsize_99": 1025,
132 + "node_get_fsm_objsize_mean": 791,
133 + "node_get_fsm_objsize_median": 669,
134 + "node_get_fsm_out_rate": 191,
135 + "node_get_fsm_rejected": 1,
136 + "node_get_fsm_rejected_60s": 1,
137 + "node_get_fsm_rejected_total": 1,
138 + "node_get_fsm_set_objsize_100": 1,
139 + "node_get_fsm_set_objsize_95": 1,
140 + "node_get_fsm_set_objsize_99": 1,
141 + "node_get_fsm_set_objsize_mean": 1,
142 + "node_get_fsm_set_objsize_median": 1,
143 + "node_get_fsm_set_siblings_100": 1,
144 + "node_get_fsm_set_siblings_95": 1,
145 + "node_get_fsm_set_siblings_99": 1,
146 + "node_get_fsm_set_siblings_mean": 1,
147 + "node_get_fsm_set_siblings_median": 1,
148 + "node_get_fsm_set_time_100": 1,
149 + "node_get_fsm_set_time_95": 1,
150 + "node_get_fsm_set_time_99": 1,
151 + "node_get_fsm_set_time_mean": 1,
152 + "node_get_fsm_set_time_median": 1,
153 + "node_get_fsm_siblings_100": 1,
154 + "node_get_fsm_siblings_95": 1,
155 + "node_get_fsm_siblings_99": 1,
156 + "node_get_fsm_siblings_mean": 1,
157 + "node_get_fsm_siblings_median": 1,
158 + "node_get_fsm_time_100": 678351,
159 + "node_get_fsm_time_95": 1,
160 + "node_get_fsm_time_99": 10148,
161 + "node_get_fsm_time_mean": 2161,
162 + "node_get_fsm_time_median": 1022,
163 + "node_gets": 19875,
164 + "node_gets_counter": 1,
165 + "node_gets_counter_total": 1,
166 + "node_gets_hll": 1,
167 + "node_gets_hll_total": 1,
168 + "node_gets_map": 1,
169 + "node_gets_map_total": 1,
170 + "node_gets_set": 1,
171 + "node_gets_set_total": 1,
172 + "node_gets_total": 422626,
173 + "node_put_fsm_active": 1,
174 + "node_put_fsm_active_60s": 10498,
175 + "node_put_fsm_counter_time_100": 1,
176 + "node_put_fsm_counter_time_95": 1,
177 + "node_put_fsm_counter_time_99": 1,
178 + "node_put_fsm_counter_time_mean": 1,
179 + "node_put_fsm_counter_time_median": 1,
180 + "node_put_fsm_hll_time_100": 1,
181 + "node_put_fsm_hll_time_95": 1,
182 + "node_put_fsm_hll_time_99": 1,
183 + "node_put_fsm_hll_time_mean": 1,
184 + "node_put_fsm_hll_time_median": 1,
185 + "node_put_fsm_in_rate": 116,
186 + "node_put_fsm_map_time_100": 1,
187 + "node_put_fsm_map_time_95": 1,
188 + "node_put_fsm_map_time_99": 1,
189 + "node_put_fsm_map_time_mean": 1,
190 + "node_put_fsm_map_time_median": 1,
191 + "node_put_fsm_out_rate": 127,
192 + "node_put_fsm_rejected": 1,
193 + "node_put_fsm_rejected_60s": 1,
194 + "node_put_fsm_rejected_total": 1,
195 + "node_put_fsm_set_time_100": 1,
196 + "node_put_fsm_set_time_95": 1,
197 + "node_put_fsm_set_time_99": 1,
198 + "node_put_fsm_set_time_mean": 1,
199 + "node_put_fsm_set_time_median": 1,
200 + "node_put_fsm_time_100": 1049568,
201 + "node_put_fsm_time_95": 19609,
202 + "node_put_fsm_time_99": 37735,
203 + "node_put_fsm_time_mean": 11828,
204 + "node_put_fsm_time_median": 5017,
205 + "node_puts": 10283,
206 + "node_puts_counter": 1,
207 + "node_puts_counter_total": 1,
208 + "node_puts_hll": 1,
209 + "node_puts_hll_total": 1,
210 + "node_puts_map": 1,
211 + "node_puts_map_total": 1,
212 + "node_puts_set": 1,
213 + "node_puts_set_total": 1,
214 + "node_puts_total": 490965,
215 + "nodename": "riak@127.0.0.1",
216 + "object_counter_merge": 1,
217 + "object_counter_merge_time_100": 1,
218 + "object_counter_merge_time_95": 1,
219 + "object_counter_merge_time_99": 1,
220 + "object_counter_merge_time_mean": 1,
221 + "object_counter_merge_time_median": 1,
222 + "object_counter_merge_total": 1,
223 + "object_hll_merge": 1,
224 + "object_hll_merge_time_100": 1,
225 + "object_hll_merge_time_95": 1,
226 + "object_hll_merge_time_99": 1,
227 + "object_hll_merge_time_mean": 1,
228 + "object_hll_merge_time_median": 1,
229 + "object_hll_merge_total": 1,
230 + "object_map_merge": 1,
231 + "object_map_merge_time_100": 1,
232 + "object_map_merge_time_95": 1,
233 + "object_map_merge_time_99": 1,
234 + "object_map_merge_time_mean": 1,
235 + "object_map_merge_time_median": 1,
236 + "object_map_merge_total": 1,
237 + "object_merge": 1,
238 + "object_merge_time_100": 1,
239 + "object_merge_time_95": 1,
240 + "object_merge_time_99": 1,
241 + "object_merge_time_mean": 1,
242 + "object_merge_time_median": 1,
243 + "object_merge_total": 7167,
244 + "object_set_merge": 1,
245 + "object_set_merge_time_100": 1,
246 + "object_set_merge_time_95": 1,
247 + "object_set_merge_time_99": 1,
248 + "object_set_merge_time_mean": 1,
249 + "object_set_merge_time_median": 1,
250 + "object_set_merge_total": 1,
251 + "pbc_active": 46,
252 + "pbc_connects": 1,
253 + "pbc_connects_total": 48,
254 + "pipeline_active": 1,
255 + "pipeline_create_count": 1,
256 + "pipeline_create_error_count": 1,
257 + "pipeline_create_error_one": 1,
258 + "pipeline_create_one": 1,
259 + "postcommit_fail": 1,
260 + "precommit_fail": 1,
261 + "read_repairs": 1,
262 + "read_repairs_counter": 1,
263 + "read_repairs_counter_total": 1,
264 + "read_repairs_fallback_notfound_count": "undefined",
265 + "read_repairs_fallback_notfound_one": "undefined",
266 + "read_repairs_fallback_outofdate_count": "undefined",
267 + "read_repairs_fallback_outofdate_one": "undefined",
268 + "read_repairs_hll": 1,
269 + "read_repairs_hll_total": 1,
270 + "read_repairs_map": 1,
271 + "read_repairs_map_total": 1,
272 + "read_repairs_primary_notfound_count": 186,
273 + "read_repairs_primary_notfound_one": 1,
274 + "read_repairs_primary_outofdate_count": 24,
275 + "read_repairs_primary_outofdate_one": 1,
276 + "read_repairs_set": 1,
277 + "read_repairs_set_total": 1,
278 + "read_repairs_total": 105,
279 + "rebalance_delay_last": 1,
280 + "rebalance_delay_max": 1,
281 + "rebalance_delay_mean": 1,
282 + "rebalance_delay_min": 1,
283 + "rejected_handoffs": 1,
284 + "riak_kv_vnodeq_max": 3,
285 + "riak_kv_vnodeq_mean": 0.078125,
286 + "riak_kv_vnodeq_median": 1,
287 + "riak_kv_vnodeq_min": 1,
288 + "riak_kv_vnodeq_total": 5,
289 + "riak_kv_vnodes_running": 64,
290 + "riak_pipe_vnodeq_max": 1,
291 + "riak_pipe_vnodeq_mean": 1,
292 + "riak_pipe_vnodeq_median": 1,
293 + "riak_pipe_vnodeq_min": 1,
294 + "riak_pipe_vnodeq_total": 1,
295 + "riak_pipe_vnodes_running": 64,
296 + "ring_creation_size": 64,
297 + "ring_members": [
298 + "riak@127.0.0.1"
299 + ],
300 + "ring_num_partitions": 64,
301 + "ring_ownership": "[{'riak@127.0.0.1',64}]",
302 + "rings_reconciled": 1,
303 + "rings_reconciled_total": 1,
304 + "set_actor_counts_100": 1,
305 + "set_actor_counts_95": 1,
306 + "set_actor_counts_99": 1,
307 + "set_actor_counts_mean": 1,
308 + "set_actor_counts_median": 1,
309 + "skipped_read_repairs": 1,
310 + "skipped_read_repairs_total": 1,
311 + "storage_backend": "riak_kv_bitcask_backend",
312 + "sys_driver_version": "2.2",
313 + "sys_global_heaps_size": "deprecated",
314 + "sys_heap_type": "private",
315 + "sys_logical_processors": 4,
316 + "sys_monitor_count": 966,
317 + "sys_otp_release": "R16B02_basho10",
318 + "sys_port_count": 336,
319 + "sys_process_count": 2169,
320 + "sys_smp_support": true,
321 + "sys_system_architecture": "x86_64-unknown-linux-gnu",
322 + "sys_system_version": "Erlang R16B02_basho10 (erts-5.10.3) [source] [64-bit] [smp:4:4] [async-threads:64] [hipe] [kernel-poll:true] [frame-pointer]",
323 + "sys_thread_pool_size": 64,
324 + "sys_threads_enabled": true,
325 + "sys_wordsize": 8,
326 + "vnode_counter_update": 1,
327 + "vnode_counter_update_time_100": 1,
328 + "vnode_counter_update_time_95": 1,
329 + "vnode_counter_update_time_99": 1,
330 + "vnode_counter_update_time_mean": 1,
331 + "vnode_counter_update_time_median": 1,
332 + "vnode_counter_update_total": 1,
333 + "vnode_get_fsm_time_100": 836988,
334 + "vnode_get_fsm_time_95": 3415,
335 + "vnode_get_fsm_time_99": 7394,
336 + "vnode_get_fsm_time_mean": 1159,
337 + "vnode_get_fsm_time_median": 461,
338 + "vnode_gets": 59641,
339 + "vnode_gets_total": 1267893,
340 + "vnode_hll_update": 1,
341 + "vnode_hll_update_time_100": 1,
342 + "vnode_hll_update_time_95": 1,
343 + "vnode_hll_update_time_99": 1,
344 + "vnode_hll_update_time_mean": 1,
345 + "vnode_hll_update_time_median": 1,
346 + "vnode_hll_update_total": 1,
347 + "vnode_index_deletes": 1,
348 + "vnode_index_deletes_postings": 1,
349 + "vnode_index_deletes_postings_total": 1,
350 + "vnode_index_deletes_total": 1,
351 + "vnode_index_reads": 1,
352 + "vnode_index_reads_total": 1,
353 + "vnode_index_refreshes": 1,
354 + "vnode_index_refreshes_total": 1,
355 + "vnode_index_writes": 1,
356 + "vnode_index_writes_postings": 1,
357 + "vnode_index_writes_postings_total": 1,
358 + "vnode_index_writes_total": 1,
359 + "vnode_map_update": 1,
360 + "vnode_map_update_time_100": 1,
361 + "vnode_map_update_time_95": 1,
362 + "vnode_map_update_time_99": 1,
363 + "vnode_map_update_time_mean": 1,
364 + "vnode_map_update_time_median": 1,
365 + "vnode_map_update_total": 1,
366 + "vnode_put_fsm_time_100": 1034955,
367 + "vnode_put_fsm_time_95": 10302,
368 + "vnode_put_fsm_time_99": 16813,
369 + "vnode_put_fsm_time_mean": 4511,
370 + "vnode_put_fsm_time_median": 1927,
371 + "vnode_puts": 30852,
372 + "vnode_puts_total": 1473108,
373 + "vnode_set_update": 1,
374 + "vnode_set_update_time_100": 1,
375 + "vnode_set_update_time_95": 1,
376 + "vnode_set_update_time_99": 1,
377 + "vnode_set_update_time_mean": 1,
378 + "vnode_set_update_time_median": 1,
379 + "vnode_set_update_total": 1,
380 + "write_once_merge": 1,
381 + "write_once_put_objsize_100": 1,
382 + "write_once_put_objsize_95": 1,
383 + "write_once_put_objsize_99": 1,
384 + "write_once_put_objsize_mean": 1,
385 + "write_once_put_objsize_median": 1,
386 + "write_once_put_time_100": 1,
387 + "write_once_put_time_95": 1,
388 + "write_once_put_time_99": 1,
389 + "write_once_put_time_mean": 1,
390 + "write_once_put_time_median": 1,
391 + "write_once_puts": 1,
392 + "write_once_puts_total": 1,
393 + "disk": [
394 + {
395 + "id": "/",
396 + "size": 488386584,
397 + "used": 11
398 + },
399 + {
400 + "id": "/dev",
401 + "size": 65536,
402 + "used": 0
403 + },
404 + {
405 + "id": "/sys/fs/cgroup",
406 + "size": 8168188,
407 + "used": 0
408 + },
409 + {
410 + "id": "/etc/hosts",
411 + "size": 488386584,
412 + "used": 11
413 + },
414 + {
415 + "id": "/dev/shm",
416 + "size": 65536,
417 + "used": 0
418 + },
419 + {
420 + "id": "/proc/asound",
421 + "size": 8168188,
422 + "used": 0
423 + },
424 + {
425 + "id": "/proc/acpi",
426 + "size": 8168188,
427 + "used": 0
428 + },
429 + {
430 + "id": "/sys/firmware",
431 + "size": 8168188,
432 + "used": 0
433 + }
434 + ],
435 + "riak_auth_mods_version": "2.1.0-0-g31b8b30",
436 + "erlydtl_version": "0.7.0",
437 + "riak_control_version": "2.1.6-0-gcbf605a",
438 + "cluster_info_version": "2.0.5-0-gd61d055",
439 + "yokozuna_version": "2.1.10-0-gb53d999",
440 + "fuse_version": "2.1.0",
441 + "ibrowse_version": "4.0.2",
442 + "riak_search_version": "2.1.6-0-g0d398f2",
443 + "merge_index_version": "2.0.4-0-gc5efac6",
444 + "riak_kv_version": "2.1.7-0-gbd8e312",
445 + "riak_api_version": "2.1.6-0-ga678e25",
446 + "riak_pb_version": "2.2.0.0-0-gf5af9ff",
447 + "protobuffs_version": "0.9.0-0-g0dde9d3",
448 + "riak_dt_version": "2.1.3-0-g9450044",
449 + "sidejob_version": "2.0.1-0-g8ac6803",
450 + "riak_pipe_version": "2.1.5-0-g8b2c842",
451 + "riak_core_version": "2.1.9-0-gb8a11b4",
452 + "exometer_core_version": "1.0.0-basho9-0-gfcc8662",
453 + "poolboy_version": "0.8.1p3-0-g8bb45fb",
454 + "pbkdf2_version": "2.0.0-0-g7076584",
455 + "eleveldb_version": "2.0.34-0-g55abc57",
456 + "clique_version": "0.3.9-0-ge7114e9",
457 + "bitcask_version": "2.0.3",
458 + "basho_stats_version": "1.0.3",
459 + "webmachine_version": "1.10.8-basho1-0-g494d14f",
460 + "mochiweb_version": "2.9.0",
461 + "inets_version": "5.9.6",
462 + "xmerl_version": "1.3.4",
463 + "erlang_js_version": "1.3.0-0-g07467d8",
464 + "runtime_tools_version": "1.8.12",
465 + "os_mon_version": "2.2.13",
466 + "riak_sysmon_version": "2.1.5-0-g0ab94b3",
467 + "ssl_version": "5.3.1",
468 + "public_key_version": "0.20",
469 + "crypto_version": "3.1",
470 + "asn1_version": "2.0.3",
471 + "sasl_version": "2.3.3",
472 + "lager_version": "3.2.2",
473 + "goldrush_version": "0.1.9",
474 + "compiler_version": "4.9.3",
475 + "syntax_tools_version": "1.6.11",
476 + "stdlib_version": "1.19.3",
477 + "kernel_version": "2.16.3"
478 +}