diff options
Diffstat (limited to 'src/go/plugin/go.d/modules/vsphere/collect.go')
-rw-r--r-- | src/go/plugin/go.d/modules/vsphere/collect.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/go/plugin/go.d/modules/vsphere/collect.go b/src/go/plugin/go.d/modules/vsphere/collect.go new file mode 100644 index 000000000..e5672d3fd --- /dev/null +++ b/src/go/plugin/go.d/modules/vsphere/collect.go @@ -0,0 +1,132 @@ +// 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 +} |