From c3a001cb56a46eab7d8b247821b0fdd557e1a624 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:02:59 +0530 Subject: [PATCH] [8.x](backport #40766) [Metricbeat][vSphere] New metrics support and minor changes to existing metricsets (#40807) * [Metricbeat][vSphere] New metrics support and minor changes to existing metricsets (#40766) * initial commit * update field mappings * update virtual machine data.json * format data.json * resolve review comments * add changelog entry (cherry picked from commit 3f44bd1f9bf0b3e17c8254119c464cbb7e872c71) # Conflicts: # metricbeat/module/vsphere/datastore/_meta/data.json # metricbeat/module/vsphere/datastore/datastore.go # metricbeat/module/vsphere/fields.go # metricbeat/module/vsphere/host/_meta/data.json # metricbeat/module/vsphere/host/host.go # metricbeat/module/vsphere/virtualmachine/_meta/data.json # metricbeat/module/vsphere/virtualmachine/data_test.go # metricbeat/module/vsphere/virtualmachine/virtualmachine.go * fix existing conflicts * remove extra changelog entries --------- Co-authored-by: Kush Rana <89848966+kush-elastic@users.noreply.github.com> Co-authored-by: Kush Rana --- CHANGELOG.next.asciidoc | 1 + metricbeat/docs/fields.asciidoc | 66 ++++---- .../module/vsphere/datastore/_meta/data.json | 56 ++++--- .../module/vsphere/datastore/_meta/fields.yml | 27 ++-- metricbeat/module/vsphere/datastore/data.go | 14 +- .../module/vsphere/datastore/data_test.go | 32 ++-- .../module/vsphere/datastore/datastore.go | 89 ++++++----- .../vsphere/datastore/datastore_test.go | 25 ++- metricbeat/module/vsphere/fields.go | 2 +- .../module/vsphere/host/_meta/data.json | 125 +++++++++------ metricbeat/module/vsphere/host/host.go | 71 +++++---- .../vsphere/virtualmachine/_meta/data.json | 146 +++++++++--------- .../vsphere/virtualmachine/_meta/fields.yml | 5 +- .../vsphere/virtualmachine/data_test.go | 10 +- .../vsphere/virtualmachine/virtualmachine.go | 8 +- 15 files changed, 379 insertions(+), 298 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 195baa976c8..09e223a3cc3 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -339,6 +339,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff] - Add new metricset resourcepool for the vSphere module. {pull}40456[40456] - Add metrics for the vSphere Virtualmachine metricset. {pull}40485[40485] - Log the total time taken for GCP `ListTimeSeries` and `AggregatedList` requests {pull}40661[40661] +- Add new metrics fot datastore and minor changes to overall vSphere metrics {pull}40766[40766] - Add new metrics for the vSphere Host metricset. {pull}40429[40429] - Add new metrics for the vSphere Datastore metricset. {pull}40441[40441] - Add new metricset cluster for the vSphere module. {pull}40536[40536] diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 1a9b61e97ae..697ee9b8ae1 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -67175,76 +67175,92 @@ format: percent -- -*`vsphere.datastore.fstype`*:: +*`vsphere.datastore.disk.capacity.bytes`*:: + -- -Filesystem type. +Configured size of the datastore. -type: keyword +type: long + +format: bytes -- -*`vsphere.datastore.host.count`*:: +*`vsphere.datastore.disk.capacity.usage.bytes`*:: + -- -Number of hosts. +The amount of storage capacity currently being consumed by datastore. type: long +format: bytes + -- -*`vsphere.datastore.host.names`*:: +*`vsphere.datastore.disk.provisioned.bytes`*:: + -- -List of all the host names. +Amount of storage set aside for use by a datastore. + + +type: long + +format: bytes + +-- + +*`vsphere.datastore.fstype`*:: ++ +-- +Filesystem type. type: keyword -- -*`vsphere.datastore.iops`*:: +*`vsphere.datastore.host.count`*:: + -- -Storage I/O Control aggregated Input/Output Operations Per Second. +Number of hosts. type: long -- -*`vsphere.datastore.name`*:: +*`vsphere.datastore.host.names`*:: + -- -Datastore name. +List of all the host names. type: keyword -- -*`vsphere.datastore.read.bytes`*:: +*`vsphere.datastore.name`*:: + -- -Rate of reading data from the datastore. - +Datastore name. -type: long -format: bytes +type: keyword -- -*`vsphere.datastore.read.latency.total.ms`*:: +*`vsphere.datastore.read.bytes`*:: + -- -Average amount of time for a read operation from the datastore in milliseconds. +Rate of reading data from the datastore. type: long +format: bytes + -- *`vsphere.datastore.status`*:: @@ -67289,16 +67305,6 @@ format: bytes -- -*`vsphere.datastore.write.latency.total.ms`*:: -+ --- -Average amount of time for a write operation from the datastore in milliseconds. - - -type: long - --- - [float] === datastorecluster @@ -68281,10 +68287,10 @@ type: long -- -*`vsphere.virtualmachine.snapshot.info`*:: +*`vsphere.virtualmachine.snapshot.info.*`*:: + -- -Deatils of the snapshots of this virtualmachine. +Details of the snapshots of this virtualmachine. type: object diff --git a/metricbeat/module/vsphere/datastore/_meta/data.json b/metricbeat/module/vsphere/datastore/_meta/data.json index 9ab349a293c..dc690b8d40e 100644 --- a/metricbeat/module/vsphere/datastore/_meta/data.json +++ b/metricbeat/module/vsphere/datastore/_meta/data.json @@ -10,39 +10,55 @@ "period": 10000 }, "service": { - "address": "127.0.0.1:55632", + "address": "127.0.0.1:33365", "type": "vsphere" }, "vsphere": { "datastore": { - "capacity": { - "free": { - "bytes": 10973641441280 - }, - "total": { - "bytes": 10995116277760 - }, - "used": { - "bytes": 21474836480, - "pct": 0.001953125 - } - }, - "fstype": "OTHER", "host": { "count": 1, "names": [ - "localhost_localdomain" + "DC3_H0" ] }, - "name": "LocalDS_0", "status": "green", "vm": { - "count": 2, + "count": 6, "names": [ - "ha-host_VM0", - "ha-host_VM1" + "DC3_H0_VM0" ] - } + }, + "read": { + "bytes": 0 + }, + "write": { + "bytes": 337000 + }, + "disk": { + "capacity": { + "usage": { + "bytes": 520505786368 + }, + "bytes": 1610344300544 + }, + "provisioned": { + "bytes": 520505786368 + } + }, + "capacity": { + "free": { + "bytes": 37120094208 + }, + "total": { + "bytes": 74686664704 + }, + "used": { + "bytes": 37566570496, + "pct": 0.502988996026061 + } + }, + "fstype": "local", + "name": "LocalDS_0" } } } \ No newline at end of file diff --git a/metricbeat/module/vsphere/datastore/_meta/fields.yml b/metricbeat/module/vsphere/datastore/_meta/fields.yml index e9fb22a486d..e44f5cec7f2 100644 --- a/metricbeat/module/vsphere/datastore/_meta/fields.yml +++ b/metricbeat/module/vsphere/datastore/_meta/fields.yml @@ -24,6 +24,21 @@ description: > Percentage of datastore capacity used. format: percent + - name: disk.capacity.bytes + type: long + description: > + Configured size of the datastore. + format: bytes + - name: disk.capacity.usage.bytes + type: long + description: > + The amount of storage capacity currently being consumed by datastore. + format: bytes + - name: disk.provisioned.bytes + type: long + description: > + Amount of storage set aside for use by a datastore. + format: bytes - name: fstype type: keyword description: > @@ -36,10 +51,6 @@ type: keyword description: > List of all the host names. - - name: iops - type: long - description: > - Storage I/O Control aggregated Input/Output Operations Per Second. - name: name type: keyword description: > @@ -49,10 +60,6 @@ description: > Rate of reading data from the datastore. format: bytes - - name: read.latency.total.ms - type: long - description: > - Average amount of time for a read operation from the datastore in milliseconds. - name: status type: keyword description: > @@ -70,8 +77,4 @@ description: > Rate of writing data to the datastore. format: bytes - - name: write.latency.total.ms - type: long - description: > - Average amount of time for a write operation from the datastore in milliseconds. diff --git a/metricbeat/module/vsphere/datastore/data.go b/metricbeat/module/vsphere/datastore/data.go index 0b438f96268..413854cafa7 100644 --- a/metricbeat/module/vsphere/datastore/data.go +++ b/metricbeat/module/vsphere/datastore/data.go @@ -65,16 +65,16 @@ func mapPerfMetricToEvent(event mapstr.M, perfMetricMap map[string]interface{}) if val, exist := perfMetricMap["datastore.read.average"]; exist { event.Put("read.bytes", val.(int64)*bytesMultiplier) } - if val, exist := perfMetricMap["datastore.totalReadLatency.average"]; exist { - event.Put("read.latency.total.ms", val) - } if val, exist := perfMetricMap["datastore.write.average"]; exist { event.Put("write.bytes", val.(int64)*bytesMultiplier) } - if val, exist := perfMetricMap["datastore.totalWriteLatency.average"]; exist { - event.Put("write.latency.total.ms", val) + if val, exist := perfMetricMap["disk.capacity.latest"]; exist { + event.Put("disk.capacity.bytes", val.(int64)*bytesMultiplier) + } + if val, exist := perfMetricMap["disk.capacity.usage.average"]; exist { + event.Put("disk.capacity.usage.bytes", val.(int64)*bytesMultiplier) } - if val, exist := perfMetricMap["datastore.datastoreIops.average"]; exist { - event.Put("iops", val) + if val, exist := perfMetricMap["disk.provisioned.latest"]; exist { + event.Put("disk.provisioned.bytes", val.(int64)*bytesMultiplier) } } diff --git a/metricbeat/module/vsphere/datastore/data_test.go b/metricbeat/module/vsphere/datastore/data_test.go index 4ecc091794c..23189e3e49f 100644 --- a/metricbeat/module/vsphere/datastore/data_test.go +++ b/metricbeat/module/vsphere/datastore/data_test.go @@ -28,7 +28,6 @@ import ( ) func TestEventMapping(t *testing.T) { - var m *DataStoreMetricSet var datastoreTest = mo.Datastore{ Summary: types.DatastoreSummary{ Name: "datastore-test", @@ -47,11 +46,11 @@ func TestEventMapping(t *testing.T) { var metricDataTest = metricData{ perfMetrics: map[string]interface{}{ - "datastore.read.average": int64(100), - "datastore.write.average": int64(200), - "datastore.datastoreIops.average": int64(10), - "datastore.totalReadLatency.average": int64(100), - "datastore.totalWriteLatency.average": int64(100), + "datastore.read.average": int64(100), + "datastore.write.average": int64(200), + "disk.capacity.latest": int64(10000), + "disk.capacity.usage.average": int64(5000), + "disk.provisioned.latest": int64(5000), }, assetNames: assetNames{ outputHostNames: []string{"DC3_H0"}, @@ -59,11 +58,10 @@ func TestEventMapping(t *testing.T) { }, } - outputEvent := m.mapEvent(datastoreTest, &metricDataTest) + outputEvent := (&DataStoreMetricSet{}).mapEvent(datastoreTest, &metricDataTest) testEvent := mapstr.M{ "fstype": "local", "status": types.ManagedEntityStatus("green"), - "iops": int64(10), "name": "datastore-test", "host": mapstr.M{ "count": 1, @@ -75,19 +73,20 @@ func TestEventMapping(t *testing.T) { }, "read": mapstr.M{ "bytes": int64(102400), - "latency": mapstr.M{ - "total": mapstr.M{ - "ms": int64(100), - }, - }, }, "write": mapstr.M{ "bytes": int64(204800), - "latency": mapstr.M{ - "total": mapstr.M{ - "ms": int64(100), + }, + "disk": mapstr.M{ + "capacity": mapstr.M{ + "bytes": int64(10240000), + "usage": mapstr.M{ + "bytes": int64(5120000), }, }, + "provisioned": mapstr.M{ + "bytes": int64(5120000), + }, }, "capacity": mapstr.M{ "free": mapstr.M{ @@ -104,5 +103,4 @@ func TestEventMapping(t *testing.T) { } assert.Exactly(t, outputEvent, testEvent) - } diff --git a/metricbeat/module/vsphere/datastore/datastore.go b/metricbeat/module/vsphere/datastore/datastore.go index 3014ec0e3f5..79ab67fe978 100644 --- a/metricbeat/module/vsphere/datastore/datastore.go +++ b/metricbeat/module/vsphere/datastore/datastore.go @@ -66,11 +66,11 @@ type assetNames struct { // Define metrics to be collected var metricSet = map[string]struct{}{ - "datastore.read.average": {}, - "datastore.write.average": {}, - "datastore.datastoreIops.average": {}, - "datastore.totalReadLatency.average": {}, - "datastore.totalWriteLatency.average": {}, + "datastore.read.average": {}, + "datastore.write.average": {}, + "disk.capacity.latest": {}, + "disk.capacity.usage.average": {}, + "disk.provisioned.latest": {}, } // Fetch methods implements the data gathering and data conversion to the right @@ -97,7 +97,7 @@ func (m *DataStoreMetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) v, err := mgr.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"Datastore"}, true) if err != nil { - return fmt.Errorf("error in CreateContainerView: %w", err) + return fmt.Errorf("error in creating container view: %w", err) } defer func() { @@ -122,39 +122,28 @@ func (m *DataStoreMetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) return fmt.Errorf("failed to retrieve metrics: %w", err) } - // Filter for required metrics - var metricIds []types.PerfMetricId - for metricName := range metricSet { - if metric, ok := metrics[metricName]; ok { - metricIds = append(metricIds, types.PerfMetricId{CounterId: metric.Key}) - } else { - m.Logger().Warnf("Metric %s not found", metricName) - } - } - - pc := property.DefaultCollector(c) + pc := property.DefaultCollector(client.Client) for i := range dst { - select { - case <-ctx.Done(): + if ctx.Err() != nil { return ctx.Err() - default: - assetNames, err := getAssetNames(ctx, pc, &dst[i]) - if err != nil { - m.Logger().Errorf("Failed to retrieve object from datastore %s: %v", dst[i].Name, err) - } + } - metricMap, err := m.getPerfMetrics(ctx, perfManager, dst[i], metricIds) - if err != nil { - m.Logger().Errorf("Failed to retrieve performance metrics from datastore %s: %v", dst[i].Name, err) - } + assetNames, err := getAssetNames(ctx, pc, &dst[i]) + if err != nil { + m.Logger().Errorf("Failed to retrieve object from datastore %s: %v", dst[i].Name, err) + } - reporter.Event(mb.Event{ - MetricSetFields: m.mapEvent(dst[i], &metricData{ - perfMetrics: metricMap, - assetNames: assetNames, - }), - }) + metricMap, err := m.getPerfMetrics(ctx, perfManager, dst[i], metrics) + if err != nil { + m.Logger().Errorf("Failed to retrieve performance metrics from datastore %s: %v", dst[i].Name, err) } + + reporter.Event(mb.Event{ + MetricSetFields: m.mapEvent(dst[i], &metricData{ + perfMetrics: metricMap, + assetNames: assetNames, + }), + }) } return nil @@ -167,6 +156,7 @@ func getAssetNames(ctx context.Context, pc *property.Collector, ds *mo.Datastore if err := pc.Retrieve(ctx, ds.Vm, []string{"name"}, &objects); err != nil { return assetNames{}, err } + for _, ob := range objects { if ob.Reference().Type == "VirtualMachine" { name := strings.ReplaceAll(ob.Name, ".", "_") @@ -174,6 +164,7 @@ func getAssetNames(ctx context.Context, pc *property.Collector, ds *mo.Datastore } } } + // calling Host explicitly because of mo.Datastore.Host has types.DatastoreHostMount instead of mo.ManagedEntity outputHostNames := make([]string, 0, len(ds.Host)) if len(ds.Host) > 0 { @@ -205,17 +196,37 @@ func getAssetNames(ctx context.Context, pc *property.Collector, ds *mo.Datastore }, nil } -func (m *DataStoreMetricSet) getPerfMetrics(ctx context.Context, perfManager *performance.Manager, dst mo.Datastore, metricIds []types.PerfMetricId) (metricMap map[string]interface{}, err error) { +func (m *DataStoreMetricSet) getPerfMetrics(ctx context.Context, perfManager *performance.Manager, dst mo.Datastore, metrics map[string]*types.PerfCounterInfo) (metricMap map[string]interface{}, err error) { metricMap = make(map[string]interface{}) - period := m.Module().Config().Period - refreshRate := int32(period.Seconds()) + period := int32(m.Module().Config().Period.Seconds()) + availableMetric, err := perfManager.AvailableMetric(ctx, dst.Reference(), period) + if err != nil { + return nil, fmt.Errorf("failed to get available metrics: %w", err) + } + + availableMetricByKey := availableMetric.ByKey() + + // Filter for required metrics + var metricIDs []types.PerfMetricId + for key, metric := range metricSet { + if counter, ok := metrics[key]; ok { + if _, exists := availableMetricByKey[counter.Key]; exists { + metricIDs = append(metricIDs, types.PerfMetricId{ + CounterId: counter.Key, + Instance: "*", + }) + } + } else { + m.Logger().Warnf("Metric %s not found", metric) + } + } spec := types.PerfQuerySpec{ Entity: dst.Reference(), - MetricId: metricIds, + MetricId: metricIDs, MaxSample: 1, - IntervalId: refreshRate, // using refreshRate as interval + IntervalId: period, // using refreshRate as interval } // Query performance data diff --git a/metricbeat/module/vsphere/datastore/datastore_test.go b/metricbeat/module/vsphere/datastore/datastore_test.go index d9a9a548780..a33ed414b39 100644 --- a/metricbeat/module/vsphere/datastore/datastore_test.go +++ b/metricbeat/module/vsphere/datastore/datastore_test.go @@ -19,7 +19,6 @@ package datastore import ( "testing" - "time" mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" @@ -33,19 +32,15 @@ func TestFetchEventContents(t *testing.T) { model := simulator.VPX() err := model.Create() require.NoError(t, err, "failed to create model") - t.Cleanup(func() { model.Remove() }) + t.Cleanup(model.Remove) ts := model.Service.NewServer() - t.Cleanup(func() { ts.Close() }) + t.Cleanup(ts.Close) f := mbtest.NewReportingMetricSetV2WithContext(t, getConfig(ts)) events, errs := mbtest.ReportingFetchV2WithContext(f) - if len(errs) > 0 { - t.Fatalf("Expected 0 error, had %d. %v\n", len(errs), errs) - } - require.Empty(t, errs, "expected no error") - - require.NotEmpty(t, events, "didn't get any event, should have gotten at least X") + require.Empty(t, errs, "Expected no errors during fetch") + require.NotEmpty(t, events, "Expected to receive at least one event") event := events[0].MetricSetFields @@ -63,6 +58,9 @@ func TestFetchEventContents(t *testing.T) { "vm.count", "write.bytes", "capacity.used.bytes", + "disk.capacity.usage.bytes", + "disk.capacity.bytes", + "disk.provisioned.bytes", } for _, field := range fields { value, err := event.GetValue(field) @@ -85,10 +83,10 @@ func TestDataStoreMetricSetData(t *testing.T) { model := simulator.ESX() err := model.Create() require.NoError(t, err, "failed to create model") - t.Cleanup(func() { model.Remove() }) + t.Cleanup(model.Remove) ts := model.Service.NewServer() - t.Cleanup(func() { ts.Close() }) + t.Cleanup(ts.Close) f := mbtest.NewReportingMetricSetV2WithContext(t, getConfig(ts)) @@ -97,15 +95,12 @@ func TestDataStoreMetricSetData(t *testing.T) { } func getConfig(ts *simulator.Server) map[string]interface{} { - urlSimulator := ts.URL.Scheme + "://" + ts.URL.Host + ts.URL.Path - return map[string]interface{}{ "module": "vsphere", "metricsets": []string{"datastore"}, - "hosts": []string{urlSimulator}, + "hosts": []string{ts.URL.String()}, "username": "user", "password": "pass", "insecure": true, - "period": time.Second * 20, } } diff --git a/metricbeat/module/vsphere/fields.go b/metricbeat/module/vsphere/fields.go index 7693e0a4328..54f4f093b7a 100644 --- a/metricbeat/module/vsphere/fields.go +++ b/metricbeat/module/vsphere/fields.go @@ -32,5 +32,5 @@ func init() { // AssetVsphere returns asset data. // This is the base64 encoded zlib format compressed contents of module/vsphere. func AssetVsphere() string { - return "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" + return "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" } diff --git a/metricbeat/module/vsphere/host/_meta/data.json b/metricbeat/module/vsphere/host/_meta/data.json index 568d08f97c9..462000c6243 100644 --- a/metricbeat/module/vsphere/host/_meta/data.json +++ b/metricbeat/module/vsphere/host/_meta/data.json @@ -1,46 +1,55 @@ { - "@timestamp": "2017-10-12T08:05:34.853Z", - "event": { - "dataset": "vsphere.host", - "duration": 115000, - "module": "vsphere" - }, + "@timestamp": "2022-09-06T06:41:22.128Z", "metricset": { "name": "host", "period": 10000 }, "service": { - "address": "127.0.0.1:55538", + "address": "https://localhost:8989/sdk", "type": "vsphere" }, + "event": { + "module": "vsphere", + "duration": 23519250, + "dataset": "vsphere.host" + }, "vsphere": { "host": { "cpu": { - "free": { - "mhz": 4521 + "used": { + "mhz": 67 }, "total": { "mhz": 4588 }, - "used": { - "mhz": 67 + "free": { + "mhz": 4521 } }, - "datastore": { - "count": 1, - "names": [ - "LocalDS_0" - ] - }, "disk": { - "read": { - "bytes": 159744 + "capacity": { + "usage": { + "bytes": 0 + } + }, + "devicelatency": { + "average": { + "ms": 0 + } + }, + "latency": { + "total": { + "ms": 18 + } }, "total": { - "bytes": 401408 + "bytes": 262000 + }, + "read": { + "bytes": 13000 }, "write": { - "bytes": 259072 + "bytes": 248000 } }, "memory": { @@ -54,49 +63,79 @@ "bytes": 1472200704 } }, - "name": "localhost.localdomain", "network": { "bandwidth": { - "received": { - "bytes": 270336 - }, "total": { - "bytes": 532480 + "bytes": 372000 }, "transmitted": { - "bytes": 249856 + "bytes": 0 + }, + "received": { + "bytes": 371000 } }, - "count": 1, - "names": [ - "VM Network" - ], "packets": { + "received": { + "count": 9463 + }, + "errors": { + "transmitted": { + "count": 0 + }, + "received": { + "count": 0 + }, + "total": { + "count": 0 + } + }, "multicast": { + "total": { + "count": 6679 + }, + "transmitted": { + "count": 0 + }, "received": { - "count": 61 + "count": 6679 } }, - "received": { - "count": 4569 + "dropped": { + "received": { + "count": 0 + }, + "total": { + "count": 0 + }, + "transmitted": { + "count": 0 + } }, "transmitted": { - "count": 4578 + "count": 54 } } }, - "network_names": [ - "VM Network" - ], - "status": "gray", - "uptime": 77229, "vm": { "count": 2, "names": [ - "ha-host_VM0", - "ha-host_VM1" + "DC0_H0_VM0", + "DC0_H0_VM1" ] - } + }, + "datastore": { + "count": 1, + "names": [ + "LocalDS_0" + ] + }, + "network_names": [ + "VM Network" + ], + "name": "DC0_H0", + "status": "green", + "uptime": 1728865 } } } \ No newline at end of file diff --git a/metricbeat/module/vsphere/host/host.go b/metricbeat/module/vsphere/host/host.go index 6248f3e6cba..cd791f5d21b 100644 --- a/metricbeat/module/vsphere/host/host.go +++ b/metricbeat/module/vsphere/host/host.go @@ -136,36 +136,27 @@ func (m *HostMetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error return fmt.Errorf("failed to retrieve metrics: %w", err) } - // Filter for required metrics - var metricIds []types.PerfMetricId - for metricName := range metricSet { - if metric, ok := metrics[metricName]; ok { - metricIds = append(metricIds, types.PerfMetricId{CounterId: metric.Key}) - } else { - m.Logger().Warnf("Metric %s not found", metricName) - } - } - pc := property.DefaultCollector(c) for i := range hst { - select { - case <-ctx.Done(): + if ctx.Err() != nil { return ctx.Err() - default: - assetNames, err := getAssetNames(ctx, pc, &hst[i]) - if err != nil { - m.Logger().Errorf("Failed to retrieve object from host %s: %v", hst[i].Name, err) - } - - metricMap, err := m.getPerfMetrics(ctx, perfManager, hst[i], metricIds) - if err != nil { - m.Logger().Errorf("Failed to retrieve performance metrics from host %s: %v", hst[i].Name, err) - } + } + assetNames, err := getAssetNames(ctx, pc, &hst[i]) + if err != nil { + m.Logger().Errorf("Failed to retrieve object from host %s: %v", hst[i].Name, err) + } - reporter.Event(mb.Event{ - MetricSetFields: m.mapEvent(hst[i], &metricData{perfMetrics: metricMap, assetNames: assetNames}), - }) + metricMap, err := m.getPerfMetrics(ctx, perfManager, hst[i], metrics) + if err != nil { + m.Logger().Errorf("Failed to retrieve performance metrics from host %s: %v", hst[i].Name, err) } + + reporter.Event(mb.Event{ + MetricSetFields: m.mapEvent(hst[i], &metricData{ + perfMetrics: metricMap, + assetNames: assetNames, + }), + }) } return nil @@ -213,17 +204,37 @@ func getAssetNames(ctx context.Context, pc *property.Collector, hs *mo.HostSyste }, nil } -func (m *HostMetricSet) getPerfMetrics(ctx context.Context, perfManager *performance.Manager, hst mo.HostSystem, metricIds []types.PerfMetricId) (metricMap map[string]interface{}, err error) { +func (m *HostMetricSet) getPerfMetrics(ctx context.Context, perfManager *performance.Manager, hst mo.HostSystem, metrics map[string]*types.PerfCounterInfo) (metricMap map[string]interface{}, err error) { metricMap = make(map[string]interface{}) - period := m.Module().Config().Period - refreshRate := int32(period.Seconds()) + period := int32(m.Module().Config().Period.Seconds()) + availableMetric, err := perfManager.AvailableMetric(ctx, hst.Reference(), period) + if err != nil { + return nil, fmt.Errorf("failed to get available metrics: %w", err) + } + + availableMetricByKey := availableMetric.ByKey() + + // Filter for required metrics + var metricIDs []types.PerfMetricId + for key, metric := range metricSet { + if counter, ok := metrics[key]; ok { + if _, exists := availableMetricByKey[counter.Key]; exists { + metricIDs = append(metricIDs, types.PerfMetricId{ + CounterId: counter.Key, + Instance: "*", + }) + } + } else { + m.Logger().Warnf("Metric %s not found", metric) + } + } spec := types.PerfQuerySpec{ Entity: hst.Reference(), - MetricId: metricIds, + MetricId: metricIDs, MaxSample: 1, - IntervalId: refreshRate, + IntervalId: period, } // Query performance data diff --git a/metricbeat/module/vsphere/virtualmachine/_meta/data.json b/metricbeat/module/vsphere/virtualmachine/_meta/data.json index d71b03e4179..8549f84040a 100644 --- a/metricbeat/module/vsphere/virtualmachine/_meta/data.json +++ b/metricbeat/module/vsphere/virtualmachine/_meta/data.json @@ -14,80 +14,80 @@ "type": "vsphere" }, "vsphere": { - "virtualmachine": { - "name": "xt0nmfpv9", - "uptime": 5348978, - "status": "green", - "host": { - "id": "host-32", - "hostname": "phx-w1c1-esxi04.com" - }, - "cpu": { - "free": { - "mhz": 0 - }, - "used": { - "mhz": 161 - }, - "total": { - "mhz": 0 - } - }, - "network": { - "names": [ - "PROD_VCF_VMS" - ], - "count": 1 - }, - "memory": { - "used": { - "guest": { - "bytes": 686817280 - }, + "virtualmachine": { + "name": "xt0nmfpv9", + "uptime": 5348978, + "status": "green", "host": { - "bytes": 29027729408 - } - }, - "total": { - "guest": { - "bytes": 68719476736 - } - }, - "free": { - "guest": { - "bytes": 68032659456 - } - } - }, - "network_names": [ - "PROD_VCF_VMS" - ], - "datastore": { - "count": 1, - "names": [ - "VxRailtoup-Virtual-Datastore-bc1d-5aa310fb" - ] - }, - "os": "CentOS 4/5/6/7 (64-bit)", - "snapshot": { - "info": [ - { - "id": 123, - "name": "Snapshot_1", - "description": "Test snapshot 1", - "createtime": "2024-09-01T12:34:56Z", - "state": "PoweredOff" + "id": "host-32", + "hostname": "phx-w1c1-esxi04.com" + }, + "cpu": { + "free": { + "mhz": 0 + }, + "used": { + "mhz": 161 + }, + "total": { + "mhz": 0 + } + }, + "network": { + "names": [ + "PROD_VCF_VMS" + ], + "count": 1 + }, + "memory": { + "used": { + "guest": { + "bytes": 686817280 + }, + "host": { + "bytes": 29027729408 + } + }, + "total": { + "guest": { + "bytes": 68719476736 + } + }, + "free": { + "guest": { + "bytes": 68032659456 + } + } + }, + "network_names": [ + "PROD_VCF_VMS" + ], + "datastore": { + "count": 1, + "names": [ + "VxRailtoup-Virtual-Datastore-bc1d-5aa310fb" + ] }, - { - "id": 745, - "name": "Snapshot_2", - "description": "Test snapshot 2", - "createtime": "2024-09-03T2:34:56Z", - "state": "PoweredOn" + "os": "CentOS 4/5/6/7 (64-bit)", + "snapshot": { + "info": [ + { + "id": 1, + "name": "VM Snapshot 7%2f3%2f2024, 4:01:21 PM", + "description": "Created to demo", + "createtime": "2024-07-03T20:01:34.329Z", + "state": "poweredOn" + }, + { + "createtime": "2024-07-05T23:35:40.859Z", + "state": "poweredOn", + "id": 2, + "name": "VM Snapshot 7%2f5%2f2024, 7:35:37 PM", + "description": "backup" + } + ], + "count": 2 } - ], - "count": 2 - } - } + } } - } \ No newline at end of file +} \ No newline at end of file diff --git a/metricbeat/module/vsphere/virtualmachine/_meta/fields.yml b/metricbeat/module/vsphere/virtualmachine/_meta/fields.yml index 2e0d61050df..783ca427b34 100644 --- a/metricbeat/module/vsphere/virtualmachine/_meta/fields.yml +++ b/metricbeat/module/vsphere/virtualmachine/_meta/fields.yml @@ -97,9 +97,10 @@ - name: snapshot type: group fields: - - name: info + - name: info.* type: object - description: Deatils of the snapshots of this virtualmachine. + object_type: keyword + description: Details of the snapshots of this virtualmachine. - name: count type: long description: The number of snapshots of this virtualmachine. diff --git a/metricbeat/module/vsphere/virtualmachine/data_test.go b/metricbeat/module/vsphere/virtualmachine/data_test.go index e48518fa8a9..32abe001c39 100644 --- a/metricbeat/module/vsphere/virtualmachine/data_test.go +++ b/metricbeat/module/vsphere/virtualmachine/data_test.go @@ -19,12 +19,12 @@ package virtualmachine import ( "testing" - "time" "github.com/stretchr/testify/assert" "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" + "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/elastic-agent-libs/mapstr" ) @@ -64,14 +64,14 @@ func TestEventMapping(t *testing.T) { ID: 123, Name: "Snapshot_1", Description: "Test snapshot 1", - CreateTime: time.Time{}, + CreateTime: common.Time{}, State: types.VirtualMachinePowerStatePoweredOff, }, { ID: 745, Name: "Snapshot_2", Description: "Test snapshot 2", - CreateTime: time.Time{}, + CreateTime: common.Time{}, State: types.VirtualMachinePowerStatePoweredOn, }, }, @@ -133,14 +133,14 @@ func TestEventMapping(t *testing.T) { ID: 123, Name: "Snapshot_1", Description: "Test snapshot 1", - CreateTime: time.Time{}, + CreateTime: common.Time{}, State: types.VirtualMachinePowerStatePoweredOff, }, { ID: 745, Name: "Snapshot_2", Description: "Test snapshot 2", - CreateTime: time.Time{}, + CreateTime: common.Time{}, State: types.VirtualMachinePowerStatePoweredOn, }, }, diff --git a/metricbeat/module/vsphere/virtualmachine/virtualmachine.go b/metricbeat/module/vsphere/virtualmachine/virtualmachine.go index bcc42b51653..124bc0c56e5 100644 --- a/metricbeat/module/vsphere/virtualmachine/virtualmachine.go +++ b/metricbeat/module/vsphere/virtualmachine/virtualmachine.go @@ -22,8 +22,8 @@ import ( "errors" "fmt" "strings" - "time" + "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/metricbeat/mb" "github.com/elastic/beats/v7/metricbeat/module/vsphere" "github.com/elastic/elastic-agent-libs/mapstr" @@ -64,7 +64,7 @@ type VMSnapshotData struct { ID int32 `json:"id"` Name string `json:"name"` Description string `json:"description"` - CreateTime time.Time `json:"createtime"` + CreateTime common.Time `json:"createtime"` State types.VirtualMachinePowerState `json:"state"` } @@ -136,7 +136,7 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { // Retrieve summary property for all machines var vmt []mo.VirtualMachine - err = v.Retrieve(ctx, []string{"VirtualMachine"}, []string{"summary", "datastore"}, &vmt) + err = v.Retrieve(ctx, []string{"VirtualMachine"}, []string{"summary", "datastore", "snapshot"}, &vmt) if err != nil { return fmt.Errorf("virtualmachine: error in Retrieve: %w", err) } @@ -294,7 +294,7 @@ func fetchSnapshots(snapshotTree []types.VirtualMachineSnapshotTree) []VMSnapsho ID: snapshot.Id, Name: snapshot.Name, Description: snapshot.Description, - CreateTime: snapshot.CreateTime, + CreateTime: common.Time(snapshot.CreateTime), State: snapshot.State, })