From 40616b642015a9c1bdb893b0a3b5eb93ed34cc2a Mon Sep 17 00:00:00 2001 From: Jaime Soriano Pastor Date: Mon, 17 Dec 2018 12:14:33 +0100 Subject: [PATCH] Add setting to disable cgroup metrics per core --- CHANGELOG.asciidoc | 2 +- .../module/system/process/_meta/docs.asciidoc | 4 ++++ metricbeat/module/system/process/cgroup.go | 24 +++++++++++-------- metricbeat/module/system/process/config.go | 2 ++ metricbeat/module/system/process/process.go | 9 +++---- metricbeat/tests/system/test_system.py | 7 +++--- 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index d8314a9b938..8804b3f9c87 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -111,7 +111,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha1...master[Check the HEAD d *Metricbeat* -- Add setting to disable docker cpu metrics per core. {pull}9194[9194] +- Add settings to disable docker and cgroup cpu metrics per core. {issue}9187[9187] {pull}9194[9194] {pull}9589[9589] - The `elasticsearch/node` metricset now reports the Elasticsearch cluster UUID. {pull}8771[8771] - Add service.type field to Metricbeat. {pull}8965[8965] - Support GET requests in Jolokia module. {issue}8566[8566] {pull}9226[9226] diff --git a/metricbeat/module/system/process/_meta/docs.asciidoc b/metricbeat/module/system/process/_meta/docs.asciidoc index 403aa246b7a..a7f05890377 100644 --- a/metricbeat/module/system/process/_meta/docs.asciidoc +++ b/metricbeat/module/system/process/_meta/docs.asciidoc @@ -77,6 +77,10 @@ metricbeat.modules: process.include_cpu_ticks: true ---- +*`process.include_per_cpu`*:: By default metrics per cpu are reported when +available. Setting this option to false will disable the reporting of these +metrics. + *`process.include_top_n`*:: These options allow you to filter out all processes that are not in the top N by CPU or memory, in order to reduce the number of documents created. If both the `by_cpu` and `by_memory` options are used, the diff --git a/metricbeat/module/system/process/cgroup.go b/metricbeat/module/system/process/cgroup.go index 464dbb501d0..bd46e1addea 100644 --- a/metricbeat/module/system/process/cgroup.go +++ b/metricbeat/module/system/process/cgroup.go @@ -26,7 +26,7 @@ import ( // cgroupStatsToMap returns a MapStr containing the data from the stats object. // If stats is nil then nil is returned. -func cgroupStatsToMap(stats *cgroup.Stats) common.MapStr { +func cgroupStatsToMap(stats *cgroup.Stats, perCPU bool) common.MapStr { if stats == nil { return nil } @@ -44,7 +44,7 @@ func cgroupStatsToMap(stats *cgroup.Stats) common.MapStr { if cpu := cgroupCPUToMapStr(stats.CPU); cpu != nil { cgroup["cpu"] = cpu } - if cpuacct := cgroupCPUAccountingToMapStr(stats.CPUAccounting); cpuacct != nil { + if cpuacct := cgroupCPUAccountingToMapStr(stats.CPUAccounting, perCPU); cpuacct != nil { cgroup["cpuacct"] = cpuacct } if memory := cgroupMemoryToMapStr(stats.Memory); memory != nil { @@ -97,23 +97,17 @@ func cgroupCPUToMapStr(cpu *cgroup.CPUSubsystem) common.MapStr { // cgroupCPUAccountingToMapStr returns a MapStr containing // CPUAccountingSubsystem data. If the cpuacct parameter is nil then nil is // returned. -func cgroupCPUAccountingToMapStr(cpuacct *cgroup.CPUAccountingSubsystem) common.MapStr { +func cgroupCPUAccountingToMapStr(cpuacct *cgroup.CPUAccountingSubsystem, perCPU bool) common.MapStr { if cpuacct == nil { return nil } - perCPUUsage := common.MapStr{} - for i, usage := range cpuacct.UsagePerCPU { - perCPUUsage[strconv.Itoa(i+1)] = usage - } - - return common.MapStr{ + event := common.MapStr{ "id": cpuacct.ID, "path": cpuacct.Path, "total": common.MapStr{ "ns": cpuacct.TotalNanos, }, - "percpu": perCPUUsage, "stats": common.MapStr{ "system": common.MapStr{ "ns": cpuacct.Stats.SystemNanos, @@ -123,6 +117,16 @@ func cgroupCPUAccountingToMapStr(cpuacct *cgroup.CPUAccountingSubsystem) common. }, }, } + + if perCPU { + perCPUUsage := common.MapStr{} + for i, usage := range cpuacct.UsagePerCPU { + perCPUUsage[strconv.Itoa(i+1)] = usage + } + event["percpu"] = perCPUUsage + } + + return event } // cgroupMemoryToMapStr returns a MapStr containing MemorySubsystem data. If the diff --git a/metricbeat/module/system/process/config.go b/metricbeat/module/system/process/config.go index 6a85fd1ad26..4b46e9adc91 100644 --- a/metricbeat/module/system/process/config.go +++ b/metricbeat/module/system/process/config.go @@ -29,6 +29,7 @@ type Config struct { CacheCmdLine bool `config:"process.cmdline.cache.enabled"` IncludeTop process.IncludeTopConfig `config:"process.include_top_n"` IncludeCPUTicks bool `config:"process.include_cpu_ticks"` + IncludePerCPU bool `config:"process.include_per_cpu"` CPUTicks *bool `config:"cpu_ticks"` // Deprecated } @@ -47,4 +48,5 @@ var defaultConfig = Config{ ByCPU: 0, ByMemory: 0, }, + IncludePerCPU: true, } diff --git a/metricbeat/module/system/process/process.go b/metricbeat/module/system/process/process.go index 00b9c1ac715..b96a360b547 100644 --- a/metricbeat/module/system/process/process.go +++ b/metricbeat/module/system/process/process.go @@ -46,9 +46,9 @@ func init() { // MetricSet that fetches process metrics. type MetricSet struct { mb.BaseMetricSet - stats *process.Stats - cgroup *cgroup.Reader - cacheCmdLine bool + stats *process.Stats + cgroup *cgroup.Reader + perCPU bool } // New creates and returns a new MetricSet. @@ -67,6 +67,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { CacheCmdLine: config.CacheCmdLine, IncludeTop: config.IncludeTop, }, + perCPU: config.IncludePerCPU, } err := m.stats.Init() if err != nil { @@ -116,7 +117,7 @@ func (m *MetricSet) Fetch() ([]common.MapStr, error) { continue } - if statsMap := cgroupStatsToMap(stats); statsMap != nil { + if statsMap := cgroupStatsToMap(stats, m.perCPU); statsMap != nil { proc["cgroup"] = statsMap } } diff --git a/metricbeat/tests/system/test_system.py b/metricbeat/tests/system/test_system.py index 7984d1b105d..d6fc4b7e665 100644 --- a/metricbeat/tests/system/test_system.py +++ b/metricbeat/tests/system/test_system.py @@ -373,6 +373,9 @@ def test_process(self): "extras": { "process.env.whitelist": ["PATH"], "process.include_cpu_ticks": True, + + # Remove 'percpu' prior to checking documented fields because its keys are dynamic. + "process.include_per_cpu": False, } }]) proc = self.start_beat() @@ -395,10 +398,6 @@ def test_process(self): if env is not None: found_env = True - # Remove 'percpu' prior to checking documented fields because its keys are dynamic. - if "cgroup" in process and "cpuacct" in process["cgroup"]: - del process["cgroup"]["cpuacct"]["percpu"] - self.assert_fields_are_documented(evt) # Remove optional keys.