master
go 160 lines 4 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package cockroachdb
4
5 import (
6 "errors"
7
8 "github.com/netdata/netdata/go/plugins/pkg/prometheus"
9 "github.com/netdata/netdata/go/plugins/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 *Collector) 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 for _, m := range scraped.FindByName(name) {
44 if isMetricFloat(name) {
45 mx[name] += m.Value * precision
46 } else {
47 mx[name] += m.Value
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 }