diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 15541fc6a6f..4dd4e6e613a 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -178,6 +178,40 @@ https://github.com/elastic/beats/compare/v8.8.1\...main[Check the HEAD diff] - Parse more fields from Elasticsearch slowlogs {pull}38295[38295] - added benchmark input {pull}37437[37437] - added benchmark input and discard output {pull}37437[37437] +- Ensure all responses sent by HTTP Endpoint are HTML-escaped. {pull}39329[39329] +- Update CEL mito extensions to v1.11.0 to improve type checking. {pull}39460[39460] +- Improve logging of request and response with request trace logging in error conditions. {pull}39455[39455] +- Implement Elastic Agent status and health reporting for CEL Filebeat input. {pull}39209[39209] +- Add HTTP metrics to CEL input. {issue}39501[39501] {pull}39503[39503] +- Add default user-agent to CEL HTTP requests. {issue}39502[39502] {pull}39587[39587] +- Improve reindexing support in security module pipelines. {issue}38224[38224] {pull}39588[39588] +- Make HTTP Endpoint input GA. {issue}38979[38979] {pull}39410[39410] +- Update CEL mito extensions to v1.12.2. {pull}39755[39755] +- Add support for base64-encoded HMAC headers to HTTP Endpoint. {pull}39655[39655] +- Add user group membership support to Okta entity analytics provider. {issue}39814[39814] {pull}39815[39815] +- Add request trace support for Okta and EntraID entity analytics providers. {pull}39821[39821] +- Fix handling of infinite rate values in CEL rate limit handling logic. {pull}39940[39940] +- Allow elision of set and append failure logging. {issue}34544[34544] {pull}39929[39929] +- Add ability to remove request trace logs from CEL input. {pull}39969[39969] +- Add ability to remove request trace logs from HTTPJSON input. {pull}40003[40003] +- Update CEL mito extensions to v1.13.0. {pull}40035[40035] +- Add Jamf entity analytics provider. {pull}39996[39996] +- Add ability to remove request trace logs from http_endpoint input. {pull}40005[40005] +- Add ability to remove request trace logs from entityanalytics input. {pull}40004[40004] +- Relax constraint on Base DN in entity analytics Active Directory provider. {pull}40054[40054] +- Implement Elastic Agent status and health reporting for Netflow Filebeat input. {pull}40080[40080] +- Enhance input state reporting for CEL evaluations that return a single error object in events. {pull}40083[40083] +- Allow absent credentials when using GCS with Application Default Credentials. {issue}39977[39977] {pull}40072[40072] +- Add SSL and username support for Redis input, now the input includes support for Redis 6.0+. {pull}40111[40111] +- Add scaling up support for Netflow input. {issue}37761[37761] {pull}40122[40122] +- Update CEL mito extensions to v1.15.0. {pull}40294[40294] +- Allow cross-region bucket configuration in s3 input. {issue}22161[22161] {pull}40309[40309] +- Improve logging in Okta Entity Analytics provider. {issue}40106[40106] {pull}40347[40347] +- Document `winlog` input. {issue}40074[40074] {pull}40462[40462] +- Added retry logic to websocket connections in the streaming input. {issue}40271[40271] {pull}40601[40601] +- Add new metricset cluster for the vSphere module. {pull}40536[40536] +- Disable event normalization for netflow input {pull}40635[40635] +- Allow attribute selection in the Active Directory entity analytics provider. {issue}40482[40482] {pull}40662[40662] *Auditbeat* diff --git a/metricbeat/docs/fields.asciidoc b/metricbeat/docs/fields.asciidoc index df93b4a6d8c..585ce62fd77 100644 --- a/metricbeat/docs/fields.asciidoc +++ b/metricbeat/docs/fields.asciidoc @@ -66854,6 +66854,107 @@ vSphere module +[float] +=== cluster + +Cluster information. + + + + +*`vsphere.cluster.datastore.names`*:: ++ +-- +List of all the Datastore names associated with the cluster. + + +type: keyword + +-- + +*`vsphere.cluster.datastore.count`*:: ++ +-- +Number of Datastores associated with the cluster. + + +type: long + +-- + + +*`vsphere.cluster.das_config.admission.control.enabled`*:: ++ +-- +Indicates whether strict admission control is enabled. + + +type: boolean + +-- + +*`vsphere.cluster.das_config.enabled`*:: ++ +-- +Indicates whether vSphere HA feature is enabled. + + +type: boolean + +-- + + +*`vsphere.cluster.host.count`*:: ++ +-- +Number of Hosts associated with the cluster. + + +type: long + +-- + +*`vsphere.cluster.host.names`*:: ++ +-- +List of all the Host names associated with the cluster. + + +type: keyword + +-- + +*`vsphere.cluster.name`*:: ++ +-- +Cluster name. + + +type: keyword + +-- + + +*`vsphere.cluster.network.count`*:: ++ +-- +Number of Networks associated with the cluster. + + +type: long + +-- + +*`vsphere.cluster.network.names`*:: ++ +-- +List of all the Network names associated with the cluster. + + +type: keyword + +-- + [float] === datastore diff --git a/metricbeat/docs/modules/vsphere.asciidoc b/metricbeat/docs/modules/vsphere.asciidoc index daab01568eb..318a735b790 100644 --- a/metricbeat/docs/modules/vsphere.asciidoc +++ b/metricbeat/docs/modules/vsphere.asciidoc @@ -11,7 +11,11 @@ This file is generated! See scripts/mage/docs_collector.go The vSphere module uses the https://github.com/vmware/govmomi[Govmomi] library to collect metrics from any Vmware SDK URL (ESXi/VCenter). This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5. +<<<<<<< HEAD By default it enables the metricsets `datastore`, `host` and `virtualmachine`. +======= +By default it enables the metricsets `cluster`, `network`, `resourcepool`, `datastore`, `host` and `virtualmachine`. +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) [float] === Dashboard @@ -35,8 +39,14 @@ in <>. Here is an example configuration: metricbeat.modules: - module: vsphere enabled: true +<<<<<<< HEAD metricsets: ["datastore", "host", "virtualmachine"] period: 10s +======= + metricsets: ["cluster", "datastore", "host", "virtualmachine", "network", "resourcepool"] + # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. + period: 20s +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) hosts: ["https://localhost/sdk"] username: "user" @@ -52,12 +62,16 @@ metricbeat.modules: The following metricsets are available: +* <> + * <> * <> * <> +include::vsphere/cluster.asciidoc[] + include::vsphere/datastore.asciidoc[] include::vsphere/host.asciidoc[] diff --git a/metricbeat/docs/modules/vsphere/cluster.asciidoc b/metricbeat/docs/modules/vsphere/cluster.asciidoc new file mode 100644 index 00000000000..1666f6c8dfd --- /dev/null +++ b/metricbeat/docs/modules/vsphere/cluster.asciidoc @@ -0,0 +1,29 @@ +//// +This file is generated! See scripts/mage/docs_collector.go +//// +:edit_url: https://github.com/elastic/beats/edit/main/metricbeat/module/vsphere/cluster/_meta/docs.asciidoc + + +[[metricbeat-metricset-vsphere-cluster]] +=== vSphere cluster metricset + +beta[] + +include::../../../module/vsphere/cluster/_meta/docs.asciidoc[] + +This is a default metricset. If the host module is unconfigured, this metricset is enabled by default. + +:edit_url: + +==== Fields + +For a description of each field in the metricset, see the +<> section. + +Here is an example document generated by this metricset: + +[source,json] +---- +include::../../../module/vsphere/cluster/_meta/data.json[] +---- +:edit_url!: \ No newline at end of file diff --git a/metricbeat/docs/modules_list.asciidoc b/metricbeat/docs/modules_list.asciidoc index da0f7525e0f..e38865c3997 100644 --- a/metricbeat/docs/modules_list.asciidoc +++ b/metricbeat/docs/modules_list.asciidoc @@ -311,7 +311,12 @@ This file is generated! See scripts/mage/docs_collector.go |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | .1+| .1+| |<> |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | +<<<<<<< HEAD .3+| .3+| |<> +======= +.6+| .6+| |<> beta[] +|<> +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) |<> |<> |<> |image:./images/icon-yes.png[Prebuilt dashboards are available] | diff --git a/metricbeat/include/list_common.go b/metricbeat/include/list_common.go index 0d061e55e8d..ad856b9cf56 100644 --- a/metricbeat/include/list_common.go +++ b/metricbeat/include/list_common.go @@ -181,6 +181,7 @@ import ( _ "github.com/elastic/beats/v7/metricbeat/module/uwsgi" _ "github.com/elastic/beats/v7/metricbeat/module/uwsgi/status" _ "github.com/elastic/beats/v7/metricbeat/module/vsphere" + _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/cluster" _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/datastore" _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/host" _ "github.com/elastic/beats/v7/metricbeat/module/vsphere/virtualmachine" diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 985e4795910..d41d18bbdbe 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -1007,8 +1007,14 @@ metricbeat.modules: #------------------------------- VSphere Module ------------------------------- - module: vsphere enabled: true +<<<<<<< HEAD metricsets: ["datastore", "host", "virtualmachine"] period: 10s +======= + metricsets: ["cluster", "datastore", "host", "virtualmachine", "network", "resourcepool"] + # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. + period: 20s +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) hosts: ["https://localhost/sdk"] username: "user" diff --git a/metricbeat/module/vsphere/_meta/README.md b/metricbeat/module/vsphere/_meta/README.md index 9ebb2bbd263..d84e34efcb1 100644 --- a/metricbeat/module/vsphere/_meta/README.md +++ b/metricbeat/module/vsphere/_meta/README.md @@ -28,6 +28,7 @@ Now setup your metricbeat config to connect to Govcsim: ``` - module: vsphere metricsets: + - cluster - datastore - host - virtualmachine diff --git a/metricbeat/module/vsphere/_meta/config.reference.yml b/metricbeat/module/vsphere/_meta/config.reference.yml index d4803d0c775..475cfbeb6ea 100644 --- a/metricbeat/module/vsphere/_meta/config.reference.yml +++ b/metricbeat/module/vsphere/_meta/config.reference.yml @@ -1,7 +1,13 @@ - module: vsphere enabled: true +<<<<<<< HEAD metricsets: ["datastore", "host", "virtualmachine"] period: 10s +======= + metricsets: ["cluster", "datastore", "host", "virtualmachine", "network", "resourcepool"] + # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. + period: 20s +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) hosts: ["https://localhost/sdk"] username: "user" diff --git a/metricbeat/module/vsphere/_meta/config.yml b/metricbeat/module/vsphere/_meta/config.yml index 6862012209b..69d5a0a8b6a 100644 --- a/metricbeat/module/vsphere/_meta/config.yml +++ b/metricbeat/module/vsphere/_meta/config.yml @@ -1,5 +1,6 @@ - module: vsphere #metricsets: + # - cluster # - datastore # - host # - virtualmachine diff --git a/metricbeat/module/vsphere/_meta/docs.asciidoc b/metricbeat/module/vsphere/_meta/docs.asciidoc index c936565acb4..d7806af948f 100644 --- a/metricbeat/module/vsphere/_meta/docs.asciidoc +++ b/metricbeat/module/vsphere/_meta/docs.asciidoc @@ -1,6 +1,10 @@ The vSphere module uses the https://github.com/vmware/govmomi[Govmomi] library to collect metrics from any Vmware SDK URL (ESXi/VCenter). This library is built for and tested against ESXi and vCenter 5.5, 6.0 and 6.5. +<<<<<<< HEAD By default it enables the metricsets `datastore`, `host` and `virtualmachine`. +======= +By default it enables the metricsets `cluster`, `network`, `resourcepool`, `datastore`, `host` and `virtualmachine`. +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) [float] === Dashboard diff --git a/metricbeat/module/vsphere/cluster/_meta/data.json b/metricbeat/module/vsphere/cluster/_meta/data.json new file mode 100644 index 00000000000..6e165063e85 --- /dev/null +++ b/metricbeat/module/vsphere/cluster/_meta/data.json @@ -0,0 +1,47 @@ +{ + "@timestamp": "2017-10-12T08:05:34.853Z", + "event": { + "dataset": "vsphere.cluster", + "duration": 115000, + "module": "vsphere" + }, + "metricset": { + "name": "cluster", + "period": 10000 + }, + "service": { + "address": "127.0.0.1:33365", + "type": "vsphere" + }, + "vsphere": { + "cluster": { + "name": "Cluster_1", + "das_config": { + "enabled": false, + "admission": { + "control": { + "enabled": true + } + } + }, + "host": { + "count": 1, + "names": [ + "Host_1" + ] + }, + "datastore": { + "count": 1, + "names": [ + "Datastore_1" + ] + }, + "network": { + "count": 1, + "names": [ + "Network_1" + ] + } + } + } +} \ No newline at end of file diff --git a/metricbeat/module/vsphere/cluster/_meta/docs.asciidoc b/metricbeat/module/vsphere/cluster/_meta/docs.asciidoc new file mode 100644 index 00000000000..e82fdcdccc6 --- /dev/null +++ b/metricbeat/module/vsphere/cluster/_meta/docs.asciidoc @@ -0,0 +1 @@ +This is the `cluster` metricset of the vSphere module. diff --git a/metricbeat/module/vsphere/cluster/_meta/fields.yml b/metricbeat/module/vsphere/cluster/_meta/fields.yml new file mode 100644 index 00000000000..7afce736285 --- /dev/null +++ b/metricbeat/module/vsphere/cluster/_meta/fields.yml @@ -0,0 +1,54 @@ +- name: cluster + type: group + release: beta + description: > + Cluster information. + fields: + - name: datastore + type: group + fields: + - name: names + type: keyword + description: > + List of all the Datastore names associated with the cluster. + - name: count + type: long + description: > + Number of Datastores associated with the cluster. + - name: das_config + type: group + fields: + - name: admission.control.enabled + type: boolean + description: > + Indicates whether strict admission control is enabled. + - name: enabled + type: boolean + description: > + Indicates whether vSphere HA feature is enabled. + - name: host + type: group + fields: + - name: count + type: long + description: > + Number of Hosts associated with the cluster. + - name: names + type: keyword + description: > + List of all the Host names associated with the cluster. + - name: name + type: keyword + description: > + Cluster name. + - name: network + type: group + fields: + - name: count + type: long + description: > + Number of Networks associated with the cluster. + - name: names + type: keyword + description: > + List of all the Network names associated with the cluster. \ No newline at end of file diff --git a/metricbeat/module/vsphere/cluster/cluster.go b/metricbeat/module/vsphere/cluster/cluster.go new file mode 100644 index 00000000000..10184c55c90 --- /dev/null +++ b/metricbeat/module/vsphere/cluster/cluster.go @@ -0,0 +1,174 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package cluster + +import ( + "context" + "fmt" + "strings" + + "github.com/elastic/beats/v7/metricbeat/mb" + "github.com/elastic/beats/v7/metricbeat/module/vsphere" + + "github.com/vmware/govmomi" + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/view" + "github.com/vmware/govmomi/vim25/mo" +) + +// init registers the MetricSet with the central registry as soon as the program +// starts. The New function will be called later to instantiate an instance of +// the MetricSet for each network is defined in the module's configuration. After the +// MetricSet has been created then Fetch will begin to be called periodically. +func init() { + mb.Registry.MustAddMetricSet("vsphere", "cluster", New, + mb.WithHostParser(vsphere.HostParser), + mb.DefaultMetricSet(), + ) +} + +// MetricSet type defines all fields of the MetricSet. +type ClusterMetricSet struct { + *vsphere.MetricSet +} + +type assetNames struct { + outputNetworkNames []string + outputDatastoreNames []string + outputHostNames []string +} + +// New creates a new instance of the MetricSet. +func New(base mb.BaseMetricSet) (mb.MetricSet, error) { + ms, err := vsphere.NewMetricSet(base) + if err != nil { + return nil, err + } + return &ClusterMetricSet{ms}, nil +} + +// Fetch methods implements the data gathering and data conversion to the right +// format. It publishes the event which is then forwarded to the output. In case +// of an error set the Error field of mb.Event or simply call report.Error(). +func (m *ClusterMetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + client, err := govmomi.NewClient(ctx, m.HostURL, m.Insecure) + if err != nil { + return fmt.Errorf("error in NewClient: %w", err) + } + defer func() { + if err := client.Logout(ctx); err != nil { + m.Logger().Debug(fmt.Errorf("error trying to logout from vSphere: %w", err)) + } + }() + + c := client.Client + + // Create a view of Cluster objects + mgr := view.NewManager(c) + + v, err := mgr.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"ClusterComputeResource"}, true) + if err != nil { + return fmt.Errorf("error in CreateContainerView: %w", err) + } + + defer func() { + if err := v.Destroy(ctx); err != nil { + m.Logger().Errorf("error trying to destroy view from vSphere: %w", err) + } + }() + + // Retrieve summary property for all Clusters + var clt []mo.ClusterComputeResource + err = v.Retrieve(ctx, []string{"ClusterComputeResource"}, []string{"name", "host", "network", "datastore", "configuration"}, &clt) + if err != nil { + return fmt.Errorf("error in Retrieve: %w", err) + } + + pc := property.DefaultCollector(c) + for i := range clt { + select { + case <-ctx.Done(): + return ctx.Err() + default: + assetNames, err := getAssetNames(ctx, pc, &clt[i]) + if err != nil { + m.Logger().Errorf("Failed to retrieve object from cluster %s: %v", clt[i].Name, err) + } + + if clt[i].Configuration.DasConfig.AdmissionControlEnabled == nil { + m.Logger().Warn("Metric das_config.admission.control.enabled not found") + } + if clt[i].Configuration.DasConfig.Enabled == nil { + m.Logger().Warn("Metric das_config.enabled not found") + } + + reporter.Event(mb.Event{ + MetricSetFields: m.mapEvent(clt[i], assetNames), + }) + } + } + return nil + +} + +func getAssetNames(ctx context.Context, pc *property.Collector, cl *mo.ClusterComputeResource) (*assetNames, error) { + referenceList := append(cl.Datastore, cl.Host...) + + outputDatastoreNames := make([]string, 0, len(cl.Datastore)) + outputHostNames := make([]string, 0, len(cl.Host)) + if len(referenceList) > 0 { + var objects []mo.ManagedEntity + if err := pc.Retrieve(ctx, referenceList, []string{"name"}, &objects); err != nil { + return nil, fmt.Errorf("failed to retrieve managed entities: %w", err) + } + + for _, ob := range objects { + name := strings.ReplaceAll(ob.Name, ".", "_") + switch ob.Reference().Type { + case "Datastore": + outputDatastoreNames = append(outputDatastoreNames, name) + case "HostSystem": + outputHostNames = append(outputHostNames, name) + } + } + } + + // calling network explicitly because of mo.Network's ManagedEntityObject.Name does not store Network name + // instead mo.Network.Name contains correct value of Network name + outputNetworkNames := make([]string, 0, len(cl.Network)) + if len(cl.Network) > 0 { + var netObjects []mo.Network + if err := pc.Retrieve(ctx, cl.Network, []string{"name"}, &netObjects); err != nil { + return nil, fmt.Errorf("failed to retrieve network objects: %w", err) + } + + for _, ob := range netObjects { + name := strings.ReplaceAll(ob.Name, ".", "_") + outputNetworkNames = append(outputNetworkNames, name) + } + } + + return &assetNames{ + outputNetworkNames: outputNetworkNames, + outputDatastoreNames: outputDatastoreNames, + outputHostNames: outputHostNames, + }, nil +} diff --git a/metricbeat/module/vsphere/cluster/cluster_test.go b/metricbeat/module/vsphere/cluster/cluster_test.go new file mode 100644 index 00000000000..37e286c113d --- /dev/null +++ b/metricbeat/module/vsphere/cluster/cluster_test.go @@ -0,0 +1,97 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package cluster + +import ( + "testing" + + mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/vmware/govmomi/simulator" +) + +func TestFetchEventContents(t *testing.T) { + // Creating a new simulator model with VPX server to collect broad range of data. + model := simulator.VPX() + err := model.Create() + require.NoError(t, err, "failed to create model") + t.Cleanup(func() { model.Remove() }) + + ts := model.Service.NewServer() + t.Cleanup(func() { ts.Close() }) + + f := mbtest.NewReportingMetricSetV2WithContext(t, getConfig(ts)) + + events, errs := mbtest.ReportingFetchV2WithContext(f) + require.Empty(t, errs, "expected no error") + + require.NotEmpty(t, events, "didn't get any event, should have gotten at least X") + + event := events[0].MetricSetFields + + t.Logf("Fetched event from %s/%s event: %+v", f.Module().Name(), f.Name(), event) + + testEvent := mapstr.M{ + "name": "DC0_C0", + "host": mapstr.M{ + "count": 3, + "names": []string{"DC0_C0_H0", "DC0_C0_H1", "DC0_C0_H2"}, + }, + "datastore": mapstr.M{ + "count": 1, + "names": []string{"LocalDS_0"}, + }, + "network": mapstr.M{ + "count": 3, + "names": []string{"VM Network", "DVS0-DVUplinks-9", "DC0_DVPG0"}, + }, + } + + assert.Exactly(t, event, testEvent) +} + +func TestClusterMetricSetData(t *testing.T) { + model := simulator.VPX() + err := model.Create() + require.NoError(t, err, "failed to create model") + t.Cleanup(func() { model.Remove() }) + + ts := model.Service.NewServer() + t.Cleanup(func() { ts.Close() }) + + f := mbtest.NewReportingMetricSetV2WithContext(t, getConfig(ts)) + + err = mbtest.WriteEventsReporterV2WithContext(f, t, "") + assert.NoError(t, err, "failed to write events with reporter") +} + +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{"cluster"}, + "hosts": []string{urlSimulator}, + "username": "user", + "password": "pass", + "insecure": true, + } +} diff --git a/metricbeat/module/vsphere/cluster/data.go b/metricbeat/module/vsphere/cluster/data.go new file mode 100644 index 00000000000..37c2ac5c319 --- /dev/null +++ b/metricbeat/module/vsphere/cluster/data.go @@ -0,0 +1,52 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package cluster + +import ( + "github.com/vmware/govmomi/vim25/mo" + + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func (m *ClusterMetricSet) mapEvent(cl mo.ClusterComputeResource, data *assetNames) mapstr.M { + event := mapstr.M{ + "host": mapstr.M{ + "count": len(data.outputHostNames), + "names": data.outputHostNames, + }, + "datastore": mapstr.M{ + "count": len(data.outputDatastoreNames), + "names": data.outputDatastoreNames, + }, + "network": mapstr.M{ + "count": len(data.outputNetworkNames), + "names": data.outputNetworkNames, + }, + "name": cl.Name, + } + + if cl.Configuration.DasConfig.Enabled != nil { + event.Put("das_config.enabled", *cl.Configuration.DasConfig.Enabled) + } + + if cl.Configuration.DasConfig.AdmissionControlEnabled != nil { + event.Put("das_config.admission.control.enabled", *cl.Configuration.DasConfig.AdmissionControlEnabled) + } + + return event +} diff --git a/metricbeat/module/vsphere/cluster/data_test.go b/metricbeat/module/vsphere/cluster/data_test.go new file mode 100644 index 00000000000..097b7254283 --- /dev/null +++ b/metricbeat/module/vsphere/cluster/data_test.go @@ -0,0 +1,79 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package cluster + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" + + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func TestEventMapping(t *testing.T) { + var m *ClusterMetricSet + var ClusterTest = mo.ClusterComputeResource{ + ComputeResource: mo.ComputeResource{ + ManagedEntity: mo.ManagedEntity{ + Name: "Cluster_0", + }, + }, + Configuration: types.ClusterConfigInfo{ + DasConfig: types.ClusterDasConfigInfo{ + Enabled: types.NewBool(false), + AdmissionControlEnabled: types.NewBool(true), + }, + }, + } + + var assetNames = assetNames{ + outputHostNames: []string{"Host_0"}, + outputDatastoreNames: []string{"Datastore_0"}, + outputNetworkNames: []string{"Network_0"}, + } + + outputEvent := m.mapEvent(ClusterTest, &assetNames) + testEvent := mapstr.M{ + "das_config": mapstr.M{ + "enabled": false, + "admission": mapstr.M{ + "control": mapstr.M{ + "enabled": true, + }, + }, + }, + "name": "Cluster_0", + "host": mapstr.M{ + "count": 1, + "names": []string{"Host_0"}, + }, + "datastore": mapstr.M{ + "count": 1, + "names": []string{"Datastore_0"}, + }, + "network": mapstr.M{ + "count": 1, + "names": []string{"Network_0"}, + }, + } + + assert.Exactly(t, outputEvent, testEvent) + +} diff --git a/metricbeat/module/vsphere/datastore/_meta/data.json b/metricbeat/module/vsphere/datastore/_meta/data.json index 944ecb1189f..35cda176a50 100644 --- a/metricbeat/module/vsphere/datastore/_meta/data.json +++ b/metricbeat/module/vsphere/datastore/_meta/data.json @@ -1,4 +1,5 @@ { +<<<<<<< HEAD "@timestamp": "2017-10-12T08:05:34.853Z", "event": { "dataset": "vsphere.datastore", @@ -31,4 +32,68 @@ "name": "LocalDS_0" } } +======= + "@timestamp": "2017-10-12T08:05:34.853Z", + "event": { + "dataset": "vsphere.datastore", + "duration": 115000, + "module": "vsphere" + }, + "metricset": { + "name": "datastore", + "period": 10000 + }, + "service": { + "address": "127.0.0.1:33365", + "type": "vsphere" + }, + "vsphere": { + "datastore": { + "iops": 0, + "host": { + "count": 1, + "names": [ + "DC3_H0" + ] + }, + "status": "green", + "vm": { + "count": 6, + "names": [ + "DC3_H0_VM0" + ] + }, + "read": { + "bytes": 0, + "latency": { + "total": { + "ms": 0 + } + } + }, + "write": { + "bytes": 337000, + "latency": { + "total": { + "ms": 0 + } + } + }, + "capacity": { + "free": { + "bytes": 37120094208 + }, + "total": { + "bytes": 74686664704 + }, + "used": { + "bytes": 37566570496, + "pct": 0.502988996026061 + } + }, + "fstype": "local", + "name": "LocalDS_0" + } + } +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) } \ No newline at end of file diff --git a/metricbeat/module/vsphere/datastore/data.go b/metricbeat/module/vsphere/datastore/data.go new file mode 100644 index 00000000000..0b438f96268 --- /dev/null +++ b/metricbeat/module/vsphere/datastore/data.go @@ -0,0 +1,80 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package datastore + +import ( + "github.com/vmware/govmomi/vim25/mo" + + "github.com/elastic/elastic-agent-libs/mapstr" +) + +func (m *DataStoreMetricSet) mapEvent(ds mo.Datastore, data *metricData) mapstr.M { + event := mapstr.M{ + "name": ds.Summary.Name, + "fstype": ds.Summary.Type, + "status": ds.OverallStatus, + "host": mapstr.M{ + "count": len(data.assetNames.outputHostNames), + "names": data.assetNames.outputHostNames, + }, + "vm": mapstr.M{ + "count": len(data.assetNames.outputVmNames), + "names": data.assetNames.outputVmNames, + }, + "capacity": mapstr.M{ + "total": mapstr.M{ + "bytes": ds.Summary.Capacity, + }, + "free": mapstr.M{ + "bytes": ds.Summary.FreeSpace, + }, + "used": mapstr.M{ + "bytes": ds.Summary.Capacity - ds.Summary.FreeSpace, + }, + }, + } + + if ds.Summary.Capacity > 0 { + usedSpacePercent := float64(ds.Summary.Capacity-ds.Summary.FreeSpace) / float64(ds.Summary.Capacity) + event.Put("capacity.used.pct", usedSpacePercent) + } + + mapPerfMetricToEvent(event, data.perfMetrics) + + return event +} + +func mapPerfMetricToEvent(event mapstr.M, perfMetricMap map[string]interface{}) { + const bytesMultiplier int64 = 1024 + + 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["datastore.datastoreIops.average"]; exist { + event.Put("iops", val) + } +} diff --git a/metricbeat/module/vsphere/datastore/data_test.go b/metricbeat/module/vsphere/datastore/data_test.go new file mode 100644 index 00000000000..4ecc091794c --- /dev/null +++ b/metricbeat/module/vsphere/datastore/data_test.go @@ -0,0 +1,108 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package datastore + +import ( + "testing" + + "github.com/elastic/elastic-agent-libs/mapstr" + + "github.com/stretchr/testify/assert" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" +) + +func TestEventMapping(t *testing.T) { + var m *DataStoreMetricSet + var datastoreTest = mo.Datastore{ + Summary: types.DatastoreSummary{ + Name: "datastore-test", + Type: "local", + Capacity: 5000000, + FreeSpace: 5000000, + }, + ManagedEntity: mo.ManagedEntity{ + OverallStatus: "green", + }, + Host: []types.DatastoreHostMount{}, + Vm: []types.ManagedObjectReference{ + {Type: "VirtualMachine", Value: "vm-test"}, + }, + } + + 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), + }, + assetNames: assetNames{ + outputHostNames: []string{"DC3_H0"}, + outputVmNames: []string{"DC3_H0_VM0"}, + }, + } + + outputEvent := m.mapEvent(datastoreTest, &metricDataTest) + testEvent := mapstr.M{ + "fstype": "local", + "status": types.ManagedEntityStatus("green"), + "iops": int64(10), + "name": "datastore-test", + "host": mapstr.M{ + "count": 1, + "names": []string{"DC3_H0"}, + }, + "vm": mapstr.M{ + "count": 1, + "names": []string{"DC3_H0_VM0"}, + }, + "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), + }, + }, + }, + "capacity": mapstr.M{ + "free": mapstr.M{ + "bytes": int64(5000000), + }, + "total": mapstr.M{ + "bytes": int64(5000000), + }, + "used": mapstr.M{ + "bytes": int64(0), + "pct": float64(0), + }, + }, + } + + assert.Exactly(t, outputEvent, testEvent) + +} diff --git a/metricbeat/module/vsphere/datastore/datastore.go b/metricbeat/module/vsphere/datastore/datastore.go index 4ec84b4b74e..f38fb68a7ca 100644 --- a/metricbeat/module/vsphere/datastore/datastore.go +++ b/metricbeat/module/vsphere/datastore/datastore.go @@ -38,7 +38,7 @@ func init() { } // MetricSet type defines all fields of the MetricSet. -type MetricSet struct { +type DataStoreMetricSet struct { *vsphere.MetricSet } @@ -48,13 +48,35 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { if err != nil { return nil, err } - return &MetricSet{ms}, nil + return &DataStoreMetricSet{ms}, nil } +<<<<<<< HEAD +======= +type metricData struct { + perfMetrics map[string]interface{} + assetNames assetNames +} + +type assetNames struct { + outputVmNames []string + outputHostNames []string +} + +// 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": {}, +} + +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) // Fetch methods implements the data gathering and data conversion to the right // format. It publishes the event which is then forwarded to the output. In case // of an error set the Error field of mb.Event or simply call report.Error(). -func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { +func (m *DataStoreMetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -91,6 +113,7 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { return fmt.Errorf("error in Retrieve: %w", err) } +<<<<<<< HEAD for _, ds := range dst { var usedSpacePercent float64 if ds.Summary.Capacity > 0 { @@ -113,6 +136,79 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { "pct": usedSpacePercent, }, }, +======= + // Create a performance manager + perfManager := performance.NewManager(c) + + // Retrieve all available metrics + metrics, err := perfManager.CounterInfoByName(ctx) + if err != nil { + 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 dst { + select { + case <-ctx.Done(): + return ctx.Err() + default: + assetNames, err := getAssetNames(ctx, pc, &dst[i]) + if err != nil { + m.Logger().Errorf("Failed to retrieve object from host %s: %w", dst[i].Name, err) + continue + } + + spec := types.PerfQuerySpec{ + Entity: dst[i].Reference(), + MetricId: metricIds, + MaxSample: 1, + IntervalId: 20, // right now we are only grabbing real time metrics from the performance manager + } + + // Query performance data + samples, err := perfManager.Query(ctx, []types.PerfQuerySpec{spec}) + if err != nil { + m.Logger().Debugf("Failed to query performance data for host %s: %v", dst[i].Name, err) + continue + } + + if len(samples) == 0 { + m.Logger().Debugf("No samples returned from performance manager") + continue + } + + results, err := perfManager.ToMetricSeries(ctx, samples) + if err != nil { + m.Logger().Debugf("Failed to query performance data to metric series for host %s: %v", dst[i].Name, err) + continue + } + + metricMap := make(map[string]interface{}) + for _, result := range results[0].Value { + if len(result.Value) > 0 { + metricMap[result.Name] = result.Value[0] + continue + } + m.Logger().Debugf("For host %s,Metric %v: No result found", dst[i].Name, result.Name) + } + + reporter.Event(mb.Event{ + MetricSetFields: m.mapEvent(dst[i], &metricData{ + perfMetrics: metricMap, + assetNames: *assetNames, + }), + }) +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) } reporter.Event(mb.Event{ @@ -122,3 +218,52 @@ func (m *MetricSet) Fetch(ctx context.Context, reporter mb.ReporterV2) error { return nil } +<<<<<<< HEAD +======= + +func getAssetNames(ctx context.Context, pc *property.Collector, ds *mo.Datastore) (*assetNames, error) { + + outputVmNames := make([]string, 0, len(ds.Vm)) + if len(ds.Vm) > 0 { + var objects []mo.ManagedEntity + if err := pc.Retrieve(ctx, ds.Vm, []string{"name"}, &objects); err != nil { + return nil, err + } + for _, ob := range objects { + if ob.Reference().Type == "VirtualMachine" { + name := strings.ReplaceAll(ob.Name, ".", "_") + outputVmNames = append(outputVmNames, name) + } + } + } + // 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 { + hsRefs := make([]types.ManagedObjectReference, 0, len(ds.Host)) + for _, obj := range ds.Host { + if obj.Key.Type == "HostSystem" { + hsRefs = append(hsRefs, obj.Key) + } + } + + // Retrieve Host names + var hosts []mo.HostSystem + if len(hsRefs) > 0 { + err := pc.Retrieve(ctx, hsRefs, []string{"name"}, &hosts) + if err != nil { + return nil, err + } + } + + for _, host := range hosts { + name := strings.ReplaceAll(host.Name, ".", "_") + outputHostNames = append(outputHostNames, name) + } + } + + return &assetNames{ + outputHostNames: outputHostNames, + outputVmNames: outputVmNames, + }, nil +} +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) diff --git a/metricbeat/module/vsphere/datastore/datastore_test.go b/metricbeat/module/vsphere/datastore/datastore_test.go index 88f5b772b5a..58e361ebf30 100644 --- a/metricbeat/module/vsphere/datastore/datastore_test.go +++ b/metricbeat/module/vsphere/datastore/datastore_test.go @@ -23,29 +23,44 @@ import ( mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/vmware/govmomi/simulator" ) func TestFetchEventContents(t *testing.T) { +<<<<<<< HEAD model := simulator.ESX() if err := model.Create(); err != nil { t.Fatal(err) } +======= + // Creating a new simulator model with VPX server to collect broad range of data. + model := simulator.VPX() + err := model.Create() + require.NoError(t, err, "failed to create model") + t.Cleanup(func() { model.Remove() }) +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) ts := model.Service.NewServer() - defer ts.Close() + t.Cleanup(func() { 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) } +<<<<<<< HEAD assert.NotEmpty(t, events) +======= + require.Empty(t, errs, "expected no error") + + require.NotEmpty(t, events, "didn't get any event, should have gotten at least X") +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) event := events[0].MetricSetFields - t.Logf("%s/%s event: %+v", f.Module().Name(), f.Name(), event.StringToPrint()) + t.Logf("Fetched event from %s/%s event: %+v", f.Module().Name(), f.Name(), event) assert.EqualValues(t, "LocalDS_0", event["name"]) assert.EqualValues(t, "local", event["fstype"]) @@ -63,6 +78,7 @@ func TestFetchEventContents(t *testing.T) { } } +<<<<<<< HEAD func isNonNegativeInt64(t testing.TB, field string, v interface{}) { i, ok := v.(int64) if !ok { @@ -77,19 +93,21 @@ func isNonNegativeInt64(t testing.TB, field string, v interface{}) { } func TestData(t *testing.T) { +======= +func TestDataStoreMetricSetData(t *testing.T) { +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) model := simulator.ESX() - if err := model.Create(); err != nil { - t.Fatal(err) - } + err := model.Create() + require.NoError(t, err, "failed to create model") + t.Cleanup(func() { model.Remove() }) ts := model.Service.NewServer() - defer ts.Close() + t.Cleanup(func() { ts.Close() }) f := mbtest.NewReportingMetricSetV2WithContext(t, getConfig(ts)) - if err := mbtest.WriteEventsReporterV2WithContext(f, t, ""); err != nil { - t.Fatal("write", err) - } + err = mbtest.WriteEventsReporterV2WithContext(f, t, "") + assert.NoError(t, err, "failed to write events with reporter") } func getConfig(ts *simulator.Server) map[string]interface{} { diff --git a/metricbeat/module/vsphere/fields.go b/metricbeat/module/vsphere/fields.go index fae0b2cc264..4e01e20f47d 100644 --- a/metricbeat/module/vsphere/fields.go +++ b/metricbeat/module/vsphere/fields.go @@ -32,5 +32,9 @@ func init() { // AssetVsphere returns asset data. // This is the base64 encoded zlib format compressed contents of module/vsphere. func AssetVsphere() string { +<<<<<<< HEAD return "eJzsl8+OmzAQxu95itHedx+AQ6Vqq20vaSttt9fIgSG4MQyyh6zo01e2IeKP002KaS/1ASnYfN8PzHxD7uGIbQInUxeocQPAkhUmcHd6dmfuNgAZmlTLmiVVCbzbAAB0s1BS1ih7mUaFwmACB7EByCWqzCRu6T1UosShhR3c1naxpqbuzgRcxkJDsUywMExnubDkRdluKiAyvo9+TDGGKPY4muhJjti+ks4mc7/hseNDzzTX7Q1zY/XjWT5JhaY1jCXMhHvPVNQildw+MLFQD/uW0QQJFFWH2+y/WUVwikA5cIHBjbEjJ10KTmBuP+PMNWJUzCeNGJ2yMZhFpXwxmK1DWaccZDSpUJjtckViuuAa1hp1ihVfS9stP8/OgqEgw0syYXL9v46DT2T4chKkdeM3pyx+xnyBHr++gKxgO1Ed2vociOfrU+AKY1fY8XxdWb9hW2JJeq1i3Tpxax+SfrtKO7i1cjkS3jpxvBSuQn4lfdzZX2GwPyraz14WxrLn7yCpuRGqFGkhq0XfLxeVbk8tG3sPcnqfS4NrIjgys4eVsrJvJpMsXyujv/ttgK3fh8txTRHfsanplxq1YFkd4Nl/yv1vGus1jfcnIZXYq5s6x6FBw6v1D8rhozVYnNSO1VXoiqg+HaK0vPiPddT4oj1X9wrGhx32weWsaWOYyp3vFEFC2v/A2T8Bf3K3IM4enTEEjP9qr/4VAAD//9YITTs=" +======= + return "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" +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) } diff --git a/metricbeat/modules.d/vsphere.yml.disabled b/metricbeat/modules.d/vsphere.yml.disabled index ede326e4ec2..ade15e77dcf 100644 --- a/metricbeat/modules.d/vsphere.yml.disabled +++ b/metricbeat/modules.d/vsphere.yml.disabled @@ -3,6 +3,7 @@ - module: vsphere #metricsets: + # - cluster # - datastore # - host # - virtualmachine diff --git a/x-pack/metricbeat/metricbeat.reference.yml b/x-pack/metricbeat/metricbeat.reference.yml index 1d2957306db..c547cd9258d 100644 --- a/x-pack/metricbeat/metricbeat.reference.yml +++ b/x-pack/metricbeat/metricbeat.reference.yml @@ -1568,8 +1568,14 @@ metricbeat.modules: #------------------------------- VSphere Module ------------------------------- - module: vsphere enabled: true +<<<<<<< HEAD metricsets: ["datastore", "host", "virtualmachine"] period: 10s +======= + metricsets: ["cluster", "datastore", "host", "virtualmachine", "network", "resourcepool"] + # Real-time data collection – An ESXi Server collects data for each performance counter every 20 seconds. + period: 20s +>>>>>>> 1058457a28 ([vSphere] Add new Cluster metricset (#40536)) hosts: ["https://localhost/sdk"] username: "user"