| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | package vsphere |
| 4 | |
| 5 | import ( |
| 6 | "github.com/vmware/govmomi/performance" |
| 7 | |
| 8 | "github.com/netdata/netdata/go/plugins/pkg/metrix" |
| 9 | rs "github.com/netdata/netdata/go/plugins/plugin/go.d/collector/vsphere/resources" |
| 10 | ) |
| 11 | |
| 12 | const ( |
| 13 | hostPowerUsagePowerMetric = "host_power_usage_power" |
| 14 | hostPowerUsageCapMetric = "host_power_usage_cap" |
| 15 | |
| 16 | hostPowerCapacityUsageUsedMetric = "host_power_capacity_usage_used" |
| 17 | hostPowerCapacityUsageUsableMetric = "host_power_capacity_usage_usable" |
| 18 | hostPowerCapacityUsageIdleMetric = "host_power_capacity_usage_idle" |
| 19 | hostPowerCapacityUsageSystemMetric = "host_power_capacity_usage_system" |
| 20 | hostPowerCapacityUsageVMMetric = "host_power_capacity_usage_vm" |
| 21 | |
| 22 | hostPowerCapacityUtilizationMetric = "host_power_capacity_utilization_used" |
| 23 | |
| 24 | hostEnergyUsageMetric = "host_energy_usage_energy" |
| 25 | |
| 26 | vmPowerUsagePowerMetric = "vm_power_usage_power" |
| 27 | |
| 28 | vmEnergyUsageMetric = "vm_energy_usage_energy" |
| 29 | ) |
| 30 | |
| 31 | var hostPowerMetricByCounter = map[string]string{ |
| 32 | "power.power.average": hostPowerUsagePowerMetric, |
| 33 | "power.powerCap.average": hostPowerUsageCapMetric, |
| 34 | "power.capacity.usage.average": hostPowerCapacityUsageUsedMetric, |
| 35 | "power.capacity.usable.average": hostPowerCapacityUsageUsableMetric, |
| 36 | "power.capacity.usageIdle.average": hostPowerCapacityUsageIdleMetric, |
| 37 | "power.capacity.usageSystem.average": hostPowerCapacityUsageSystemMetric, |
| 38 | "power.capacity.usageVm.average": hostPowerCapacityUsageVMMetric, |
| 39 | "power.capacity.usagePct.average": hostPowerCapacityUtilizationMetric, |
| 40 | "power.energy.summation": hostEnergyUsageMetric, |
| 41 | } |
| 42 | |
| 43 | var vmPowerMetricByCounter = map[string]string{ |
| 44 | "power.power.average": vmPowerUsagePowerMetric, |
| 45 | "power.energy.summation": vmEnergyUsageMetric, |
| 46 | } |
| 47 | |
| 48 | type hostPowerPerfSample struct { |
| 49 | host *rs.Host |
| 50 | values map[string]int64 |
| 51 | } |
| 52 | |
| 53 | type vmPowerPerfSample struct { |
| 54 | vm *rs.VM |
| 55 | values map[string]int64 |
| 56 | } |
| 57 | |
| 58 | func (c *Collector) collectHostPowerMetrics(host *rs.Host, metrics []performance.MetricSeries) { |
| 59 | for _, metric := range metrics { |
| 60 | if len(metric.Value) == 0 || metric.Value[0] == -1 || metric.Instance != "" { |
| 61 | continue |
| 62 | } |
| 63 | metricName, ok := hostPowerMetricByCounter[metric.Name] |
| 64 | if !ok { |
| 65 | continue |
| 66 | } |
| 67 | if c.hostPowerPerfSamples == nil { |
| 68 | c.hostPowerPerfSamples = make(map[string]*hostPowerPerfSample) |
| 69 | } |
| 70 | sample := c.hostPowerPerfSamples[host.ID] |
| 71 | if sample == nil { |
| 72 | sample = &hostPowerPerfSample{ |
| 73 | host: host, |
| 74 | values: make(map[string]int64), |
| 75 | } |
| 76 | c.hostPowerPerfSamples[host.ID] = sample |
| 77 | } |
| 78 | sample.values[metricName] = metric.Value[0] |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | func (c *Collector) collectVMPowerMetrics(vm *rs.VM, metrics []performance.MetricSeries) { |
| 83 | for _, metric := range metrics { |
| 84 | if len(metric.Value) == 0 || metric.Value[0] == -1 || metric.Instance != "" { |
| 85 | continue |
| 86 | } |
| 87 | metricName, ok := vmPowerMetricByCounter[metric.Name] |
| 88 | if !ok { |
| 89 | continue |
| 90 | } |
| 91 | if c.vmPowerPerfSamples == nil { |
| 92 | c.vmPowerPerfSamples = make(map[string]*vmPowerPerfSample) |
| 93 | } |
| 94 | sample := c.vmPowerPerfSamples[vm.ID] |
| 95 | if sample == nil { |
| 96 | sample = &vmPowerPerfSample{ |
| 97 | vm: vm, |
| 98 | values: make(map[string]int64), |
| 99 | } |
| 100 | c.vmPowerPerfSamples[vm.ID] = sample |
| 101 | } |
| 102 | sample.values[metricName] = metric.Value[0] |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | func (c *Collector) writePowerMetrics() { |
| 107 | c.writeHostPowerMetrics() |
| 108 | c.writeVMPowerMetrics() |
| 109 | } |
| 110 | |
| 111 | func (c *Collector) writeHostPowerMetrics() { |
| 112 | if len(c.hostPowerPerfSamples) == 0 { |
| 113 | return |
| 114 | } |
| 115 | |
| 116 | for _, sample := range sortedHostPowerPerfSamples(c.hostPowerPerfSamples) { |
| 117 | labels := c.labelSet(c.hostPowerLabels(sample.host)) |
| 118 | for metricName, value := range sample.values { |
| 119 | c.observeGauge(metricName, value, labels) |
| 120 | } |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | func (c *Collector) writeVMPowerMetrics() { |
| 125 | if len(c.vmPowerPerfSamples) == 0 { |
| 126 | return |
| 127 | } |
| 128 | |
| 129 | for _, sample := range sortedVMPowerPerfSamples(c.vmPowerPerfSamples) { |
| 130 | labels := c.labelSet(c.vmPowerLabels(sample.vm)) |
| 131 | for metricName, value := range sample.values { |
| 132 | c.observeGauge(metricName, value, labels) |
| 133 | } |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | func (c *Collector) hostPowerLabels(host *rs.Host) []metrix.Label { |
| 138 | return c.v2MetricLabels(host.ID, []metrix.Label{ |
| 139 | {Key: "datacenter", Value: host.Hier.DC.Name}, |
| 140 | {Key: "cluster", Value: getHostClusterName(host)}, |
| 141 | {Key: "host", Value: host.Name}, |
| 142 | }, host.Labels) |
| 143 | } |
| 144 | |
| 145 | func (c *Collector) vmPowerLabels(vm *rs.VM) []metrix.Label { |
| 146 | return c.v2MetricLabels(vm.ID, []metrix.Label{ |
| 147 | {Key: "datacenter", Value: vm.Hier.DC.Name}, |
| 148 | {Key: "cluster", Value: getVMClusterName(vm)}, |
| 149 | {Key: "host", Value: vm.Hier.Host.Name}, |
| 150 | {Key: "vm", Value: vm.Name}, |
| 151 | }, vm.Labels) |
| 152 | } |