11package main
22
33import (
4+ "bytes"
45 "strings"
56
67 as "github.com/aerospike/aerospike-client-go"
9091 counter ("client_write_error" , "client write error" ),
9192 counter ("client_write_success" , "client write success" ),
9293 counter ("client_write_timeout" , "client write timeout" ),
93- counter ("defrag_reads" , "defrag reads" ),
94- counter ("defrag_writes" , "defrag writes" ),
9594 counter ("evicted_objects" , "evicted objects" ),
9695 counter ("expired_objects" , "expired objects" ),
9796 counter ("fail_generation" , "fail generation" ),
@@ -166,7 +165,6 @@ var (
166165 counter ("xdr_write_success" , "xdr write success" ),
167166 counter ("xdr_write_timeout" , "xdr write timeout" ),
168167 gauge ("available_bin_names" , "available bin names" ),
169- // broken gauge("defrag_q", "defrag queue"),
170168 gauge ("device_available_pct" , "device available pct" ),
171169 gauge ("device_compression_ratio" , "device compression ratio" ),
172170 gauge ("device_free_pct" , "device free pct" ),
@@ -216,7 +214,6 @@ var (
216214 gauge ("prole_objects" , "prole objects" ),
217215 gauge ("prole_tombstones" , "prole tombstones" ),
218216 gauge ("replication-factor" , "replication factor" ),
219- // broken gauge("shadow_write_q", "shadow write queue"),
220217 gauge ("stop_writes" , "stop writes" ),
221218 gauge ("stop-writes-pct" , "stop writes pct" ),
222219 gauge ("tombstones" , "tombstones" ),
@@ -225,10 +222,16 @@ var (
225222 gauge ("dead_partitions" , "dead partitions" ),
226223 gauge ("unavailable_partitions" , "unavailable partitions" ),
227224 gauge ("rack-id" , "rack id" ),
228- // gauge("write_q", "write queue"),
229225 // device-level stats don't appear to work
230226 // and this plugin thinks "storage-engine.device[0].write_q" is malformed.
231227 }
228+ NamespaceStorageMetrics = []metric {
229+ counter ("defrag_reads" , "defrag reads" ),
230+ counter ("defrag_writes" , "defrag writes" ),
231+ gauge ("shadow_write_q" , "shadow write queue" ),
232+ gauge ("defrag_q" , "defrag queue" ),
233+ gauge ("write_q" , "write queue" ),
234+ }
232235)
233236
234237type nsCollector cmetrics
@@ -246,6 +249,18 @@ func newNSCollector() nsCollector {
246249 ),
247250 }
248251 }
252+ for _ , m := range NamespaceStorageMetrics {
253+ ns [m .aeroName ] = cmetric {
254+ typ : m .typ ,
255+ desc : prometheus .NewDesc (
256+ promkey (systemNamespace , m .aeroName ),
257+ m .desc ,
258+ []string {"namespace" , "mount" },
259+ nil ,
260+ ),
261+ }
262+ }
263+
249264 return ns
250265}
251266
@@ -255,21 +270,85 @@ func (nc nsCollector) describe(ch chan<- *prometheus.Desc) {
255270 }
256271}
257272
273+ func (nc nsCollector ) parseStorage (s string , d string ) (string , error ) {
274+ // the function remove the storage prefix metrics for each device:
275+ // d is storage-engine.device[ix]
276+ // s is all storage metrics that has been scraped
277+ // storage-engine.device[ix].age -> age
278+ // https://www.aerospike.com/docs/reference/metrics/#storage-engine.device[ix].age
279+ buf := bytes.Buffer {}
280+ for _ , l := range strings .Split (s , ";" ) {
281+ for _ , v := range strings .Split (l , ":" ) {
282+ kv := strings .SplitN (v , "=" , 2 )
283+ if len (kv ) > 1 {
284+ if strings .HasPrefix (kv [0 ], d ) {
285+ //todo: optimize
286+ kv [0 ] = strings .Replace (kv [0 ]+ "." , d , "" , 1 )
287+ kv [0 ] = strings .Replace (kv [0 ], "." , "" , - 1 )
288+ }
289+ buf .WriteString (kv [0 ] + "=" + kv [1 ] + ";" )
290+ }
291+ }
292+ }
293+ r := buf .String ()
294+ return r , nil
295+ }
296+
297+ func (nc nsCollector ) splitInfo (s string ) (string , string , map [string ]string ) {
298+ nsStorageMounts := map [string ]string {}
299+
300+ bufStandardMetrics := bytes.Buffer {}
301+ bufStorageMetrics := bytes.Buffer {}
302+
303+ for _ , l := range strings .Split (s , ";" ) {
304+ for _ , v := range strings .Split (l , ":" ) {
305+ kv := strings .SplitN (v , "=" , 2 )
306+ if strings .HasPrefix (kv [0 ], "storage-engine" ) {
307+ bufStorageMetrics .WriteString (v + ";" )
308+ if strings .HasSuffix (kv [0 ], "]" ) {
309+ nsStorageMounts [kv [1 ]] = kv [0 ]
310+ }
311+ } else {
312+ bufStandardMetrics .WriteString (v + ";" )
313+ }
314+ }
315+ }
316+ nsStandardMetrics := bufStandardMetrics .String ()
317+ nsStorageMetrics := bufStorageMetrics .String ()
318+ return nsStorageMetrics , nsStandardMetrics , nsStorageMounts
319+ }
320+
258321func (nc nsCollector ) collect (conn * as.Connection ) ([]prometheus.Metric , error ) {
259322 info , err := as .RequestInfo (conn , "namespaces" )
260323 if err != nil {
261324 return nil , err
262325 }
263326 var metrics []prometheus.Metric
264327 for _ , ns := range strings .Split (info ["namespaces" ], ";" ) {
265- nsinfo , err := as .RequestInfo (conn , "namespace/" + ns )
328+ nsInfo , err := as .RequestInfo (conn , "namespace/" + ns )
266329 if err != nil {
267330 return nil , err
268331 }
332+
333+ nsInfoStorage , nsInfoStandard , nsInfoStorageDevices := nc .splitInfo (nsInfo ["namespace/" + ns ])
334+
269335 metrics = append (
270336 metrics ,
271- infoCollect (cmetrics (nc ), nsinfo [ "namespace/" + ns ] , ns )... ,
337+ infoCollect (cmetrics (nc ), nsInfoStandard , ns )... ,
272338 )
339+
340+ for mountName , metricName := range nsInfoStorageDevices {
341+ nsInfoStorage , err = nc .parseStorage (nsInfoStorage , metricName )
342+
343+ if err != nil {
344+ return nil , err
345+ }
346+
347+ metrics = append (
348+ metrics ,
349+ infoCollect (cmetrics (nc ), nsInfoStorage , ns , mountName )... ,
350+ )
351+ }
273352 }
274353 return metrics , nil
275354}
0 commit comments