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
+}