github.com/netdata/go.d.plugin@v0.58.1/modules/vsphere/collect.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package vsphere
     4  
     5  import (
     6  	"errors"
     7  	"fmt"
     8  	"time"
     9  
    10  	rs "github.com/netdata/go.d.plugin/modules/vsphere/resources"
    11  
    12  	"github.com/vmware/govmomi/performance"
    13  )
    14  
    15  // ManagedEntityStatus
    16  var overallStatuses = []string{"green", "red", "yellow", "gray"}
    17  
    18  func (vs *VSphere) collect() (map[string]int64, error) {
    19  	vs.collectionLock.Lock()
    20  	defer vs.collectionLock.Unlock()
    21  
    22  	vs.Debug("starting collection process")
    23  	t := time.Now()
    24  	mx := make(map[string]int64)
    25  
    26  	err := vs.collectHosts(mx)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	err = vs.collectVMs(mx)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	vs.updateCharts()
    37  
    38  	vs.Debugf("metrics collected, process took %s", time.Since(t))
    39  
    40  	return mx, nil
    41  }
    42  
    43  func (vs *VSphere) collectHosts(mx map[string]int64) error {
    44  	if len(vs.resources.Hosts) == 0 {
    45  		return nil
    46  	}
    47  	// NOTE: returns unsorted if at least one types.PerfMetricId Instance is not ""
    48  	metrics := vs.ScrapeHosts(vs.resources.Hosts)
    49  	if len(metrics) == 0 {
    50  		return errors.New("failed to scrape hosts metrics")
    51  	}
    52  
    53  	vs.collectHostsMetrics(mx, metrics)
    54  
    55  	return nil
    56  }
    57  
    58  func (vs *VSphere) collectHostsMetrics(mx map[string]int64, metrics []performance.EntityMetric) {
    59  	for k := range vs.discoveredHosts {
    60  		vs.discoveredHosts[k]++
    61  	}
    62  
    63  	for _, metric := range metrics {
    64  		if host := vs.resources.Hosts.Get(metric.Entity.Value); host != nil {
    65  			vs.discoveredHosts[host.ID] = 0
    66  			writeHostMetrics(mx, host, metric.Value)
    67  		}
    68  	}
    69  }
    70  
    71  func writeHostMetrics(mx map[string]int64, host *rs.Host, metrics []performance.MetricSeries) {
    72  	for _, metric := range metrics {
    73  		if len(metric.Value) == 0 || metric.Value[0] == -1 {
    74  			continue
    75  		}
    76  		key := fmt.Sprintf("%s_%s", host.ID, metric.Name)
    77  		mx[key] = metric.Value[0]
    78  	}
    79  	for _, v := range overallStatuses {
    80  		key := fmt.Sprintf("%s_overall.status.%s", host.ID, v)
    81  		mx[key] = boolToInt(host.OverallStatus == v)
    82  	}
    83  }
    84  
    85  func (vs *VSphere) collectVMs(mx map[string]int64) error {
    86  	if len(vs.resources.VMs) == 0 {
    87  		return nil
    88  	}
    89  	// NOTE: returns unsorted if at least one types.PerfMetricId Instance is not ""
    90  	ems := vs.ScrapeVMs(vs.resources.VMs)
    91  	if len(ems) == 0 {
    92  		return errors.New("failed to scrape vms metrics")
    93  	}
    94  
    95  	vs.collectVMsMetrics(mx, ems)
    96  
    97  	return nil
    98  }
    99  
   100  func (vs *VSphere) collectVMsMetrics(mx map[string]int64, metrics []performance.EntityMetric) {
   101  	for id := range vs.discoveredVMs {
   102  		vs.discoveredVMs[id]++
   103  	}
   104  
   105  	for _, metric := range metrics {
   106  		if vm := vs.resources.VMs.Get(metric.Entity.Value); vm != nil {
   107  			writeVMMetrics(mx, vm, metric.Value)
   108  			vs.discoveredVMs[vm.ID] = 0
   109  		}
   110  	}
   111  }
   112  
   113  func writeVMMetrics(mx map[string]int64, vm *rs.VM, metrics []performance.MetricSeries) {
   114  	for _, metric := range metrics {
   115  		if len(metric.Value) == 0 || metric.Value[0] == -1 {
   116  			continue
   117  		}
   118  		key := fmt.Sprintf("%s_%s", vm.ID, metric.Name)
   119  		mx[key] = metric.Value[0]
   120  	}
   121  	for _, v := range overallStatuses {
   122  		key := fmt.Sprintf("%s_overall.status.%s", vm.ID, v)
   123  		mx[key] = boolToInt(vm.OverallStatus == v)
   124  	}
   125  }
   126  
   127  func boolToInt(v bool) int64 {
   128  	if v {
   129  		return 1
   130  	}
   131  	return 0
   132  }