123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- package vcenterreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver"
- import (
- "context"
- "github.com/vmware/govmomi/performance"
- "github.com/vmware/govmomi/vim25/mo"
- "github.com/vmware/govmomi/vim25/types"
- "go.opentelemetry.io/collector/pdata/pcommon"
- "go.opentelemetry.io/collector/receiver/scrapererror"
- "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/vcenterreceiver/internal/metadata"
- )
- func (v *vcenterMetricScraper) recordHostSystemMemoryUsage(
- now pcommon.Timestamp,
- hs mo.HostSystem,
- ) {
- s := hs.Summary
- h := s.Hardware
- z := s.QuickStats
- v.mb.RecordVcenterHostMemoryUsageDataPoint(now, int64(z.OverallMemoryUsage))
- memUtilization := 100 * float64(z.OverallMemoryUsage) / float64(h.MemorySize>>20)
- v.mb.RecordVcenterHostMemoryUtilizationDataPoint(now, memUtilization)
- v.mb.RecordVcenterHostCPUUsageDataPoint(now, int64(z.OverallCpuUsage))
- cpuUtilization := 100 * float64(z.OverallCpuUsage) / float64(int32(h.NumCpuCores)*h.CpuMhz)
- v.mb.RecordVcenterHostCPUUtilizationDataPoint(now, cpuUtilization)
- }
- func (v *vcenterMetricScraper) recordVMUsages(
- now pcommon.Timestamp,
- vm mo.VirtualMachine,
- hs mo.HostSystem,
- ) {
- memUsage := vm.Summary.QuickStats.GuestMemoryUsage
- balloonedMem := vm.Summary.QuickStats.BalloonedMemory
- swappedMem := vm.Summary.QuickStats.SwappedMemory
- swappedSSDMem := vm.Summary.QuickStats.SsdSwappedMemory
- if totalMemory := vm.Summary.Config.MemorySizeMB; totalMemory > 0 && memUsage > 0 {
- memoryUtilization := float64(memUsage) / float64(totalMemory) * 100
- v.mb.RecordVcenterVMMemoryUtilizationDataPoint(now, memoryUtilization)
- }
- v.mb.RecordVcenterVMMemoryUsageDataPoint(now, int64(memUsage))
- v.mb.RecordVcenterVMMemoryBalloonedDataPoint(now, int64(balloonedMem))
- v.mb.RecordVcenterVMMemorySwappedDataPoint(now, int64(swappedMem))
- v.mb.RecordVcenterVMMemorySwappedSsdDataPoint(now, swappedSSDMem)
- diskUsed := vm.Summary.Storage.Committed
- diskFree := vm.Summary.Storage.Uncommitted
- v.mb.RecordVcenterVMDiskUsageDataPoint(now, diskUsed, metadata.AttributeDiskStateUsed)
- v.mb.RecordVcenterVMDiskUsageDataPoint(now, diskFree, metadata.AttributeDiskStateAvailable)
- if diskFree != 0 {
- diskUtilization := float64(diskUsed) / float64(diskFree+diskUsed) * 100
- v.mb.RecordVcenterVMDiskUtilizationDataPoint(now, diskUtilization)
- }
- cpuUsage := vm.Summary.QuickStats.OverallCpuUsage
- if cpuUsage == 0 {
- // Most likely the VM is unavailable or is unreachable.
- return
- }
- v.mb.RecordVcenterVMCPUUsageDataPoint(now, int64(cpuUsage))
- // https://communities.vmware.com/t5/VMware-code-Documents/Resource-Management/ta-p/2783456
- // VirtualMachine.runtime.maxCpuUsage is a property of the virtual machine, indicating the limit value.
- // This value is always equal to the limit value set for that virtual machine.
- // If no limit, it has full host mhz * vm.Config.Hardware.NumCPU.
- cpuLimit := vm.Config.Hardware.NumCPU * hs.Summary.Hardware.CpuMhz
- if vm.Runtime.MaxCpuUsage != 0 {
- cpuLimit = vm.Runtime.MaxCpuUsage
- }
- if cpuLimit == 0 {
- // This shouldn't happen, but protect against division by zero.
- return
- }
- v.mb.RecordVcenterVMCPUUtilizationDataPoint(now, 100*float64(cpuUsage)/float64(cpuLimit))
- }
- func (v *vcenterMetricScraper) recordDatastoreProperties(
- now pcommon.Timestamp,
- ds mo.Datastore,
- ) {
- s := ds.Summary
- diskUsage := s.Capacity - s.FreeSpace
- diskUtilization := float64(diskUsage) / float64(s.Capacity) * 100
- v.mb.RecordVcenterDatastoreDiskUsageDataPoint(now, diskUsage, metadata.AttributeDiskStateUsed)
- v.mb.RecordVcenterDatastoreDiskUsageDataPoint(now, s.FreeSpace, metadata.AttributeDiskStateAvailable)
- v.mb.RecordVcenterDatastoreDiskUtilizationDataPoint(now, diskUtilization)
- }
- func (v *vcenterMetricScraper) recordResourcePool(
- now pcommon.Timestamp,
- rp mo.ResourcePool,
- ) {
- s := rp.Summary.GetResourcePoolSummary()
- if s.QuickStats != nil {
- v.mb.RecordVcenterResourcePoolCPUUsageDataPoint(now, s.QuickStats.OverallCpuUsage)
- v.mb.RecordVcenterResourcePoolMemoryUsageDataPoint(now, s.QuickStats.GuestMemoryUsage)
- }
- v.mb.RecordVcenterResourcePoolCPUSharesDataPoint(now, int64(s.Config.CpuAllocation.Shares.Shares))
- v.mb.RecordVcenterResourcePoolMemorySharesDataPoint(now, int64(s.Config.MemoryAllocation.Shares.Shares))
- }
- var hostPerfMetricList = []string{
- // network metrics
- "net.bytesTx.average",
- "net.bytesRx.average",
- "net.packetsTx.summation",
- "net.packetsRx.summation",
- "net.usage.average",
- "net.errorsRx.summation",
- "net.errorsTx.summation",
- // disk metrics
- "virtualDisk.totalWriteLatency.average",
- "disk.deviceReadLatency.average",
- "disk.deviceWriteLatency.average",
- "disk.kernelReadLatency.average",
- "disk.kernelWriteLatency.average",
- "disk.maxTotalLatency.latest",
- "disk.read.average",
- "disk.write.average",
- }
- func (v *vcenterMetricScraper) recordHostPerformanceMetrics(
- ctx context.Context,
- host mo.HostSystem,
- errs *scrapererror.ScrapeErrors,
- ) {
- spec := types.PerfQuerySpec{
- Entity: host.Reference(),
- MaxSample: 5,
- Format: string(types.PerfFormatNormal),
- MetricId: []types.PerfMetricId{{Instance: "*"}},
- // right now we are only grabbing real time metrics from the performance
- // manager
- IntervalId: int32(20),
- }
- info, err := v.client.performanceQuery(ctx, spec, hostPerfMetricList, []types.ManagedObjectReference{host.Reference()})
- if err != nil {
- errs.AddPartial(1, err)
- return
- }
- if v.emitPerfWithObject {
- v.processHostPerformance(info.results)
- } else {
- v.processHostPerformanceWithoutObject(info.results)
- }
- }
- // vmPerfMetricList may be customizable in the future but here is the full list of Virtual Machine Performance Counters
- // https://docs.vmware.com/en/vRealize-Operations/8.6/com.vmware.vcom.metrics.doc/GUID-1322F5A4-DA1D-481F-BBEA-99B228E96AF2.html
- var vmPerfMetricList = []string{
- // network metrics
- "net.packetsTx.summation",
- "net.packetsRx.summation",
- "net.bytesRx.average",
- "net.bytesTx.average",
- "net.usage.average",
- // disk metrics
- "disk.totalWriteLatency.average",
- "disk.totalReadLatency.average",
- "disk.maxTotalLatency.latest",
- "virtualDisk.totalWriteLatency.average",
- "virtualDisk.totalReadLatency.average",
- }
- func (v *vcenterMetricScraper) recordVMPerformance(
- ctx context.Context,
- vm mo.VirtualMachine,
- errs *scrapererror.ScrapeErrors,
- ) {
- spec := types.PerfQuerySpec{
- Entity: vm.Reference(),
- Format: string(types.PerfFormatNormal),
- // Just grabbing real time performance metrics of the current
- // supported metrics by this receiver. If more are added we may need
- // a system of making this user customizable or adapt to use a 5 minute interval per metric
- IntervalId: int32(20),
- }
- info, err := v.client.performanceQuery(ctx, spec, vmPerfMetricList, []types.ManagedObjectReference{vm.Reference()})
- if err != nil {
- errs.AddPartial(1, err)
- return
- }
- if v.emitPerfWithObject {
- v.processVMPerformanceMetrics(info)
- } else {
- v.processVMPerformanceMetricsWithoutObject(info)
- }
- }
- func (v *vcenterMetricScraper) processVMPerformanceMetrics(info *perfSampleResult) {
- for _, m := range info.results {
- for _, val := range m.Value {
- for j, nestedValue := range val.Value {
- si := m.SampleInfo[j]
- switch val.Name {
- // Performance monitoring level 1 metrics
- case "net.bytesTx.average":
- v.mb.RecordVcenterVMNetworkThroughputDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted, val.Instance)
- case "net.bytesRx.average":
- v.mb.RecordVcenterVMNetworkThroughputDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived, val.Instance)
- case "net.usage.average":
- v.mb.RecordVcenterVMNetworkUsageDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, val.Instance)
- case "net.packetsTx.summation":
- v.mb.RecordVcenterVMNetworkPacketCountDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted, val.Instance)
- case "net.packetsRx.summation":
- v.mb.RecordVcenterVMNetworkPacketCountDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived, val.Instance)
- // Performance monitoring level 2 metrics required
- case "disk.totalReadLatency.average":
- v.mb.RecordVcenterVMDiskLatencyAvgDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionRead, metadata.AttributeDiskTypePhysical, val.Instance)
- case "virtualDisk.totalReadLatency.average":
- v.mb.RecordVcenterVMDiskLatencyAvgDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionRead, metadata.AttributeDiskTypeVirtual, val.Instance)
- case "disk.totalWriteLatency.average":
- v.mb.RecordVcenterVMDiskLatencyAvgDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionWrite, metadata.AttributeDiskTypePhysical, val.Instance)
- case "virtualDisk.totalWriteLatency.average":
- v.mb.RecordVcenterVMDiskLatencyAvgDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionWrite, metadata.AttributeDiskTypeVirtual, val.Instance)
- case "disk.maxTotalLatency.latest":
- v.mb.RecordVcenterVMDiskLatencyMaxDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, val.Instance)
- }
- }
- }
- }
- }
- func (v *vcenterMetricScraper) processVMPerformanceMetricsWithoutObject(info *perfSampleResult) {
- for _, m := range info.results {
- for _, val := range m.Value {
- for j, nestedValue := range val.Value {
- si := m.SampleInfo[j]
- switch val.Name {
- // Performance monitoring level 1 metrics
- case "net.bytesTx.average":
- v.mb.RecordVcenterVMNetworkThroughputDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted)
- case "net.bytesRx.average":
- v.mb.RecordVcenterVMNetworkThroughputDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived)
- case "net.usage.average":
- v.mb.RecordVcenterVMNetworkUsageDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue)
- case "net.packetsTx.summation":
- v.mb.RecordVcenterVMNetworkPacketCountDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted)
- case "net.packetsRx.summation":
- v.mb.RecordVcenterVMNetworkPacketCountDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived)
- // Performance monitoring level 2 metrics required
- case "disk.totalReadLatency.average":
- v.mb.RecordVcenterVMDiskLatencyAvgDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionRead, metadata.AttributeDiskTypePhysical)
- case "virtualDisk.totalReadLatency.average":
- v.mb.RecordVcenterVMDiskLatencyAvgDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionRead, metadata.AttributeDiskTypeVirtual)
- case "disk.totalWriteLatency.average":
- v.mb.RecordVcenterVMDiskLatencyAvgDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionWrite, metadata.AttributeDiskTypePhysical)
- case "virtualDisk.totalWriteLatency.average":
- v.mb.RecordVcenterVMDiskLatencyAvgDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionWrite, metadata.AttributeDiskTypeVirtual)
- case "disk.maxTotalLatency.latest":
- v.mb.RecordVcenterVMDiskLatencyMaxDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue)
- }
- }
- }
- }
- }
- func (v *vcenterMetricScraper) processHostPerformance(metrics []performance.EntityMetric) {
- for _, m := range metrics {
- for _, val := range m.Value {
- for j, nestedValue := range val.Value {
- si := m.SampleInfo[j]
- switch val.Name {
- // Performance monitoring level 1 metrics
- case "net.usage.average":
- v.mb.RecordVcenterHostNetworkUsageDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, val.Instance)
- case "net.bytesTx.average":
- v.mb.RecordVcenterHostNetworkThroughputDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted, val.Instance)
- case "net.bytesRx.average":
- v.mb.RecordVcenterHostNetworkThroughputDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived, val.Instance)
- case "net.packetsTx.summation":
- v.mb.RecordVcenterHostNetworkPacketCountDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted, val.Instance)
- case "net.packetsRx.summation":
- v.mb.RecordVcenterHostNetworkPacketCountDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived, val.Instance)
- // Following requires performance level 2
- case "net.errorsRx.summation":
- v.mb.RecordVcenterHostNetworkPacketErrorsDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived, val.Instance)
- case "net.errorsTx.summation":
- v.mb.RecordVcenterHostNetworkPacketErrorsDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted, val.Instance)
- case "disk.totalWriteLatency.average":
- v.mb.RecordVcenterHostDiskLatencyAvgDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionWrite, val.Instance)
- case "disk.totalReadLatency.average":
- v.mb.RecordVcenterHostDiskLatencyAvgDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionRead, val.Instance)
- case "disk.maxTotalLatency.latest":
- v.mb.RecordVcenterHostDiskLatencyMaxDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, val.Instance)
- // Following requires performance level 4
- case "disk.read.average":
- v.mb.RecordVcenterHostDiskThroughputDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionRead, val.Instance)
- case "disk.write.average":
- v.mb.RecordVcenterHostDiskThroughputDataPoint(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionWrite, val.Instance)
- }
- }
- }
- }
- }
- func (v *vcenterMetricScraper) processHostPerformanceWithoutObject(metrics []performance.EntityMetric) {
- for _, m := range metrics {
- for _, val := range m.Value {
- for j, nestedValue := range val.Value {
- si := m.SampleInfo[j]
- switch val.Name {
- // Performance monitoring level 1 metrics
- case "net.usage.average":
- v.mb.RecordVcenterHostNetworkUsageDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue)
- case "net.bytesTx.average":
- v.mb.RecordVcenterHostNetworkThroughputDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted)
- case "net.bytesRx.average":
- v.mb.RecordVcenterHostNetworkThroughputDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived)
- case "net.packetsTx.summation":
- v.mb.RecordVcenterHostNetworkPacketCountDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted)
- case "net.packetsRx.summation":
- v.mb.RecordVcenterHostNetworkPacketCountDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived)
- // Following requires performance level 2
- case "net.errorsRx.summation":
- v.mb.RecordVcenterHostNetworkPacketErrorsDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionReceived)
- case "net.errorsTx.summation":
- v.mb.RecordVcenterHostNetworkPacketErrorsDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeThroughputDirectionTransmitted)
- case "disk.totalWriteLatency.average":
- v.mb.RecordVcenterHostDiskLatencyAvgDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionWrite)
- case "disk.totalReadLatency.average":
- v.mb.RecordVcenterHostDiskLatencyAvgDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionRead)
- case "disk.maxTotalLatency.latest":
- v.mb.RecordVcenterHostDiskLatencyMaxDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue)
- // Following requires performance level 4
- case "disk.read.average":
- v.mb.RecordVcenterHostDiskThroughputDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionRead)
- case "disk.write.average":
- v.mb.RecordVcenterHostDiskThroughputDataPointWithoutObject(pcommon.NewTimestampFromTime(si.Timestamp), nestedValue, metadata.AttributeDiskDirectionWrite)
- }
- }
- }
- }
- }
|