github.com/netdata/go.d.plugin@v0.58.1/modules/cockroachdb/collect.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package cockroachdb 4 5 import ( 6 "errors" 7 8 "github.com/netdata/go.d.plugin/pkg/prometheus" 9 "github.com/netdata/go.d.plugin/pkg/stm" 10 ) 11 12 func validCockroachDBMetrics(scraped prometheus.Series) bool { 13 return scraped.FindByName("sql_restart_savepoint_count_internal").Len() > 0 14 } 15 16 func (c *CockroachDB) collect() (map[string]int64, error) { 17 scraped, err := c.prom.ScrapeSeries() 18 if err != nil { 19 return nil, err 20 } 21 22 if !validCockroachDBMetrics(scraped) { 23 return nil, errors.New("returned metrics aren't CockroachDB metrics") 24 } 25 26 mx := collectScraped(scraped, metrics) 27 calcUsableCapacity(mx) 28 calcUnusableCapacity(mx) 29 calcTotalCapacityUsedPercentage(mx) 30 calcUsableCapacityUsedPercentage(mx) 31 calcRocksDBCacheHitRate(mx) 32 calcActiveReplicas(mx) 33 calcCPUUsagePercent(mx) 34 35 return stm.ToMap(mx), nil 36 } 37 38 const precision = 1000 39 40 func collectScraped(scraped prometheus.Series, metricList []string) map[string]float64 { 41 mx := make(map[string]float64) 42 for _, name := range metricList { 43 if ms := scraped.FindByName(name); ms.Len() == 1 { 44 if isMetricFloat(name) { 45 mx[name] = ms.Max() * precision 46 } else { 47 mx[name] = ms.Max() 48 } 49 } 50 } 51 return mx 52 } 53 54 func calcUsableCapacity(mx map[string]float64) { 55 if !hasAll(mx, metricCapacityAvailable, metricCapacityUsed) { 56 return 57 } 58 available := mx[metricCapacityAvailable] 59 used := mx[metricCapacityUsed] 60 61 mx[metricCapacityUsable] = available + used 62 } 63 64 func calcUnusableCapacity(mx map[string]float64) { 65 if !hasAll(mx, metricCapacity, metricCapacityAvailable, metricCapacityUsed) { 66 return 67 } 68 total := mx[metricCapacity] 69 available := mx[metricCapacityAvailable] 70 used := mx[metricCapacityUsed] 71 72 mx[metricCapacityUnusable] = total - (available + used) 73 } 74 75 func calcTotalCapacityUsedPercentage(mx map[string]float64) { 76 if !hasAll(mx, metricCapacity, metricCapacityUnusable, metricCapacityUsed) { 77 return 78 } 79 total := mx[metricCapacity] 80 unusable := mx[metricCapacityUnusable] 81 used := mx[metricCapacityUsed] 82 83 if mx[metricCapacity] == 0 { 84 mx[metricCapacityUsedPercentage] = 0 85 } else { 86 mx[metricCapacityUsedPercentage] = (unusable + used) / total * 100 * precision 87 } 88 } 89 90 func calcUsableCapacityUsedPercentage(mx map[string]float64) { 91 if !hasAll(mx, metricCapacityUsable, metricCapacityUsed) { 92 return 93 } 94 usable := mx[metricCapacityUsable] 95 used := mx[metricCapacityUsed] 96 97 if usable == 0 { 98 mx[metricCapacityUsableUsedPercentage] = 0 99 } else { 100 mx[metricCapacityUsableUsedPercentage] = used / usable * 100 * precision 101 } 102 } 103 104 func calcRocksDBCacheHitRate(mx map[string]float64) { 105 if !hasAll(mx, metricRocksDBBlockCacheHits, metricRocksDBBlockCacheMisses) { 106 return 107 } 108 hits := mx[metricRocksDBBlockCacheHits] 109 misses := mx[metricRocksDBBlockCacheMisses] 110 111 if sum := hits + misses; sum == 0 { 112 mx[metricRocksDBBlockCacheHitRate] = 0 113 } else { 114 mx[metricRocksDBBlockCacheHitRate] = hits / sum * 100 * precision 115 } 116 } 117 118 func calcActiveReplicas(mx map[string]float64) { 119 if !hasAll(mx, metricReplicasQuiescent) { 120 return 121 } 122 total := mx[metricReplicas] 123 quiescent := mx[metricReplicasQuiescent] 124 125 mx[metricReplicasActive] = total - quiescent 126 } 127 128 func calcCPUUsagePercent(mx map[string]float64) { 129 if hasAll(mx, metricSysCPUUserPercent) { 130 mx[metricSysCPUUserPercent] *= 100 131 } 132 if hasAll(mx, metricSysCPUSysPercent) { 133 mx[metricSysCPUSysPercent] *= 100 134 } 135 if hasAll(mx, metricSysCPUCombinedPercentNormalized) { 136 mx[metricSysCPUCombinedPercentNormalized] *= 100 137 } 138 } 139 140 func isMetricFloat(name string) bool { 141 // only Float metrics (see NewGaugeFloat64 in the cockroach repo): 142 // - GcPausePercent, CPUUserPercent, CPUCombinedPercentNorm, AverageQueriesPerSecond, AverageWritesPerSecond 143 switch name { 144 case metricSysCPUUserPercent, 145 metricSysCPUSysPercent, 146 metricSysCPUCombinedPercentNormalized, 147 metricRebalancingQueriesPerSecond, 148 metricRebalancingWritesPerSecond: 149 return true 150 } 151 return false 152 } 153 154 func hasAll(mx map[string]float64, key string, rest ...string) bool { 155 _, ok := mx[key] 156 if len(rest) == 0 { 157 return ok 158 } 159 return ok && hasAll(mx, rest[0], rest[1:]...) 160 }