bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/cassandra_unix.go (about)

     1  // +build darwin linux
     2  
     3  package collectors
     4  
     5  import (
     6  	"strconv"
     7  	"strings"
     8  
     9  	"bosun.org/metadata"
    10  	"bosun.org/opentsdb"
    11  	"bosun.org/util"
    12  )
    13  
    14  type MetricSet map[string]string
    15  
    16  func init() {
    17  	collectors = append(collectors, &IntervalCollector{F: c_nodestats_cfstats_linux})
    18  }
    19  
    20  func c_nodestats_cfstats_linux() (opentsdb.MultiDataPoint, error) {
    21  	var md opentsdb.MultiDataPoint
    22  	var keyspace, table string
    23  	util.ReadCommand(func(line string) error {
    24  		fields := strings.Split(strings.TrimSpace(line), ": ")
    25  		if len(fields) != 2 {
    26  			return nil
    27  		}
    28  		if fields[0] == "Keyspace" {
    29  			keyspace = fields[1]
    30  			table = ""
    31  			return nil
    32  		}
    33  		if fields[0] == "Table" {
    34  			table = fields[1]
    35  			return nil
    36  		}
    37  
    38  		tagset := make(opentsdb.TagSet)
    39  		metricset := make(MetricSet)
    40  
    41  		if table != "" {
    42  			tagset["table"] = table
    43  		}
    44  		if keyspace != "" {
    45  			tagset["keyspace"] = keyspace
    46  		}
    47  
    48  		metric := strings.Replace(fields[0], " ", "_", -1)
    49  		metric = strings.Replace(metric, "(", "", -1)
    50  		metric = strings.Replace(metric, ")", "", -1)
    51  		metric = strings.Replace(metric, ",", "", -1)
    52  		metric = strings.ToLower(metric)
    53  
    54  		/*  This is to handle lines like "SSTables in each level: [31/4, 0, 0, 0, 0, 0, 0, 0]"
    55  		sstables_in_each_level format (BNF):
    56  		     <count>         ::= <integer>
    57  		     <max_threshold> ::= <integer>
    58  		     <exceeded>      ::= <count> "/" <max_threshold>
    59  		     <level_item>    ::= <count>|<exceeded>
    60  		     <list_item>     ::= <level_item> "," " " | <level_item>
    61  		     <list>          ::= <list_item> | <list_item> <list>
    62  		     <per_level>     ::= "[" <list> "]"
    63  		*/
    64  		if metric == "sstables_in_each_level" {
    65  			fields[1] = strings.Replace(fields[1], "[", "", -1)
    66  			fields[1] = strings.Replace(fields[1], "]", "", -1)
    67  			per_level := strings.Split(fields[1], ", ")
    68  			for index, count := range per_level {
    69  				metricset["cassandra.tables.sstables_in_level_"+strconv.Itoa(index)] = strings.Split(count, "/")[0]
    70  			}
    71  			submitMetrics(&md, metricset, tagset)
    72  			return nil
    73  		}
    74  
    75  		// every other value is simpler, and we only want the first word
    76  		values := strings.Fields(fields[1])
    77  		if _, err := strconv.ParseFloat(values[0], 64); err != nil || values[0] == "NaN" {
    78  			return nil
    79  		}
    80  
    81  		metricset["cassandra.tables."+metric] = values[0]
    82  
    83  		submitMetrics(&md, metricset, tagset)
    84  		return nil
    85  	}, "nodetool", "cfstats")
    86  	return md, nil
    87  }
    88  
    89  func submitMetrics(md *opentsdb.MultiDataPoint, metricset MetricSet, tagset opentsdb.TagSet) {
    90  	for m, v := range metricset {
    91  		Add(md, m, v, tagset, metadata.Unknown, metadata.None, "")
    92  	}
    93  }