def test_whitelist_blacklist(self): items = ['abc', 'def', 'abcdef', 'ghi'] whitelist = ['def'] blacklist = ['abc'] assert pattern_filter(items, whitelist=whitelist, blacklist=blacklist) == ['def']
def test_key_function(self): items = [Item('abc'), Item('def'), Item('abcdef'), Item('ghi')] whitelist = ['abc', 'def'] assert pattern_filter(items, whitelist=whitelist, key=lambda item: item.name) == [ Item('abc'), Item('def'), Item('abcdef'), ]
def get_projects(self, include_project_name_rules, exclude_project_name_rules): projects = self._api.get_projects() project_by_name = {} for project in projects: name = project.get('name') project_by_name[name] = project filtered_project_names = pattern_filter( [p for p in project_by_name], whitelist=include_project_name_rules, blacklist=exclude_project_name_rules ) result = {name: v for (name, v) in iteritems(project_by_name) if name in filtered_project_names} return result
def _check_linux(self, instance): """ _check_linux can be run inside a container and still collects the network metrics from the host For that procfs_path can be set to something like "/host/proc" When a custom procfs_path is set, the collect_connection_state option is ignored """ proc_location = self.agentConfig.get('procfs_path', '/proc').rstrip('/') custom_tags = instance.get('tags', []) net_proc_base_location = self._get_net_proc_base_location( proc_location) if self._is_collect_cx_state_runnable(net_proc_base_location): try: self.log.debug("Using `ss` to collect connection state") # Try using `ss` for increased performance over `netstat` metrics = self._get_metrics() for ip_version in ['4', '6']: # Call `ss` for each IP version because there's no built-in way of distinguishing # between the IP versions in the output # Also calls `ss` for each protocol, because on some systems (e.g. Ubuntu 14.04), there is a # bug that print `tcp` even if it's `udp` # The `-H` flag isn't available on old versions of `ss`. cmd = "ss --numeric --tcp --all --ipv{} | cut -d ' ' -f 1 | sort | uniq -c".format( ip_version) output, _, _ = get_subprocess_output(["sh", "-c", cmd], self.log) # 7624 CLOSE-WAIT # 72 ESTAB # 9 LISTEN # 1 State # 37 TIME-WAIT lines = output.splitlines() self._parse_short_state_lines(lines, metrics, self.tcp_states['ss'], ip_version=ip_version) cmd = "ss --numeric --udp --all --ipv{} | wc -l".format( ip_version) output, _, _ = get_subprocess_output(["sh", "-c", cmd], self.log) metric = self.cx_state_gauge[('udp{}'.format(ip_version), 'connections')] metrics[metric] = int(output) - 1 # Remove header for metric, value in iteritems(metrics): self.gauge(metric, value, tags=custom_tags) except OSError: self.log.info("`ss` not found: using `netstat` as a fallback") output, _, _ = get_subprocess_output( ["netstat", "-n", "-u", "-t", "-a"], self.log) lines = output.splitlines() # Active Internet connections (w/o servers) # Proto Recv-Q Send-Q Local Address Foreign Address State # tcp 0 0 46.105.75.4:80 79.220.227.193:2032 SYN_RECV # tcp 0 0 46.105.75.4:143 90.56.111.177:56867 ESTABLISHED # tcp 0 0 46.105.75.4:50468 107.20.207.175:443 TIME_WAIT # tcp6 0 0 46.105.75.4:80 93.15.237.188:58038 FIN_WAIT2 # tcp6 0 0 46.105.75.4:80 79.220.227.193:2029 ESTABLISHED # udp 0 0 0.0.0.0:123 0.0.0.0:* # udp6 0 0 :::41458 :::* metrics = self._parse_linux_cx_state( lines[2:], self.tcp_states['netstat'], 5) for metric, value in iteritems(metrics): self.gauge(metric, value, tags=custom_tags) except SubprocessOutputEmptyError: self.log.exception("Error collecting connection stats.") proc_dev_path = "{}/net/dev".format(net_proc_base_location) with open(proc_dev_path, 'r') as proc: lines = proc.readlines() # Inter-| Receive | Transmit # face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed # noqa: E501 # lo:45890956 112797 0 0 0 0 0 0 45890956 112797 0 0 0 0 0 0 # noqa: E501 # eth0:631947052 1042233 0 19 0 184 0 1206 1208625538 1320529 0 0 0 0 0 0 # noqa: E501 # eth1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 # noqa: E501 for l in lines[2:]: cols = l.split(':', 1) x = cols[1].split() # Filter inactive interfaces if self._parse_value(x[0]) or self._parse_value(x[8]): iface = cols[0].strip() metrics = { 'bytes_rcvd': self._parse_value(x[0]), 'bytes_sent': self._parse_value(x[8]), 'packets_in.count': self._parse_value(x[1]), 'packets_in.error': self._parse_value(x[2]) + self._parse_value(x[3]), 'packets_out.count': self._parse_value(x[9]), 'packets_out.error': self._parse_value(x[10]) + self._parse_value(x[11]), } self._submit_devicemetrics(iface, metrics, custom_tags) netstat_data = {} for f in ['netstat', 'snmp']: proc_data_path = "{}/net/{}".format(net_proc_base_location, f) try: with open(proc_data_path, 'r') as netstat: while True: n_header = netstat.readline() if not n_header: break # No more? Abort! n_data = netstat.readline() h_parts = n_header.strip().split(' ') h_values = n_data.strip().split(' ') ns_category = h_parts[0][:-1] netstat_data[ns_category] = {} # Turn the data into a dictionary for idx, hpart in enumerate(h_parts[1:]): netstat_data[ns_category][hpart] = h_values[idx + 1] except IOError: # On Openshift, /proc/net/snmp is only readable by root self.log.debug("Unable to read %s.", proc_data_path) nstat_metrics_names = { 'Tcp': { 'RetransSegs': 'system.net.tcp.retrans_segs', 'InSegs': 'system.net.tcp.in_segs', 'OutSegs': 'system.net.tcp.out_segs', }, 'TcpExt': { 'ListenOverflows': 'system.net.tcp.listen_overflows', 'ListenDrops': 'system.net.tcp.listen_drops', 'TCPBacklogDrop': 'system.net.tcp.backlog_drops', 'TCPRetransFail': 'system.net.tcp.failed_retransmits', }, 'Udp': { 'InDatagrams': 'system.net.udp.in_datagrams', 'NoPorts': 'system.net.udp.no_ports', 'InErrors': 'system.net.udp.in_errors', 'OutDatagrams': 'system.net.udp.out_datagrams', 'RcvbufErrors': 'system.net.udp.rcv_buf_errors', 'SndbufErrors': 'system.net.udp.snd_buf_errors', 'InCsumErrors': 'system.net.udp.in_csum_errors', }, } # Skip the first line, as it's junk for k in nstat_metrics_names: for met in nstat_metrics_names[k]: if met in netstat_data.get(k, {}): self._submit_netmetric(nstat_metrics_names[k][met], self._parse_value( netstat_data[k][met]), tags=custom_tags) # Get the conntrack -S information conntrack_path = instance.get('conntrack_path') if conntrack_path is not None: self._add_conntrack_stats_metrics(conntrack_path, custom_tags) # Get the rest of the metric by reading the files. Metrics available since kernel 3.6 conntrack_files_location = os.path.join(proc_location, 'sys', 'net', 'netfilter') # By default, only max and count are reported. However if the blacklist is set, # the whitelist is loosing its default value blacklisted_files = instance.get('blacklist_conntrack_metrics') whitelisted_files = instance.get('whitelist_conntrack_metrics') if blacklisted_files is None and whitelisted_files is None: whitelisted_files = ['max', 'count'] available_files = [] # Get the metrics to read try: for metric_file in os.listdir(conntrack_files_location): if (os.path.isfile( os.path.join(conntrack_files_location, metric_file)) and 'nf_conntrack_' in metric_file): available_files.append(metric_file[len('nf_conntrack_'):]) except Exception as e: self.log.debug("Unable to list the files in {}. {}".format( conntrack_files_location, e)) filtered_available_files = pattern_filter(available_files, whitelist=whitelisted_files, blacklist=blacklisted_files) for metric_name in filtered_available_files: metric_file_location = os.path.join( conntrack_files_location, 'nf_conntrack_{}'.format(metric_name)) try: with open(metric_file_location, 'r') as conntrack_file: # Checking it's an integer try: value = int(conntrack_file.read().rstrip()) self.gauge( 'system.net.conntrack.{}'.format(metric_name), value, tags=custom_tags) except ValueError: self.log.debug( "{} is not an integer".format(metric_name)) except IOError as e: self.log.debug("Unable to read {}, skipping {}.".format( metric_file_location, e))
def test_multiple_matches_blacklist(self): items = ['abc', 'def', 'abcdef', 'ghi'] blacklist = ['abc', 'def'] assert pattern_filter(items, blacklist=blacklist) == ['ghi']
def test_multiple_matches_whitelist(self): items = ['abc', 'def', 'abcdef', 'ghi'] whitelist = ['abc', 'def'] assert pattern_filter(items, whitelist=whitelist) == ['abc', 'def', 'abcdef']
def test_no_patterns(self): items = ['mock'] assert pattern_filter(items) is items
def test_no_items(self): items = [] whitelist = ['mock'] assert pattern_filter(items, whitelist=whitelist) == []