diff --git a/monasca_agent/collector/checks_d/process.py b/monasca_agent/collector/checks_d/process.py index 53015473..f7e47cda 100644 --- a/monasca_agent/collector/checks_d/process.py +++ b/monasca_agent/collector/checks_d/process.py @@ -84,7 +84,7 @@ class ProcessCheck(checks.AgentCheck): # process metrics available for psutil versions 0.6.0 and later extended_metrics_0_6_0 = (self.is_psutil_version_later_than((0, 6, 0)) and not util.Platform.is_win32()) - # On Windows get_ext_memory_info returns different metrics + # On Windows ext_memory_info returns different metrics if extended_metrics_0_6_0: real = 0 voluntary_ctx_switches = 0 @@ -116,10 +116,10 @@ class ProcessCheck(checks.AgentCheck): try: p = psutil.Process(pid) if extended_metrics_0_6_0: - mem = p.get_ext_memory_info() + mem = p.memory_info_ex() real += float((mem.rss - mem.shared) / 1048576) try: - ctx_switches = p.get_num_ctx_switches() + ctx_switches = p.num_ctx_switches() voluntary_ctx_switches += ctx_switches.voluntary involuntary_ctx_switches += ctx_switches.involuntary except NotImplementedError: @@ -127,11 +127,11 @@ class ProcessCheck(checks.AgentCheck): voluntary_ctx_switches = None involuntary_ctx_switches = None else: - mem = p.get_memory_info() + mem = p.memory_info() if extended_metrics_0_5_0_unix: try: - open_file_descriptors = float(p.get_num_fds()) + open_file_descriptors = float(p.num_fds()) max_open_file_descriptors = float(p.rlimit(psutil.RLIMIT_NOFILE)[1]) if max_open_file_descriptors > 0.0: open_file_descriptors_perc = open_file_descriptors / max_open_file_descriptors * 100 @@ -142,13 +142,13 @@ class ProcessCheck(checks.AgentCheck): rss += float(mem.rss / 1048576) vms += float(mem.vms / 1048576) - thr += p.get_num_threads() - cpu += p.get_cpu_percent(cpu_check_interval) + thr += p.num_threads() + cpu += p.cpu_percent(cpu_check_interval) - # user might not have permission to call get_io_counters() + # user might not have permission to call io_counters() if read_count is not None: try: - io_counters = p.get_io_counters() + io_counters = p.io_counters() read_count += io_counters.read_count write_count += io_counters.write_count read_kbytes += float(io_counters.read_bytes / 1024) diff --git a/tests/common.py b/tests/common.py new file mode 100644 index 00000000..9b4ee56b --- /dev/null +++ b/tests/common.py @@ -0,0 +1,48 @@ +import os +import sys +import inspect + +import monasca_agent.common.config as configuration +from monasca_agent.common.util import Paths + +# Base config must be loaded before AgentCheck or it will try to load with no config file +base_config = configuration.Config(os.path.join(os.path.dirname(__file__), 'test-agent.yaml')) + +from monasca_agent.collector.checks import AgentCheck + +def load_check(name, config): + checksd_path = Paths().get_checksd_path() + if checksd_path not in sys.path: + sys.path.append(checksd_path) + + check_module = __import__(name) + check_class = None + classes = inspect.getmembers(check_module, inspect.isclass) + for name, clsmember in classes: + if clsmember == AgentCheck: + continue + if issubclass(clsmember, AgentCheck): + check_class = clsmember + if AgentCheck in clsmember.__bases__: + continue + else: + break + if check_class is None: + raise Exception( + "Unable to import check %s. Missing a class that inherits AgentCheck" % name) + + init_config = config.get('init_config', None) + instances = config.get('instances') + + agent_config = base_config.get_config(sections='Main') + # init the check class + try: + return check_class( + name, init_config=init_config, agent_config=agent_config, instances=instances) + except: + # Backwards compatitiblity for old checks that don't support the + # instances argument. + c = check_class(name, init_config=init_config, agent_config=agent_config) + c.instances = instances + return c + diff --git a/tests/test-agent.yaml b/tests/test-agent.yaml new file mode 100644 index 00000000..56ceeb5b --- /dev/null +++ b/tests/test-agent.yaml @@ -0,0 +1,53 @@ +Api: + # To configure Keystone correctly, a project-scoped token must be acquired. + # To accomplish this, the configuration must be set up with one of the + # following scenarios: + # Set username and password and you have a default project set in keystone. + # Set username, password and project id. + # Set username, password, project name and (domain id or domain name). + # + # Monitoring API URL: URL for the monitoring API, if undefined it will be pulled from the keystone service catalog + # Example: https://region-a.geo-1.monitoring.hpcloudsvc.com:8080/v2.0 + url: http://localhost:8080 + # Keystone Username + username: test + # Keystone Password + password: password + # Keystone API URL: URL for the Keystone server to use + # Example: https://region-a.geo-1.identity.hpcloudsvc.com:35357/v3/ + keystone_url: http://localhost:5000 + # Project name to be used by this agent + project_name: test + + # The following 2 options are for handling buffering and reconnection to the monasca-api + # If you want the messages to be sent as fast as possible, set these two options to + # the same number. If you have a larger system with many agents, you may want to throttle + # the number of messages sent to the API by setting the backlog_send_rate to a lower number. + + # Maximum number of messages to buffer when unable to communicate with the monasca-api + max_buffer_size: 1000 + # Maximum number of messages to send at one time when communication with the monasca-api is restored + backlog_send_rate: 1000 + + # Publish extra metrics to the API by adding this number of 'amplifier' dimensions. + # For load testing purposes only; set to 0 for production use. + +Main: + # Force the hostname to whatever you want. + hostname: localhost + +Logging: + # ========================================================================== # + # Logging + # ========================================================================== # + log_level: DEBUG + collector_log_file: /var/log/monasca/agent/collector.log + forwarder_log_file: /var/log/monasca/agent/forwarder.log + statsd_log_file: /var/log/monasca/agent/statsd.log + + # if syslog is enabled but a host and port are not set, a local domain socket + # connection will be attempted + # + # log_to_syslog: yes + # syslog_host: + # syslog_port: diff --git a/tests/test_process.py b/tests/test_process.py new file mode 100644 index 00000000..350ce491 --- /dev/null +++ b/tests/test_process.py @@ -0,0 +1,56 @@ +import unittest + +from tests.common import load_check + + +class TestSimpleProcess(unittest.TestCase): + def setUp(self): + config = {'init_config': {}, 'instances': [{'name': 'test', + 'search_string': ['python'], + 'detailed': False}]} + self.check = load_check('process', config) + + def testPidCount(self): + self.check.run() + metrics = self.check.get_metrics() + self.assertTrue(len(metrics) == 1, metrics) + self.assertTrue(metrics[0].name == 'process.pid_count') + + +class TestDetailedProcess(unittest.TestCase): + def setUp(self): + config = {'init_config': {}, 'instances': [{'name': 'test', + 'search_string': ['python'], + 'detailed': True}]} + self.check = load_check('process', config) + + def testPidCount(self): + self.check.run() + metrics = self.check.get_metrics() + self.assertTrue(len(metrics) > 1, metrics) + + def testMeasurements(self): + self.check.run() + metrics = self.check.get_metrics() + + measurement_names = [] + for metric in metrics: + measurement_names.append(metric.name) + + measurement_names.sort() + + expected_names = ['process.cpu_perc', + 'process.involuntary_ctx_switches', + 'process.io.read_count', + 'process.io.read_kbytes', + 'process.io.write_count', + 'process.io.write_kbytes', + 'process.mem.real_mbytes', + 'process.mem.rss_mbytes', + 'process.mem.vsz_mbytes', + 'process.open_file_descriptors', + 'process.open_file_descriptors_perc', + 'process.pid_count', + 'process.thread_count', + 'process.voluntary_ctx_switches'] + self.assertTrue(measurement_names == expected_names) diff --git a/tests_to_fix/common.py b/tests_to_fix/common.py index f0983be0..11cf08a2 100644 --- a/tests_to_fix/common.py +++ b/tests_to_fix/common.py @@ -8,42 +8,6 @@ from monasca_agent.common.util import Paths from monasca_agent.common.util import get_os -def load_check(name, config, agent_config): - checksd_path = Paths().get_checksd_path() - if checksd_path not in sys.path: - sys.path.append(checksd_path) - - check_module = __import__(name) - check_class = None - classes = inspect.getmembers(check_module, inspect.isclass) - for name, clsmember in classes: - if clsmember == AgentCheck: - continue - if issubclass(clsmember, AgentCheck): - check_class = clsmember - if AgentCheck in clsmember.__bases__: - continue - else: - break - if check_class is None: - raise Exception( - "Unable to import check %s. Missing a class that inherits AgentCheck" % name) - - init_config = config.get('init_config', None) - instances = config.get('instances') - - # init the check class - try: - return check_class( - name, init_config=init_config, agent_config=agent_config, instances=instances) - except: - # Backwards compatitiblity for old checks that don't support the - # instances argument. - c = check_class(name, init_config=init_config, agent_config=agent_config) - c.instances = instances - return c - - def kill_subprocess(process_obj): try: process_obj.terminate()