src/go/plugin/go.d/modules/vsphere/collect.go
// SPDX-License-Identifier: GPL-3.0-or-later
package vsphere
import (
"errors"
"fmt"
"time"
rs "github.com/netdata/netdata/go/plugins/plugin/go.d/modules/vsphere/resources"
"github.com/vmware/govmomi/performance"
)
// ManagedEntityStatus
var overallStatuses = []string{"green", "red", "yellow", "gray"}
func (vs *VSphere) collect() (map[string]int64, error) {
vs.collectionLock.Lock()
defer vs.collectionLock.Unlock()
vs.Debug("starting collection process")
t := time.Now()
mx := make(map[string]int64)
err := vs.collectHosts(mx)
if err != nil {
return nil, err
}
err = vs.collectVMs(mx)
if err != nil {
return nil, err
}
vs.updateCharts()
vs.Debugf("metrics collected, process took %s", time.Since(t))
return mx, nil
}
func (vs *VSphere) collectHosts(mx map[string]int64) error {
if len(vs.resources.Hosts) == 0 {
return nil
}
// NOTE: returns unsorted if at least one types.PerfMetricId Instance is not ""
metrics := vs.ScrapeHosts(vs.resources.Hosts)
if len(metrics) == 0 {
return errors.New("failed to scrape hosts metrics")
}
vs.collectHostsMetrics(mx, metrics)
return nil
}
func (vs *VSphere) collectHostsMetrics(mx map[string]int64, metrics []performance.EntityMetric) {
for k := range vs.discoveredHosts {
vs.discoveredHosts[k]++
}
for _, metric := range metrics {
if host := vs.resources.Hosts.Get(metric.Entity.Value); host != nil {
vs.discoveredHosts[host.ID] = 0
writeHostMetrics(mx, host, metric.Value)
}
}
}
func writeHostMetrics(mx map[string]int64, host *rs.Host, metrics []performance.MetricSeries) {
for _, metric := range metrics {
if len(metric.Value) == 0 || metric.Value[0] == -1 {
continue
}
key := fmt.Sprintf("%s_%s", host.ID, metric.Name)
mx[key] = metric.Value[0]
}
for _, v := range overallStatuses {
key := fmt.Sprintf("%s_overall.status.%s", host.ID, v)
mx[key] = boolToInt(host.OverallStatus == v)
}
}
func (vs *VSphere) collectVMs(mx map[string]int64) error {
if len(vs.resources.VMs) == 0 {
return nil
}
// NOTE: returns unsorted if at least one types.PerfMetricId Instance is not ""
ems := vs.ScrapeVMs(vs.resources.VMs)
if len(ems) == 0 {
return errors.New("failed to scrape vms metrics")
}
vs.collectVMsMetrics(mx, ems)
return nil
}
func (vs *VSphere) collectVMsMetrics(mx map[string]int64, metrics []performance.EntityMetric) {
for id := range vs.discoveredVMs {
vs.discoveredVMs[id]++
}
for _, metric := range metrics {
if vm := vs.resources.VMs.Get(metric.Entity.Value); vm != nil {
writeVMMetrics(mx, vm, metric.Value)
vs.discoveredVMs[vm.ID] = 0
}
}
}
func writeVMMetrics(mx map[string]int64, vm *rs.VM, metrics []performance.MetricSeries) {
for _, metric := range metrics {
if len(metric.Value) == 0 || metric.Value[0] == -1 {
continue
}
key := fmt.Sprintf("%s_%s", vm.ID, metric.Name)
mx[key] = metric.Value[0]
}
for _, v := range overallStatuses {
key := fmt.Sprintf("%s_overall.status.%s", vm.ID, v)
mx[key] = boolToInt(vm.OverallStatus == v)
}
}
func boolToInt(v bool) int64 {
if v {
return 1
}
return 0
}