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 }