Skip to content

Add extended flag to CPU collector #577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/collectors/CPUCollector.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Setting | Default | Description | Type
--------|---------|-------------|-----
byte_unit | byte | Default numeric output(s) | str
enabled | False | Enable collecting these metrics | bool
extended | False | return aggregate CPU% metric and complex CPU metrics | str
measure_collector_time | False | Collect the collector run time in ms | bool
metrics_blacklist | None | Regex to match metrics to block. Mutually exclusive with metrics_whitelist | NoneType
metrics_whitelist | None | Regex to match metrics to transmit. Mutually exclusive with metrics_blacklist | NoneType
Expand All @@ -33,4 +34,3 @@ servers.hostname.cpu.total.nice 0.0
servers.hostname.cpu.total.system 0.2
servers.hostname.cpu.total.user 0.4
```

12 changes: 9 additions & 3 deletions src/collectors/cpu/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def get_default_config_help(self):
config_help.update({
'percore': 'Collect metrics per cpu core or just total',
'simple': 'only return aggregate CPU% metric',
'extended': 'return aggregate CPU% metric and complex CPU metrics',
'normalize': 'for cpu totals, divide by the number of CPUs',
})
return config_help
Expand All @@ -57,6 +58,7 @@ def get_default_config(self):
'percore': 'True',
'xenfix': None,
'simple': 'False',
'extended': 'False',
'normalize': 'False',
})
return config
Expand Down Expand Up @@ -91,12 +93,16 @@ def cpu_delta_time(interval):

if os.access(self.PROC, os.R_OK):

# If simple only return aggregate CPU% metric
if str_to_bool(self.config['simple']):
# If simple only return aggregate CPU% metric, unless extended is
# set (in which case return both)
if str_to_bool(self.config['simple']) or \
str_to_bool(self.config['extended']):
dt = cpu_delta_time(self.INTERVAL)
cpuPct = 100 - (dt[len(dt) - 1] * 100.00 / sum(dt))
self.publish('percent', str('%.4f' % cpuPct))
return True
# Only return simple metrics, unless the `extended` flag is set
if not str_to_bool(self.config['extended']):
return True

results = {}
# Open file
Expand Down
100 changes: 100 additions & 0 deletions src/collectors/cpu/test/testcpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,106 @@ def test_should_work_psutil(self, psutil_mock, os_mock, publish_mock):

self.assertPublishedMany(publish_mock, self.expected)


class TestCPUCollectorSimple(CollectorTestCase):

def setUp(self):
self.config = get_collector_config('CPUCollector', {
'interval': 10,
'normalize': False,
'simple': True,
})

self.collector = CPUCollector(self.config, None)

def test_import(self):
self.assertTrue(CPUCollector)

@patch.object(Collector, 'publish')
def test_produces_simple_percent(self, publish_mock):
# when the simple config option is set, we check the CPU values twice
# to calculate a delta, so we need two mock values
m = Mock()
patch_open = patch('__builtin__.open', m)
m.side_effect = [
StringIO('cpu 100 200 300 400 500 0 0 0 0 0'),
StringIO('cpu 110 220 330 440 550 0 0 0 0 0'),
]

patch_open.start()
self.collector.collect()
patch_open.stop()

self.assertPublishedMany(publish_mock, {})

m = Mock()
patch_open = patch('__builtin__.open', m)
m.side_effect = [
StringIO('cpu 110 220 330 440 550 0 0 0 0 0'),
StringIO('cpu 120 230 340 450 560 0 0 0 0 0'),
]

patch_open.start()
self.collector.collect()
patch_open.stop()

self.assertPublishedMany(publish_mock, {
'percent': 75.0
})


class TestCPUCollectorExtended(CollectorTestCase):

def setUp(self):
self.config = get_collector_config('CPUCollector', {
'interval': 10,
'normalize': False,
'extended': True,
})

self.collector = CPUCollector(self.config, None)

def test_import(self):
self.assertTrue(CPUCollector)

@patch.object(Collector, 'publish')
def test_produces_simple_and_complex(self, publish_mock):
# similar to above, we need three mock values: two for the simple
# metric (to calculate a delta), plus one more for the standard
# metrics
patch_open = patch('__builtin__.open', Mock(side_effect=[
StringIO('cpu 100 200 300 400 500 0 0 0 0 0'),
StringIO('cpu 110 220 330 440 550 0 0 0 0 0'),
StringIO('cpu 100 200 300 400 500 0 0 0 0 0'),
]))

patch_open.start()
self.collector.collect()
patch_open.stop()

self.assertPublishedMany(publish_mock, {})

patch_open = patch('__builtin__.open', Mock(side_effect=[
StringIO('cpu 110 220 330 440 550 0 0 0 0 0'),
StringIO('cpu 120 230 340 450 560 0 0 0 0 0'),
StringIO('cpu 110 220 330 440 550 0 0 0 0 0'),
]))

patch_open.start()
self.collector.collect()
patch_open.stop()

# Since the `extended` config option is set, we should see both simple
# percent-only metrics, but also the standard metrics
self.assertPublishedMany(publish_mock, {
'total.user': 1.0,
'total.nice': 2.0,
'total.system': 3.0,
'total.idle': 4.0,
'percent': 75.0
})


##########################################################################
if __name__ == "__main__":
unittest.main()