From 83a880f47b144661aceeabbd50e4832b51802853 Mon Sep 17 00:00:00 2001 From: Kush Rana <89848966+kush-elastic@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:05:13 +0530 Subject: [PATCH] [vSphere][datastore_cluster] Add support for new metrics in datastore_cluster metricset (#40694) * initial commit * add childEntity * add changelog entry * resolve review comments --- CHANGELOG.next.asciidoc | 1 + metricbeat/docs/fields.asciidoc | 20 +++++++++ .../vsphere/datastorecluster/_meta/data.json | 6 +++ .../vsphere/datastorecluster/_meta/fields.yml | 10 ++++- .../module/vsphere/datastorecluster/data.go | 22 ++++++---- .../vsphere/datastorecluster/data_test.go | 8 +++- .../datastorecluster/datastorecluster.go | 41 ++++++++++++++++++- metricbeat/module/vsphere/fields.go | 2 +- 8 files changed, 97 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index cfca6ac5034..fdff4e717ca 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -328,6 +328,7 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff] *Metricbeat* +- Add support for new metrics for vSphere module datastorecluster metricset. {pull}40694[40694] *Osquerybeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index 0016c473805..8f3ccce6fff 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -67175,6 +67175,26 @@ format: bytes -- +*`vsphere.datastorecluster.datastore.names`*:: ++ +-- +List of all the Datastore names associated with the Datastore Cluster. + + +type: keyword + +-- + +*`vsphere.datastorecluster.datastore.count`*:: ++ +-- +Number of datastores in the Datastore Cluster. + + +type: long + +-- + [float] === host diff --git a/metricbeat/module/vsphere/datastorecluster/_meta/data.json b/metricbeat/module/vsphere/datastorecluster/_meta/data.json index 833b852c6da..10a4d2f98de 100644 --- a/metricbeat/module/vsphere/datastorecluster/_meta/data.json +++ b/metricbeat/module/vsphere/datastorecluster/_meta/data.json @@ -21,6 +21,12 @@ }, "free_space": { "bytes": 8788836876288 + }, + "datastore": { + "count": 1, + "names": [ + "LocalDS_0" + ] } } } diff --git a/metricbeat/module/vsphere/datastorecluster/_meta/fields.yml b/metricbeat/module/vsphere/datastorecluster/_meta/fields.yml index 8e22bb6259d..50ce1ca9d44 100644 --- a/metricbeat/module/vsphere/datastorecluster/_meta/fields.yml +++ b/metricbeat/module/vsphere/datastorecluster/_meta/fields.yml @@ -17,4 +17,12 @@ type: long description: > Total free space on this storage pod, in bytes. - format: bytes \ No newline at end of file + format: bytes + - name: datastore.names + type: keyword + description: > + List of all the Datastore names associated with the Datastore Cluster. + - name: datastore.count + type: long + description: > + Number of datastores in the Datastore Cluster. \ No newline at end of file diff --git a/metricbeat/module/vsphere/datastorecluster/data.go b/metricbeat/module/vsphere/datastorecluster/data.go index 8abdc5e695d..d7c7903c62c 100644 --- a/metricbeat/module/vsphere/datastorecluster/data.go +++ b/metricbeat/module/vsphere/datastorecluster/data.go @@ -23,12 +23,18 @@ import ( "github.com/elastic/elastic-agent-libs/mapstr" ) -func (m *DatastoreClusterMetricSet) mapEvent(datastoreCluster mo.StoragePod) mapstr.M { - event := mapstr.M{} - - event.Put("name", datastoreCluster.Name) - event.Put("capacity.bytes", datastoreCluster.Summary.Capacity) - event.Put("free_space.bytes", datastoreCluster.Summary.FreeSpace) - - return event +func (m *DatastoreClusterMetricSet) mapEvent(datastoreCluster mo.StoragePod, data *metricData) mapstr.M { + return mapstr.M{ + "name": datastoreCluster.Name, + "capacity": mapstr.M{ + "bytes": datastoreCluster.Summary.Capacity, + }, + "free_space": mapstr.M{ + "bytes": datastoreCluster.Summary.FreeSpace, + }, + "datastore": mapstr.M{ + "names": data.assetNames.outputDsNames, + "count": len(data.assetNames.outputDsNames), + }, + } } diff --git a/metricbeat/module/vsphere/datastorecluster/data_test.go b/metricbeat/module/vsphere/datastorecluster/data_test.go index de181264210..41d1736777e 100644 --- a/metricbeat/module/vsphere/datastorecluster/data_test.go +++ b/metricbeat/module/vsphere/datastorecluster/data_test.go @@ -38,7 +38,7 @@ func TestEventMapping(t *testing.T) { }, } - event := (&DatastoreClusterMetricSet{}).mapEvent(datastoreClusterTest) + event := (&DatastoreClusterMetricSet{}).mapEvent(datastoreClusterTest, &metricData{assetNames: assetNames{outputDsNames: []string{"DCS_0"}}}) name, _ := event.GetValue("name") assert.Equal(t, "Folder1", name) @@ -48,4 +48,10 @@ func TestEventMapping(t *testing.T) { freeSpace, _ := event.GetValue("free_space.bytes") assert.Equal(t, int64(50), freeSpace) + + datastoreNames, _ := event.GetValue("datastore.names") + assert.Equal(t, []string{"DCS_0"}, datastoreNames) + + datastoreCount, _ := event.GetValue("datastore.count") + assert.Equal(t, 1, datastoreCount) } diff --git a/metricbeat/module/vsphere/datastorecluster/datastorecluster.go b/metricbeat/module/vsphere/datastorecluster/datastorecluster.go index 5d20217202a..dd26fa7ba04 100644 --- a/metricbeat/module/vsphere/datastorecluster/datastorecluster.go +++ b/metricbeat/module/vsphere/datastorecluster/datastorecluster.go @@ -20,8 +20,10 @@ package datastorecluster import ( "context" "fmt" + "strings" "github.com/vmware/govmomi" + "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/view" "github.com/vmware/govmomi/vim25/mo" @@ -55,6 +57,14 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { return &DatastoreClusterMetricSet{ms}, nil } +type metricData struct { + assetNames assetNames +} + +type assetNames struct { + outputDsNames []string +} + func (m *DatastoreClusterMetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -84,18 +94,45 @@ func (m *DatastoreClusterMetricSet) Fetch(ctx context.Context, reporter mb.Repor }() var datastoreCluster []mo.StoragePod - err = v.Retrieve(ctx, []string{"StoragePod"}, nil, &datastoreCluster) + err = v.Retrieve(ctx, []string{"StoragePod"}, []string{"name", "summary", "childEntity"}, &datastoreCluster) if err != nil { return fmt.Errorf("error in retrieve from vsphere: %w", err) } + pc := property.DefaultCollector(c) for i := range datastoreCluster { if ctx.Err() != nil { return ctx.Err() } - reporter.Event(mb.Event{MetricSetFields: m.mapEvent(datastoreCluster[i])}) + assetNames, err := getAssetNames(ctx, pc, &datastoreCluster[i]) + if err != nil { + m.Logger().Errorf("Failed to retrieve object from host %s: %w", datastoreCluster[i].Name, err) + } + + reporter.Event(mb.Event{MetricSetFields: m.mapEvent(datastoreCluster[i], &metricData{assetNames: assetNames})}) } return nil } + +func getAssetNames(ctx context.Context, pc *property.Collector, dsc *mo.StoragePod) (assetNames, error) { + var objects []mo.ManagedEntity + if len(dsc.ChildEntity) > 0 { + if err := pc.Retrieve(ctx, dsc.ChildEntity, []string{"name"}, &objects); err != nil { + return assetNames{}, err + } + } + + outputDsNames := make([]string, 0) + for _, ob := range objects { + if ob.Reference().Type == "Datastore" { + name := strings.ReplaceAll(ob.Name, ".", "_") + outputDsNames = append(outputDsNames, name) + } + } + + return assetNames{ + outputDsNames: outputDsNames, + }, nil +} diff --git a/metricbeat/module/vsphere/fields.go b/metricbeat/module/vsphere/fields.go index 05e29ff253c..729c11e6264 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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" }