master
go 226 lines 8.77 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package vsphere
4
5 import (
6 "github.com/netdata/netdata/go/plugins/pkg/metrix"
7 rs "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/resources"
8 scrapepkg "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/scrape"
9 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/oldmetrix"
10 )
11
12 const (
13 vsanClusterSpaceUsageTotalMetric = "vsan_cluster_space_usage_total"
14 vsanClusterSpaceUsageFreeMetric = "vsan_cluster_space_usage_free"
15 vsanClusterSpaceUsageUsedMetric = "vsan_cluster_space_usage_used"
16 vsanClusterSpaceUtilizationUsedMetric = "vsan_cluster_space_utilization_used"
17 vsanClusterHealthStatusGreenMetric = "vsan_cluster_health_status_green"
18 vsanClusterHealthStatusYellowMetric = "vsan_cluster_health_status_yellow"
19 vsanClusterHealthStatusRedMetric = "vsan_cluster_health_status_red"
20 vsanClusterHealthStatusUnknownMetric = "vsan_cluster_health_status_unknown"
21 vsanClusterOperationsReadMetric = "vsan_cluster_operations_read"
22 vsanClusterOperationsWriteMetric = "vsan_cluster_operations_write"
23 vsanClusterThroughputReadMetric = "vsan_cluster_throughput_read"
24 vsanClusterThroughputWriteMetric = "vsan_cluster_throughput_write"
25 vsanClusterLatencyReadMetric = "vsan_cluster_latency_read"
26 vsanClusterLatencyWriteMetric = "vsan_cluster_latency_write"
27 vsanClusterCongestionsMetric = "vsan_cluster_congestions"
28 vsanHostOperationsReadMetric = "vsan_host_operations_read"
29 vsanHostOperationsWriteMetric = "vsan_host_operations_write"
30 vsanHostThroughputReadMetric = "vsan_host_throughput_read"
31 vsanHostThroughputWriteMetric = "vsan_host_throughput_write"
32 vsanHostLatencyReadMetric = "vsan_host_latency_read"
33 vsanHostLatencyWriteMetric = "vsan_host_latency_write"
34 vsanHostCongestionsMetric = "vsan_host_congestions"
35 vsanHostCacheHitRateMetric = "vsan_host_cache_hit_rate"
36 vsanVMOperationsReadMetric = "vsan_vm_operations_read"
37 vsanVMOperationsWriteMetric = "vsan_vm_operations_write"
38 vsanVMThroughputReadMetric = "vsan_vm_throughput_read"
39 vsanVMThroughputWriteMetric = "vsan_vm_throughput_write"
40 vsanVMLatencyReadMetric = "vsan_vm_latency_read"
41 vsanVMLatencyWriteMetric = "vsan_vm_latency_write"
42 vsanUUIDLabel = "vsan_uuid"
43 vsanNodeUUIDLabel = "vsan_node_uuid"
44 vmInstanceUUIDLabel = "vm_instance_uuid"
45 )
46
47 func (c *Collector) writeVSANMetrics() {
48 if !c.CollectVSAN || c.resources == nil || c.vsanMetrics == nil {
49 return
50 }
51 c.writeVSANClusterSpaceMetrics()
52 c.writeVSANClusterHealthMetrics()
53 c.writeVSANClusterPerformanceMetrics()
54 c.writeVSANHostPerformanceMetrics()
55 c.writeVSANVMPerformanceMetrics()
56 }
57
58 func (c *Collector) vsanResources() (rs.Clusters, rs.Hosts, rs.VMs) {
59 clusters := make(rs.Clusters)
60 hosts := make(rs.Hosts)
61 vms := make(rs.VMs)
62
63 clusterMatcher := c.vsanClusterMatcher
64 hostMatcher := c.vsanHostMatcher
65 vmMatcher := c.vsanVMMatcher
66
67 selectedClusters := make(map[string]bool)
68 for _, cluster := range sortedClusters(c.resources.Clusters) {
69 if !cluster.VSANEnabled || (clusterMatcher != nil && !clusterMatcher.Match(cluster)) {
70 continue
71 }
72 clusters[cluster.ID] = cluster
73 selectedClusters[cluster.ID] = true
74 }
75
76 for _, host := range sortedHosts(c.resources.Hosts) {
77 if !selectedClusters[host.Hier.Cluster.ID] || host.VSANNodeUUID == "" || (hostMatcher != nil && !hostMatcher.Match(host)) {
78 continue
79 }
80 hosts[host.ID] = host
81 }
82
83 for _, vm := range sortedVMs(c.resources.VMs) {
84 if !selectedClusters[vm.Hier.Cluster.ID] || vm.InstanceUUID == "" || (vmMatcher != nil && !vmMatcher.Match(vm)) {
85 continue
86 }
87 vms[vm.ID] = vm
88 }
89
90 return clusters, hosts, vms
91 }
92
93 func (c *Collector) writeVSANClusterSpaceMetrics() {
94 for _, id := range sortedMapKeys(c.vsanMetrics.Space) {
95 cluster := c.resources.Clusters.Get(id)
96 if cluster == nil {
97 continue
98 }
99 space := c.vsanMetrics.Space[id]
100 used := max(space.Total-space.Free, 0)
101 labels := c.labelSet(c.vsanClusterLabels(cluster))
102 c.observeGaugeFloat(vsanClusterSpaceUsageTotalMetric, float64(space.Total), labels)
103 c.observeGaugeFloat(vsanClusterSpaceUsageFreeMetric, float64(space.Free), labels)
104 c.observeGaugeFloat(vsanClusterSpaceUsageUsedMetric, float64(used), labels)
105 if space.Total > 0 {
106 c.observeGaugeFloat(vsanClusterSpaceUtilizationUsedMetric, float64(used)/float64(space.Total)*scaledPercent, labels)
107 } else {
108 c.observeGaugeFloat(vsanClusterSpaceUtilizationUsedMetric, 0, labels)
109 }
110 }
111 }
112
113 func (c *Collector) writeVSANClusterHealthMetrics() {
114 for _, id := range sortedMapKeys(c.vsanMetrics.Health) {
115 cluster := c.resources.Clusters.Get(id)
116 if cluster == nil {
117 continue
118 }
119 health := c.vsanMetrics.Health[id]
120 labels := c.labelSet(c.vsanClusterLabels(cluster))
121 c.observeGaugeFloat(vsanClusterHealthStatusGreenMetric, float64(oldmetrix.Bool(health == "green")), labels)
122 c.observeGaugeFloat(vsanClusterHealthStatusYellowMetric, float64(oldmetrix.Bool(health == "yellow")), labels)
123 c.observeGaugeFloat(vsanClusterHealthStatusRedMetric, float64(oldmetrix.Bool(health == "red")), labels)
124 c.observeGaugeFloat(vsanClusterHealthStatusUnknownMetric, float64(oldmetrix.Bool(health != "green" && health != "yellow" && health != "red")), labels)
125 }
126 }
127
128 func (c *Collector) writeVSANClusterPerformanceMetrics() {
129 for _, id := range sortedMapKeys(c.vsanMetrics.Clusters) {
130 cluster := c.resources.Clusters.Get(id)
131 if cluster == nil {
132 continue
133 }
134 labels := c.labelSet(c.vsanClusterLabels(cluster))
135 writeVSANPerformanceValues(c, labels, c.vsanMetrics.Clusters[id], vsanClusterPerfMetricByName)
136 }
137 }
138
139 func (c *Collector) writeVSANHostPerformanceMetrics() {
140 for _, id := range sortedMapKeys(c.vsanMetrics.Hosts) {
141 host := c.resources.Hosts.Get(id)
142 if host == nil {
143 continue
144 }
145 labels := c.labelSet(c.vsanHostLabels(host))
146 writeVSANPerformanceValues(c, labels, c.vsanMetrics.Hosts[id], vsanHostPerfMetricByName)
147 }
148 }
149
150 func (c *Collector) writeVSANVMPerformanceMetrics() {
151 for _, id := range sortedMapKeys(c.vsanMetrics.VMs) {
152 vm := c.resources.VMs.Get(id)
153 if vm == nil {
154 continue
155 }
156 labels := c.labelSet(c.vsanVMLabels(vm))
157 writeVSANPerformanceValues(c, labels, c.vsanMetrics.VMs[id], vsanVMPerfMetricByName)
158 }
159 }
160
161 func writeVSANPerformanceValues(c *Collector, labels metrix.LabelSet, values scrapepkg.VSANEntityMetrics, metricByName map[string]string) {
162 for _, name := range sortedMapKeys(values) {
163 metricName := metricByName[name]
164 if metricName == "" {
165 continue
166 }
167 c.observeGaugeFloat(metricName, values[name], labels)
168 }
169 }
170
171 var vsanClusterPerfMetricByName = map[string]string{
172 "read_operations": vsanClusterOperationsReadMetric,
173 "write_operations": vsanClusterOperationsWriteMetric,
174 "read_throughput": vsanClusterThroughputReadMetric,
175 "write_throughput": vsanClusterThroughputWriteMetric,
176 "read_latency": vsanClusterLatencyReadMetric,
177 "write_latency": vsanClusterLatencyWriteMetric,
178 "congestions": vsanClusterCongestionsMetric,
179 }
180
181 var vsanHostPerfMetricByName = map[string]string{
182 "read_operations": vsanHostOperationsReadMetric,
183 "write_operations": vsanHostOperationsWriteMetric,
184 "read_throughput": vsanHostThroughputReadMetric,
185 "write_throughput": vsanHostThroughputWriteMetric,
186 "read_latency": vsanHostLatencyReadMetric,
187 "write_latency": vsanHostLatencyWriteMetric,
188 "congestions": vsanHostCongestionsMetric,
189 "cache_hit_rate": vsanHostCacheHitRateMetric,
190 }
191
192 var vsanVMPerfMetricByName = map[string]string{
193 "read_operations": vsanVMOperationsReadMetric,
194 "write_operations": vsanVMOperationsWriteMetric,
195 "read_throughput": vsanVMThroughputReadMetric,
196 "write_throughput": vsanVMThroughputWriteMetric,
197 "read_latency": vsanVMLatencyReadMetric,
198 "write_latency": vsanVMLatencyWriteMetric,
199 }
200
201 func (c *Collector) vsanClusterLabels(cluster *rs.Cluster) []metrix.Label {
202 return c.v2MetricLabels(cluster.ID, []metrix.Label{
203 {Key: "datacenter", Value: cluster.Hier.DC.Name},
204 {Key: "cluster", Value: cluster.Name},
205 {Key: vsanUUIDLabel, Value: cluster.VSANUUID},
206 }, cluster.Labels)
207 }
208
209 func (c *Collector) vsanHostLabels(host *rs.Host) []metrix.Label {
210 return c.v2MetricLabels(host.ID, []metrix.Label{
211 {Key: "datacenter", Value: host.Hier.DC.Name},
212 {Key: "cluster", Value: getHostClusterName(host)},
213 {Key: "host", Value: host.Name},
214 {Key: vsanNodeUUIDLabel, Value: host.VSANNodeUUID},
215 }, host.Labels)
216 }
217
218 func (c *Collector) vsanVMLabels(vm *rs.VM) []metrix.Label {
219 return c.v2MetricLabels(vm.ID, []metrix.Label{
220 {Key: "datacenter", Value: vm.Hier.DC.Name},
221 {Key: "cluster", Value: getVMClusterName(vm)},
222 {Key: "host", Value: vm.Hier.Host.Name},
223 {Key: "vm", Value: vm.Name},
224 {Key: vmInstanceUUIDLabel, Value: vm.InstanceUUID},
225 }, vm.Labels)
226 }