def stop(self): for monitor in self.monitors: try: monitor.stop() except Exception as e: # 捕获所有的异常,防止其中一个monitor的stop操作发生异常退出时,影响其他的monitor的stop操作 logger.error(e) try: if self.logcat_monitor: self.logcat_monitor.stop() except Exception as e: logger.error("stop exception for logcat monitor") logger.error(e) if self.config_dic["monkey"] == "true": self.device.adb.kill_process("com.android.commands.monkey") # 统计测试时长 cost_time = round((float)(time.time() - TimeUtils.getTimeStamp( RuntimeData.start_time, TimeUtils.UnderLineFormatter)) / 3600, 2) self.add_device_info("test cost time:", str(cost_time) + "h") # 根据csv生成excel汇总文件 Report(RuntimeData.package_save_path, self.packages) self.pull_heapdump() self.pull_log_files() # self.memory_analyse() # self.device.adb.bugreport(RuntimeData.package_save_path) os._exit(0)
def list_dir_between_time(self, dir_path, start_time, end_time): '''列取目录下 起止时间点之间的文件 start_time end_time 时间戳 返回文件绝对路径 列表 ''' # ls - l # -rwxrwx--- 1 root root 19897899 2018-12-27 18:02 com.alibaba.ailabs.ar.fireeye2_dumpheap_2018_12_27_18_02_52.hprof result = self.run_shell_cmd('ls -l %s' % dir_path) if not result: return "" result = result.replace('\r\r\n', '\n') if 'No such file or directory' in result: logger.error('文件(夹) %s 不存在' % dir_path) file_list = [] re_time = re.compile(r'\S*\s+(\d+-\d+-\d+\s+\d+:\d+)\s+\S+') for line in result.split('\n'): items = line.split() match = re_time.search(line) if match: last_modify_time = match.group(1) logger.debug(last_modify_time) last_modify_timestamp = TimeUtils.getTimeStamp(last_modify_time, "%Y-%m-%d %H:%M") # logger.debug(last_modify_timestamp) if start_time < last_modify_timestamp and last_modify_timestamp < end_time: logger.debug("append file:" + items[-1]) file_list.append('%s/%s' % (dir_path, items[-1])) return file_list
def is_overtime_days(self, filepath, days=7): result = self.run_shell_cmd('ls -l %s' % filepath) if not result: return False result = result.replace('\r\r\n', '\n') if 'No such file or directory' in result: logger.error('文件(夹) %s 不存在' % filepath) return False re_time = re.compile(r'\S*\s+(\d+-\d+-\d+\s+\d+:\d+)\s+\S+') match = re_time.search(result) if match: last_modify_time = match.group(1) logger.debug(last_modify_time) last_modify_timestamp = TimeUtils.getTimeStamp(last_modify_time, "%Y-%m-%d %H:%M") # logger.debug(last_modify_timestamp) if last_modify_timestamp < (time.time() - days * 24 * 60 * 60): logger.debug(filepath + " is overtime days:" + str(days)) return True else: logger.debug(filepath + " is not overtime days:" + str(days)) return False logger.debug(filepath + " not have match time formatter") return False
def _collect_memory_thread(self, start_time): end_time = time.time() + self._timeout mem_list_titile = ["datatime", "total_ram(MB)", "free_ram(MB)"] pid_list_titile = ["datatime"] pss_detail_titile = [ "datatime", "package", "pid", "pss", "java_heap", "native_heap", "system" ] for i in range(0, len(self.packages)): mem_list_titile.extend(["package", "pid", "pid_pss(MB)"]) pid_list_titile.extend(["package", "pid"]) if len(self.packages) > 1: mem_list_titile.append("total_pss(MB)") mem_file = os.path.join(RuntimeData.package_save_path, 'meminfo.csv') pid_file = os.path.join(RuntimeData.package_save_path, 'pid_change.csv') for package in self.packages: pss_detail_file = os.path.join( RuntimeData.package_save_path, 'pss_%s.csv' % package.split(".")[-1].replace(":", "_")) with open(pss_detail_file, 'a+') as df: csv.writer(df, lineterminator='\n').writerow(pss_detail_titile) try: with open(mem_file, 'a+') as df: csv.writer(df, lineterminator='\n').writerow(mem_list_titile) if self.mem_queue: mem_file_dic = {'mem_file': mem_file} self.mem_queue.put(mem_file_dic) with open(pid_file, 'a+') as df: csv.writer(df, lineterminator='\n').writerow(pid_list_titile) except RuntimeError as e: logger.error(e) starttime_stamp = TimeUtils.getTimeStamp(start_time, "%Y_%m_%d_%H_%M_%S") old_package_pid_pss_list = [] dumpsys_mem_times = 0 # D系统上会报错 System server has no access to file context # hprof_path = "/sdcard/hprof" hprof_path = "/data/local/tmp" self.device.adb.run_shell_cmd("mkdir " + hprof_path) # sdcard 卡目录下dump需要打开这个开关 self.device.adb.run_shell_cmd("setenforce 0") first_dump = True while not self._stop_event.is_set() and time.time() < end_time: try: before = time.time() logger.debug( "-----------into _collect_mem_thread loop, thread is : " + str(threading.current_thread().name)) collection_time = time.time() # # 获取主进程的详细信息 for package in self.packages: mem_pck_snapshot = self._dumpsys_process_meminfo(package) if 0 == mem_pck_snapshot.totalPSS: logger.error("package total pss is 0:%s" % package) continue pss_detail_file = os.path.join( RuntimeData.package_save_path, 'pss_%s.csv' % package.split(".")[-1].replace(":", "_")) pss_detail_list = [ TimeUtils.formatTimeStamp(collection_time), package, mem_pck_snapshot.pid, mem_pck_snapshot.totalPSS, mem_pck_snapshot.javaHeap, mem_pck_snapshot.nativeHeap, mem_pck_snapshot.system ] with open(pss_detail_file, 'a+') as pss_writer: writer_p = csv.writer(pss_writer, lineterminator='\n') writer_p.writerow(pss_detail_list) # 写到pss_detail表格中 # 手机每5分钟 dumpheap一次 if (before - starttime_stamp) > 300 or first_dump: # 先清理hprof文件 filelist = self.device.adb.list_dir(hprof_path) if filelist: for file in filelist: for package in self.packages: if package in file: self.device.adb.delete_file(hprof_path + "/" + file) # if (before - starttime_stamp) % 60 < self._interval and "D" in self.device.adb.get_system_version(): for package in self.packages: self.device.adb.dumpheap(package, RuntimeData.package_save_path) starttime_stamp = before # self.device.adb.run_shell_cmd("kill -10 %s"%str(mem_pck_snapshot.pid)) # dumpsys meminfo 耗时长,可能会导致system server cpu占用变高,降低采集频率 dumpsys_mem_times = dumpsys_mem_times + 1 # 10倍率frequency dumpsys meminfo一次 if dumpsys_mem_times % 10 == 0 or first_dump: mem_device_snapshot = self._dumpsys_meminfo() # 如果没有采集到dumpsys meminfo的信息,正常情况totalmem不可能为0 if mem_device_snapshot == None or not mem_device_snapshot.package_pid_pss_list or mem_device_snapshot.totalmem == 0: logger.error("mem_device_snapshot is none") # 如果获取不到结果,继续延长采集间隔 dumpsys_mem_times = dumpsys_mem_times - 1 continue first_dump = False logger.debug("current time: " + TimeUtils.getCurrentTime() + ", processname: " + ",total pss:" + str(mem_device_snapshot.total_pss)) logger.debug("collection time in meminfo is : " + TimeUtils.getCurrentTime()) gather_list = [ TimeUtils.formatTimeStamp(collection_time), mem_device_snapshot.totalmem, mem_device_snapshot.freemem ] pid_list = [TimeUtils.formatTimeStamp(collection_time)] pid_change = False for i in range(0, len(self.packages)): if len(mem_device_snapshot.package_pid_pss_list ) == len(self.packages): gather_list.extend([ mem_device_snapshot.package_pid_pss_list[i] ["package"], mem_device_snapshot.package_pid_pss_list[i] ["pid"], mem_device_snapshot.package_pid_pss_list[i] ["pss"] ]) if not old_package_pid_pss_list: old_package_pid_pss_list = mem_device_snapshot.package_pid_pss_list pid_change = True else: for i in range(0, len(self.packages)): package = mem_device_snapshot.package_pid_pss_list[ i]["package"] if mem_device_snapshot.package_pid_pss_list[i]["pid"] and \ old_package_pid_pss_list[i]["pid"]!=mem_device_snapshot.package_pid_pss_list[i]["pid"]: pid_change = True # 确保上次pid也有 if old_package_pid_pss_list[i]["pid"]: if package and package in RuntimeData.config_dic[ "pid_change_focus_package"]: # 确保有tombstones文件才提单 self.device.adb.pull_file( "/data/vendor/tombstones", RuntimeData.package_save_path) if pid_change: old_package_pid_pss_list = mem_device_snapshot.package_pid_pss_list for i in range(0, len(self.packages)): if len(old_package_pid_pss_list) == len( self.packages): pid_list.extend([ old_package_pid_pss_list[i]["package"], old_package_pid_pss_list[i]["pid"] ]) try: with open(pid_file, 'a+') as pid_writer: writer_p = csv.writer(pid_writer, lineterminator='\n') writer_p.writerow(pid_list) logger.debug("write to file:" + pid_file) logger.debug(pid_list) except RuntimeError as e: logger.error(e) if len(self.packages) > 1: gather_list.append(mem_device_snapshot.total_pss) if self.mem_queue: gather_list[0] = collection_time self.mem_queue.put(gather_list) if not self.mem_queue: #为了本地单个文件运行 try: with open(mem_file, 'a+') as mem_writer: writer_p = csv.writer(mem_writer, lineterminator='\n') writer_p.writerow(gather_list) logger.debug("write to file:" + mem_file) logger.debug(gather_list) except RuntimeError as e: logger.error(e) after = time.time() time_consume = after - before delta_inter = self._interval - time_consume logger.info("time consume for meminfos: " + str(time_consume)) if delta_inter > 0: time.sleep(delta_inter) except: logger.error( "an exception hanpend in meminfo thread, reason unkown!") s = traceback.format_exc() logger.debug(s) if self.mem_queue: self.mem_queue.task_done() logger.debug("stop event is set or timeout")