netdata/netdata

View on GitHub
src/go/collectors/go.d.plugin/modules/vsphere/collect.go

Summary

Maintainability
B
5 hrs
Test Coverage
// SPDX-License-Identifier: GPL-3.0-or-later

package vsphere

import (
    "errors"
    "fmt"
    "time"

    rs "github.com/netdata/netdata/go/go.d.plugin/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
}