From 2904246cb5f324fed8709a9f74fdf671eaeb0552 Mon Sep 17 00:00:00 2001 From: Sergei Trofimov Date: Fri, 18 Sep 2015 09:32:09 +0100 Subject: [PATCH] Adding netstats instrument. This instrument allows monitoring data sent/received by applications on an Android device. --- wlauto/instrumentation/netstats/__init__.py | 187 +++++++++++++++++++ wlauto/instrumentation/netstats/netstats.apk | Bin 0 -> 39631 bytes 2 files changed, 187 insertions(+) create mode 100644 wlauto/instrumentation/netstats/__init__.py create mode 100644 wlauto/instrumentation/netstats/netstats.apk diff --git a/wlauto/instrumentation/netstats/__init__.py b/wlauto/instrumentation/netstats/__init__.py new file mode 100644 index 00000000..920bc9ed --- /dev/null +++ b/wlauto/instrumentation/netstats/__init__.py @@ -0,0 +1,187 @@ +import os +import re +import csv +import tempfile +import logging +from datetime import datetime +from collections import defaultdict +from itertools import izip_longest + +from wlauto import Instrument, Parameter +from wlauto import ApkFile +from wlauto.exceptions import DeviceError, HostError +from wlauto.utils.android import ApkInfo +from wlauto.utils.types import list_of_strings + + +THIS_DIR = os.path.dirname(__file__) + +NETSTAT_REGEX = re.compile(r'I/(?Pnetstats-\d+)\(\s*\d*\): (?P\d+) ' + r'"(?P[^"]+)" TX: (?P\S+) RX: (?P\S+)') + + +def extract_netstats(filepath, tag=None): + netstats = [] + with open(filepath) as fh: + for line in fh: + match = NETSTAT_REGEX.search(line) + if not match: + continue + if tag and match.group('tag') != tag: + continue + netstats.append((match.group('tag'), + match.group('ts'), + match.group('package'), + match.group('tx'), + match.group('rx'))) + return netstats + + +def netstats_to_measurements(netstats): + measurements = defaultdict(list) + for row in netstats: + tag, ts, package, tx, rx = row # pylint: disable=unused-variable + measurements[package + '_tx'].append(tx) + measurements[package + '_rx'].append(rx) + return measurements + + +def write_measurements_csv(measurements, filepath): + headers = sorted(measurements.keys()) + columns = [measurements[h] for h in headers] + with open(filepath, 'wb') as wfh: + writer = csv.writer(wfh) + writer.writerow(headers) + writer.writerows(izip_longest(*columns)) + + +class NetstatsCollector(object): + + def __init__(self, target, apk, service='.TrafficMetricsService'): + """ + Additional paramerter: + + :apk: Path to the APK file that contains ``com.arm.devlab.netstats`` + package. If not specified, it will be assumed that an APK with + name "netstats.apk" is located in the same directory as the + Python module for the instrument. + :service: Name of the service to be launched. This service must be + present in the APK. + + """ + self.target = target + self.apk = apk + self.logger = logging.getLogger('netstat') + self.package = ApkInfo(self.apk).package + self.service = service + self.tag = None + self.command = None + self.stop_command = 'am kill {}'.format(self.package) + + def setup(self, force=False): + if self.target.package_is_installed(self.package): + if force: + self.logger.debug('Re-installing {} (forced)'.format(self.package)) + self.target.uninstall(self.package) + self.target.install(self.apk, timeout=300) + else: + self.logger.debug('{} already present on target'.format(self.package)) + else: + self.logger.debug('Deploying {} to target'.format(self.package)) + self.target.install(self.apk) + + def reset(self, sites=None, period=None): + period_arg, packages_arg = '', '' + self.tag = 'netstats-{}'.format(datetime.now().strftime('%Y%m%d%H%M%s')) + tag_arg = ' --es tag {}'.format(self.tag) + if sites: + packages_arg = ' --es packages {}'.format(','.join(sites)) + if period: + period_arg = ' --ei period {}'.format(period) + self.command = 'am startservice{}{}{} {}/{}'.format(tag_arg, + period_arg, + packages_arg, + self.package, + self.service) + self.target.execute(self.stop_command) # ensure the service is not running. + + def start(self): + if self.command is None: + raise RuntimeError('reset() must be called before start()') + self.target.execute(self.command) + + def stop(self): + self.target.execute(self.stop_command) + + def get_data(self, outfile): + raw_log_file = tempfile.mktemp() + self.target.dump_logcat(raw_log_file) + data = extract_netstats(raw_log_file) + measurements = netstats_to_measurements(data) + write_measurements_csv(measurements, outfile) + os.remove(raw_log_file) + + def teardown(self): + self.target.uninstall(self.package) + + +class NetstatsInstrument(Instrument): + # pylint: disable=unused-argument + + name = 'netstats' + description = """ + Measures transmit/receive network traffic on an Android divice on per-package + basis. + + """ + + parameters = [ + Parameter('packages', kind=list_of_strings, + description=""" + List of Android packages who's traffic will be monitored. If + unspecified, all packages in the device will be monitorred. + """), + Parameter('force_reinstall', kind=bool, default=False, + description=""" + If ``True``, instrumentation APK will always be re-installed even if + it already installed on the device. + """), + Parameter('uninstall_on_completion', kind=bool, default=False, + global_alias='cleanup', + description=""" + If ``True``, instrumentation will be uninstalled upon run completion. + """), + ] + + def initialize(self, context): + if self.device.platform != 'android': + raise DeviceError('nestats instrument only supports on Android devices.') + apk = context.resolver.get(ApkFile(self)) + self.collector = NetstatsCollector(self.device, apk) # pylint: disable=attribute-defined-outside-init + self.collector.setup(force=self.force_reinstall) + + def setup(self, context): + self.collector.reset(sites=self.packages) + + def start(self, context): + self.collector.start() + + def stop(self, context): + self.collector.stop() + + def update_result(self, context): + outfile = os.path.join(context.output_directory, 'netstats.csv') + self.collector.get_data(outfile) + context.add_artifact('netstats', outfile, kind='data') + with open(outfile, 'rb') as fh: + reader = csv.reader(fh) + metrics = reader.next() + data = [c for c in izip_longest(*list(reader))] + for name, values in zip(metrics, data): + value = sum(map(int, [v for v in values if v])) + context.add_metric(name, value, units='bytes') + + def finalize(self, context): + if self.uninstall_on_completion: + self.collector.teardown() + diff --git a/wlauto/instrumentation/netstats/netstats.apk b/wlauto/instrumentation/netstats/netstats.apk new file mode 100644 index 0000000000000000000000000000000000000000..8b93da6e5ef477085d51f4a3386b08af776f5ae6 GIT binary patch literal 39631 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 z