summaryrefslogtreecommitdiffstats
path: root/src/go/collectors/go.d.plugin/modules/vsphere/charts.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/go/collectors/go.d.plugin/modules/vsphere/charts.go506
1 files changed, 506 insertions, 0 deletions
diff --git a/src/go/collectors/go.d.plugin/modules/vsphere/charts.go b/src/go/collectors/go.d.plugin/modules/vsphere/charts.go
new file mode 100644
index 000000000..ed4db941d
--- /dev/null
+++ b/src/go/collectors/go.d.plugin/modules/vsphere/charts.go
@@ -0,0 +1,506 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+package vsphere
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/netdata/netdata/go/go.d.plugin/agent/module"
+ rs "github.com/netdata/netdata/go/go.d.plugin/modules/vsphere/resources"
+)
+
+const (
+ prioVMCPUUtilization = module.Priority + iota
+ prioVmMemoryUtilization
+ prioVmMemoryUsage
+ prioVmMemorySwapUsage
+ prioVmMemorySwapIO
+ prioVmDiskIO
+ prioVmDiskMaxLatency
+ prioVmNetworkTraffic
+ prioVmNetworkPackets
+ prioVmNetworkDrops
+ prioVmOverallStatus
+ prioVmSystemUptime
+
+ prioHostCPUUtilization
+ prioHostMemoryUtilization
+ prioHostMemoryUsage
+ prioHostMemorySwapIO
+ prioHostDiskIO
+ prioHostDiskMaxLatency
+ prioHostNetworkTraffic
+ prioHostNetworkPackets
+ prioHostNetworkDrops
+ prioHostNetworkErrors
+ prioHostOverallStatus
+ prioHostSystemUptime
+)
+
+var (
+ vmChartsTmpl = module.Charts{
+ vmCPUUtilizationChartTmpl.Copy(),
+
+ vmMemoryUtilizationChartTmpl.Copy(),
+ vmMemoryUsageChartTmpl.Copy(),
+ vmMemorySwapUsageChartTmpl.Copy(),
+ vmMemorySwapIOChartTmpl.Copy(),
+
+ vmDiskIOChartTmpl.Copy(),
+ vmDiskMaxLatencyChartTmpl.Copy(),
+
+ vmNetworkTrafficChartTmpl.Copy(),
+ vmNetworkPacketsChartTmpl.Copy(),
+ vmNetworkDropsChartTmpl.Copy(),
+
+ vmOverallStatusChartTmpl.Copy(),
+
+ vmSystemUptimeChartTmpl.Copy(),
+ }
+
+ vmCPUUtilizationChartTmpl = module.Chart{
+ ID: "%s_cpu_utilization",
+ Title: "Virtual Machine CPU utilization",
+ Units: "percentage",
+ Fam: "vms cpu",
+ Ctx: "vsphere.vm_cpu_utilization",
+ Priority: prioVMCPUUtilization,
+ Dims: module.Dims{
+ {ID: "%s_cpu.usage.average", Name: "used", Div: 100},
+ },
+ }
+
+ // Ref: https://www.vmware.com/support/developer/converter-sdk/conv51_apireference/memory_counters.html
+ vmMemoryUtilizationChartTmpl = module.Chart{
+ ID: "%s_mem_utilization",
+ Title: "Virtual Machine memory utilization",
+ Units: "percentage",
+ Fam: "vms mem",
+ Ctx: "vsphere.vm_mem_utilization",
+ Priority: prioVmMemoryUtilization,
+ Dims: module.Dims{
+ {ID: "%s_mem.usage.average", Name: "used", Div: 100},
+ },
+ }
+ vmMemoryUsageChartTmpl = module.Chart{
+ ID: "%s_mem_usage",
+ Title: "Virtual Machine memory usage",
+ Units: "KiB",
+ Fam: "vms mem",
+ Ctx: "vsphere.vm_mem_usage",
+ Priority: prioVmMemoryUsage,
+ Dims: module.Dims{
+ {ID: "%s_mem.granted.average", Name: "granted"},
+ {ID: "%s_mem.consumed.average", Name: "consumed"},
+ {ID: "%s_mem.active.average", Name: "active"},
+ {ID: "%s_mem.shared.average", Name: "shared"},
+ },
+ }
+ vmMemorySwapUsageChartTmpl = module.Chart{
+ ID: "%s_mem_swap_usage",
+ Title: "Virtual Machine VMKernel memory swap usage",
+ Units: "KiB",
+ Fam: "vms mem",
+ Ctx: "vsphere.vm_mem_swap_usage",
+ Priority: prioVmMemorySwapUsage,
+ Dims: module.Dims{
+ {ID: "%s_mem.swapped.average", Name: "swapped"},
+ },
+ }
+ vmMemorySwapIOChartTmpl = module.Chart{
+ ID: "%s_mem_swap_io_rate",
+ Title: "Virtual Machine VMKernel memory swap IO",
+ Units: "KiB/s",
+ Fam: "vms mem",
+ Ctx: "vsphere.vm_mem_swap_io",
+ Type: module.Area,
+ Priority: prioVmMemorySwapIO,
+ Dims: module.Dims{
+ {ID: "%s_mem.swapinRate.average", Name: "in"},
+ {ID: "%s_mem.swapoutRate.average", Name: "out"},
+ },
+ }
+
+ vmDiskIOChartTmpl = module.Chart{
+ ID: "%s_disk_io",
+ Title: "Virtual Machine disk IO",
+ Units: "KiB/s",
+ Fam: "vms disk",
+ Ctx: "vsphere.vm_disk_io",
+ Type: module.Area,
+ Priority: prioVmDiskIO,
+ Dims: module.Dims{
+ {ID: "%s_disk.read.average", Name: "read"},
+ {ID: "%s_disk.write.average", Name: "write", Mul: -1},
+ },
+ }
+ vmDiskMaxLatencyChartTmpl = module.Chart{
+ ID: "%s_disk_max_latency",
+ Title: "Virtual Machine disk max latency",
+ Units: "milliseconds",
+ Fam: "vms disk",
+ Ctx: "vsphere.vm_disk_max_latency",
+ Priority: prioVmDiskMaxLatency,
+ Dims: module.Dims{
+ {ID: "%s_disk.maxTotalLatency.latest", Name: "latency"},
+ },
+ }
+
+ vmNetworkTrafficChartTmpl = module.Chart{
+ ID: "%s_net_traffic",
+ Title: "Virtual Machine network traffic",
+ Units: "KiB/s",
+ Fam: "vms net",
+ Ctx: "vsphere.vm_net_traffic",
+ Type: module.Area,
+ Priority: prioVmNetworkTraffic,
+ Dims: module.Dims{
+ {ID: "%s_net.bytesRx.average", Name: "received"},
+ {ID: "%s_net.bytesTx.average", Name: "sent", Mul: -1},
+ },
+ }
+ vmNetworkPacketsChartTmpl = module.Chart{
+ ID: "%s_net_packets",
+ Title: "Virtual Machine network packets",
+ Units: "packets",
+ Fam: "vms net",
+ Ctx: "vsphere.vm_net_packets",
+ Priority: prioVmNetworkPackets,
+ Dims: module.Dims{
+ {ID: "%s_net.packetsRx.summation", Name: "received"},
+ {ID: "%s_net.packetsTx.summation", Name: "sent", Mul: -1},
+ },
+ }
+ vmNetworkDropsChartTmpl = module.Chart{
+ ID: "%s_net_drops",
+ Title: "Virtual Machine network dropped packets",
+ Units: "drops",
+ Fam: "vms net",
+ Ctx: "vsphere.vm_net_drops",
+ Priority: prioVmNetworkDrops,
+ Dims: module.Dims{
+ {ID: "%s_net.droppedRx.summation", Name: "received"},
+ {ID: "%s_net.droppedTx.summation", Name: "sent", Mul: -1},
+ },
+ }
+
+ vmOverallStatusChartTmpl = module.Chart{
+ ID: "%s_overall_status",
+ Title: "Virtual Machine overall alarm status",
+ Units: "status",
+ Fam: "vms status",
+ Ctx: "vsphere.vm_overall_status",
+ Priority: prioVmOverallStatus,
+ Dims: module.Dims{
+ {ID: "%s_overall.status.green", Name: "green"},
+ {ID: "%s_overall.status.red", Name: "red"},
+ {ID: "%s_overall.status.yellow", Name: "yellow"},
+ {ID: "%s_overall.status.gray", Name: "gray"},
+ },
+ }
+
+ vmSystemUptimeChartTmpl = module.Chart{
+ ID: "%s_system_uptime",
+ Title: "Virtual Machine system uptime",
+ Units: "seconds",
+ Fam: "vms uptime",
+ Ctx: "vsphere.vm_system_uptime",
+ Priority: prioVmSystemUptime,
+ Dims: module.Dims{
+ {ID: "%s_sys.uptime.latest", Name: "uptime"},
+ },
+ }
+)
+
+var (
+ hostChartsTmpl = module.Charts{
+ hostCPUUtilizationChartTmpl.Copy(),
+
+ hostMemUtilizationChartTmpl.Copy(),
+ hostMemUsageChartTmpl.Copy(),
+ hostMemSwapIOChartTmpl.Copy(),
+
+ hostDiskIOChartTmpl.Copy(),
+ hostDiskMaxLatencyChartTmpl.Copy(),
+
+ hostNetworkTraffic.Copy(),
+ hostNetworkPacketsChartTmpl.Copy(),
+ hostNetworkDropsChartTmpl.Copy(),
+ hostNetworkErrorsChartTmpl.Copy(),
+
+ hostOverallStatusChartTmpl.Copy(),
+
+ hostSystemUptimeChartTmpl.Copy(),
+ }
+ hostCPUUtilizationChartTmpl = module.Chart{
+ ID: "%s_cpu_usage_total",
+ Title: "ESXi Host CPU utilization",
+ Units: "percentage",
+ Fam: "hosts cpu",
+ Ctx: "vsphere.host_cpu_utilization",
+ Priority: prioHostCPUUtilization,
+ Dims: module.Dims{
+ {ID: "%s_cpu.usage.average", Name: "used", Div: 100},
+ },
+ }
+ hostMemUtilizationChartTmpl = module.Chart{
+ ID: "%s_mem_utilization",
+ Title: "ESXi Host memory utilization",
+ Units: "percentage",
+ Fam: "hosts mem",
+ Ctx: "vsphere.host_mem_utilization",
+ Priority: prioHostMemoryUtilization,
+ Dims: module.Dims{
+ {ID: "%s_mem.usage.average", Name: "used", Div: 100},
+ },
+ }
+ hostMemUsageChartTmpl = module.Chart{
+ ID: "%s_mem_usage",
+ Title: "ESXi Host memory usage",
+ Units: "KiB",
+ Fam: "hosts mem",
+ Ctx: "vsphere.host_mem_usage",
+ Priority: prioHostMemoryUsage,
+ Dims: module.Dims{
+ {ID: "%s_mem.granted.average", Name: "granted"},
+ {ID: "%s_mem.consumed.average", Name: "consumed"},
+ {ID: "%s_mem.active.average", Name: "active"},
+ {ID: "%s_mem.shared.average", Name: "shared"},
+ {ID: "%s_mem.sharedcommon.average", Name: "sharedcommon"},
+ },
+ }
+ hostMemSwapIOChartTmpl = module.Chart{
+ ID: "%s_mem_swap_rate",
+ Title: "ESXi Host VMKernel memory swap IO",
+ Units: "KiB/s",
+ Fam: "hosts mem",
+ Ctx: "vsphere.host_mem_swap_io",
+ Type: module.Area,
+ Priority: prioHostMemorySwapIO,
+ Dims: module.Dims{
+ {ID: "%s_mem.swapinRate.average", Name: "in"},
+ {ID: "%s_mem.swapoutRate.average", Name: "out"},
+ },
+ }
+
+ hostDiskIOChartTmpl = module.Chart{
+ ID: "%s_disk_io",
+ Title: "ESXi Host disk IO",
+ Units: "KiB/s",
+ Fam: "hosts disk",
+ Ctx: "vsphere.host_disk_io",
+ Type: module.Area,
+ Priority: prioHostDiskIO,
+ Dims: module.Dims{
+ {ID: "%s_disk.read.average", Name: "read"},
+ {ID: "%s_disk.write.average", Name: "write", Mul: -1},
+ },
+ }
+ hostDiskMaxLatencyChartTmpl = module.Chart{
+ ID: "%s_disk_max_latency",
+ Title: "ESXi Host disk max latency",
+ Units: "milliseconds",
+ Fam: "hosts disk",
+ Ctx: "vsphere.host_disk_max_latency",
+ Priority: prioHostDiskMaxLatency,
+ Dims: module.Dims{
+ {ID: "%s_disk.maxTotalLatency.latest", Name: "latency"},
+ },
+ }
+
+ hostNetworkTraffic = module.Chart{
+ ID: "%s_net_traffic",
+ Title: "ESXi Host network traffic",
+ Units: "KiB/s",
+ Fam: "hosts net",
+ Ctx: "vsphere.host_net_traffic",
+ Type: module.Area,
+ Priority: prioHostNetworkTraffic,
+ Dims: module.Dims{
+ {ID: "%s_net.bytesRx.average", Name: "received"},
+ {ID: "%s_net.bytesTx.average", Name: "sent", Mul: -1},
+ },
+ }
+ hostNetworkPacketsChartTmpl = module.Chart{
+ ID: "%s_net_packets",
+ Title: "ESXi Host network packets",
+ Units: "packets",
+ Fam: "hosts net",
+ Ctx: "vsphere.host_net_packets",
+ Priority: prioHostNetworkPackets,
+ Dims: module.Dims{
+ {ID: "%s_net.packetsRx.summation", Name: "received"},
+ {ID: "%s_net.packetsTx.summation", Name: "sent", Mul: -1},
+ },
+ }
+ hostNetworkDropsChartTmpl = module.Chart{
+ ID: "%s_net_drops_total",
+ Title: "ESXi Host network drops",
+ Units: "drops",
+ Fam: "hosts net",
+ Ctx: "vsphere.host_net_drops",
+ Priority: prioHostNetworkDrops,
+ Dims: module.Dims{
+ {ID: "%s_net.droppedRx.summation", Name: "received"},
+ {ID: "%s_net.droppedTx.summation", Name: "sent", Mul: -1},
+ },
+ }
+ hostNetworkErrorsChartTmpl = module.Chart{
+ ID: "%s_net_errors",
+ Title: "ESXi Host network errors",
+ Units: "errors",
+ Fam: "hosts net",
+ Ctx: "vsphere.host_net_errors",
+ Priority: prioHostNetworkErrors,
+ Dims: module.Dims{
+ {ID: "%s_net.errorsRx.summation", Name: "received"},
+ {ID: "%s_net.errorsTx.summation", Name: "sent", Mul: -1},
+ },
+ }
+
+ hostOverallStatusChartTmpl = module.Chart{
+ ID: "%s_overall_status",
+ Title: "ESXi Host overall alarm status",
+ Units: "status",
+ Fam: "hosts status",
+ Ctx: "vsphere.host_overall_status",
+ Priority: prioHostOverallStatus,
+ Dims: module.Dims{
+ {ID: "%s_overall.status.green", Name: "green"},
+ {ID: "%s_overall.status.red", Name: "red"},
+ {ID: "%s_overall.status.yellow", Name: "yellow"},
+ {ID: "%s_overall.status.gray", Name: "gray"},
+ },
+ }
+ hostSystemUptimeChartTmpl = module.Chart{
+ ID: "%s_system_uptime",
+ Title: "ESXi Host system uptime",
+ Units: "seconds",
+ Fam: "hosts uptime",
+ Ctx: "vsphere.host_system_uptime",
+ Priority: prioHostSystemUptime,
+ Dims: module.Dims{
+ {ID: "%s_sys.uptime.latest", Name: "uptime"},
+ },
+ }
+)
+
+const failedUpdatesLimit = 10
+
+func (vs *VSphere) updateCharts() {
+ for id, fails := range vs.discoveredHosts {
+ if fails >= failedUpdatesLimit {
+ vs.removeFromCharts(id)
+ delete(vs.charted, id)
+ delete(vs.discoveredHosts, id)
+ continue
+ }
+
+ host := vs.resources.Hosts.Get(id)
+ if host == nil || vs.charted[id] || fails != 0 {
+ continue
+ }
+
+ vs.charted[id] = true
+ charts := newHostCharts(host)
+ if err := vs.Charts().Add(*charts...); err != nil {
+ vs.Error(err)
+ }
+ }
+
+ for id, fails := range vs.discoveredVMs {
+ if fails >= failedUpdatesLimit {
+ vs.removeFromCharts(id)
+ delete(vs.charted, id)
+ delete(vs.discoveredVMs, id)
+ continue
+ }
+
+ vm := vs.resources.VMs.Get(id)
+ if vm == nil || vs.charted[id] || fails != 0 {
+ continue
+ }
+
+ vs.charted[id] = true
+ charts := newVMCHarts(vm)
+ if err := vs.Charts().Add(*charts...); err != nil {
+ vs.Error(err)
+ }
+ }
+}
+
+func newVMCHarts(vm *rs.VM) *module.Charts {
+ charts := vmChartsTmpl.Copy()
+
+ for _, chart := range *charts {
+ chart.ID = fmt.Sprintf(chart.ID, vm.ID)
+ chart.Labels = []module.Label{
+ {Key: "datacenter", Value: vm.Hier.DC.Name},
+ {Key: "cluster", Value: getVMClusterName(vm)},
+ {Key: "host", Value: vm.Hier.Host.Name},
+ {Key: "vm", Value: vm.Name},
+ }
+ for _, dim := range chart.Dims {
+ dim.ID = fmt.Sprintf(dim.ID, vm.ID)
+ }
+ }
+
+ return charts
+}
+
+func getVMClusterName(vm *rs.VM) string {
+ if vm.Hier.Cluster.Name == vm.Hier.Host.Name {
+ return ""
+ }
+ return vm.Hier.Cluster.Name
+}
+
+func newHostCharts(host *rs.Host) *module.Charts {
+ charts := hostChartsTmpl.Copy()
+
+ for _, chart := range *charts {
+ chart.ID = fmt.Sprintf(chart.ID, host.ID)
+ chart.Labels = []module.Label{
+ {Key: "datacenter", Value: host.Hier.DC.Name},
+ {Key: "cluster", Value: getHostClusterName(host)},
+ {Key: "host", Value: host.Name},
+ }
+
+ for _, dim := range chart.Dims {
+ dim.ID = fmt.Sprintf(dim.ID, host.ID)
+ }
+ }
+
+ return charts
+}
+
+func getHostClusterName(host *rs.Host) string {
+ if host.Hier.Cluster.Name == host.Name {
+ return ""
+ }
+ return host.Hier.Cluster.Name
+}
+
+func (vs *VSphere) removeFromCharts(prefix string) {
+ for _, c := range *vs.Charts() {
+ if strings.HasPrefix(c.ID, prefix) {
+ c.MarkRemove()
+ c.MarkNotCreated()
+ }
+ }
+}
+
+//func findMetricSeriesByPrefix(ms []performance.MetricSeries, prefix string) []performance.MetricSeries {
+// from := sort.Search(len(ms), func(i int) bool { return ms[i].Name >= prefix })
+//
+// if from == len(ms) || !strings.HasPrefix(ms[from].Name, prefix) {
+// return nil
+// }
+//
+// until := from + 1
+// for until < len(ms) && strings.HasPrefix(ms[until].Name, prefix) {
+// until++
+// }
+// return ms[from:until]
+//}