Пример #1
0
 def _monkey_thread_func(self,save_dir):
     '''获取monkey线程,保存monkey日志,monkey Crash日志暂不处理,后续有需要再处理
     '''
     self.append_log_line_num = 0
     self.file_log_line_num = 0
     self.log_file_create_time = None
     log_is_none = 0
     logs = []
     logger.debug("monkey_thread_func")
     if RuntimeData.start_time is None:
         RuntimeData.start_time = TimeUtils.getCurrentTime()
     while self.running:
         try:
             log = self._log_pipe.stdout.readline().strip()
             if not isinstance(log, str):
                 # 先编码为unicode
                 try:
                     log = str(log, "utf8")
                 except Exception as e:
                     log = repr(log)
                     logger.error('str error:' + log)
                     logger.error(e)
             if log:
                 logs.append(log)
                 self.append_log_line_num = self.append_log_line_num + 1
                 self.file_log_line_num = self.file_log_line_num + 1
                 # if self.append_log_line_num > 1000:
                 if self.append_log_line_num > 100:
                     if not self.log_file_create_time:
                         self.log_file_create_time = TimeUtils.getCurrentTimeUnderline()
                     log_file = os.path.join(save_dir,
                                             'monkey_%s.log' % self.log_file_create_time)
                     self.append_log_line_num = 0
                     # 降低音量,避免音量过大,导致语音指令失败
                     self.device.adb.run_shell_cmd("input keyevent 25")
                     self.save(log_file, logs)
                     logs = []
                 # 新建文件
                 if self.file_log_line_num > 600000:
                     # if self.file_log_line_num > 200:
                     self.file_log_line_num = 0
                     self.log_file_create_time = TimeUtils.getCurrentTimeUnderline()
                     log_file = os.path.join(save_dir, 'monkey_%s.log' % self.log_file_create_time)
                     self.save(log_file, logs)
                     logs = []
             else:
                 log_is_none = log_is_none + 1
                 if log_is_none % 1000 == 0:
                     logger.info("log is none")
                     if not self.device.adb.is_process_running("com.android.commands.monkey") and self.running:
                         self.device.adb.kill_process("com.android.commands.monkey")
                         self._log_pipe = self.device.adb.run_shell_cmd(self.monkey_cmd, sync=False)
         except:
             logger.error("an exception hanpend in monkey thread, reason unkown!")
             s = traceback.format_exc()
             logger.debug(s)
Пример #2
0
 def __init__(self, csv_dir, packages=[]):
     os.chdir(csv_dir)
     # 需要画曲线的csv文件名
     self.summary_csf_file = {
         "cpuinfo.csv": {
             "table_name": "pid_cpu",
             "x_axis": "datatime",
             "y_axis": "%",
             "values": ["pid_cpu%", "total_pid_cpu%"]
         },
         "meminfo.csv": {
             "table_name": "pid_pss",
             "x_axis": "datatime",
             "y_axis": "mem(MB)",
             "values": ["pid_pss(MB)", "total_pss(MB)"]
         },
         "pid_change.csv": {
             "table_name": "pid",
             "x_axis": "datatime",
             "y_axis": "pid_num",
             "values": ["pid"]
         },
     }
     self.packages = packages
     if len(self.packages) > 0:
         for package in self.packages:
             pss_detail_dic = {
                 "table_name": "pss_detail",
                 "x_axis": "datatime",
                 "y_axis": "mem(MB)",
                 "values": ["pss", "java_heap", "native_heap", "system"]
             }
             #        文件名太长会导致写excel失败
             self.summary_csf_file["pss_%s.csv" %
                                   package.split(".")[-1].replace(
                                       ":", "_")] = pss_detail_dic
     logger.debug(self.packages)
     logger.debug(self.summary_csf_file)
     logger.info('create report for %s' % csv_dir)
     file_names = self.filter_file_names(csv_dir)
     logger.debug('%s' % file_names)
     if file_names:
         book_name = 'summary_%s.xlsx' % TimeUtils.getCurrentTimeUnderline()
         excel = Excel(book_name)
         for file_name in file_names:
             logger.debug('get csv %s to excel' % file_name)
             values = self.summary_csf_file[file_name]
             excel.csv_to_xlsx(file_name, values["table_name"],
                               values["x_axis"], values["y_axis"],
                               values["values"])
         logger.info('wait to save %s' % book_name)
         excel.save()
Пример #3
0
 def run_shell_cmd(self, cmd, **kwds):
     '''执行 adb shell 命令
     '''
     # 如果失去连接后,adb又正常连接了
     if not self.before_connect and self.after_connect:
         cpu_uptime_file = os.path.join(RuntimeData.package_save_path, "uptime.txt")
         with open(cpu_uptime_file, "a+",encoding = "utf-8") as writer:
             writer.write(TimeUtils.getCurrentTimeUnderline() + " /proc/uptime:" + self.run_adb_cmd("shell cat /proc/uptime") + "\n")
         self.before_connect = True
     ret = self.run_adb_cmd('shell', '%s' % cmd, **kwds)
     # 当 adb 命令传入 sync=False时,ret是Poen对象
     if ret == None:
         logger.error(u'adb cmd failed:%s ' % cmd)
     return ret
Пример #4
0
    def handle_exception(self, log_line):
        '''
        这个方法在每次有log时回调
        :param log_line:最近一条的log 内容
        异常日志写一个文件
        :return:void
        '''

        for tag in self.exception_log_list:
            if tag in log_line:
                logger.debug("exception Info: " + log_line)
                tmp_file = os.path.join(RuntimeData.package_save_path,
                                        'exception.log')
                with open(tmp_file, 'a+') as f:
                    f.write(log_line + '\n')
                #     这个路径 空格会有影响
                process_stack_log_file = os.path.join(
                    RuntimeData.package_save_path, 'process_stack_%s_%s.log' %
                    (self.package, TimeUtils.getCurrentTimeUnderline()))
                # 如果进程挂了,pid会变 ,抓变后进程pid的堆栈没有意义
                # self.logmonitor.device.adb.get_process_stack(self.package,process_stack_log_file)
                if RuntimeData.old_pid:
                    self.device.adb.get_process_stack_from_pid(
                        RuntimeData.old_pid, process_stack_log_file)
Пример #5
0
    def run(self, time_out=None):
        self.clear_heapdump()
        # objgraph.show_growth()
        #       对设备连接情况的检查
        if not self.serialnum:
            #           androiddevice 没传  serialnum,默认执行adb shell
            logger.info(
                "serialnum in config file is null,default get connected phone")
        is_device_connect = False
        for i in range(0, 5):
            if self.device.adb.is_connected(self.serialnum):
                is_device_connect = True
                break
            else:
                logger.error("device not found:" + self.serialnum)
                time.sleep(2)
        if not is_device_connect:
            logger.error("after 5 times check,device not found:" +
                         self.serialnum)
            return

# 对是否安装被测app的检查 只在最开始检查一次
        if not self.device.adb.is_app_installed(self.packages[0]):
            logger.error("test app not installed:" + self.packages[0])
            return
        try:
            #初始化数据处理的类,将没有消息队列传递过去,以便获取数据,并处理
            # datahandle = DataWorker(self.get_queue_dic())
            # 将queue传进去,与datahandle那个线程交互
            self.add_monitor(
                CpuMonitor(self.serialnum, self.packages, self.frequency,
                           self.timeout))
            self.add_monitor(
                MemMonitor(self.serialnum, self.packages, self.frequency,
                           self.timeout))
            self.add_monitor(
                TrafficMonitor(self.serialnum, self.packages[0],
                               self.frequency, self.timeout))
            # 软件方式 获取电量不准,已用硬件方案测试功耗
            # self.add_monitor(PowerMonitor(self.serialnum, self.frequency,self.timeout))
            self.add_monitor(
                FPSMonitor(self.serialnum, self.packages[0], self.frequency,
                           self.timeout))
            # 6.0以下能采集到fd数据,7.0以上没权限
            if self.device.adb.get_sdk_version() <= 23:
                self.add_monitor(
                    FdMonitor(self.serialnum, self.packages[0], self.frequency,
                              self.timeout))
            self.add_monitor(
                ThreadNumMonitor(self.serialnum, self.packages[0],
                                 self.frequency, self.timeout))
            if self.config_dic["monkey"] == "true":
                self.add_monitor(Monkey(self.serialnum, self.packages[0]))
            if self.config_dic["main_activity"] and self.config_dic[
                    "activity_list"]:
                self.add_monitor(
                    DeviceMonitor(self.serialnum, self.packages[0],
                                  self.frequency,
                                  self.config_dic["main_activity"],
                                  self.config_dic["activity_list"],
                                  RuntimeData.exit_event))

            if len(self.monitors):
                start_time = TimeUtils.getCurrentTimeUnderline()
                RuntimeData.start_time = start_time
                if self.config_dic["save_path"]:
                    RuntimeData.package_save_path = os.path.join(
                        self.config_dic["save_path"], self.packages[0],
                        start_time)
                else:
                    RuntimeData.package_save_path = os.path.join(
                        RuntimeData.top_dir, 'results', self.packages[0],
                        start_time)
                FileUtils.makedir(RuntimeData.package_save_path)
                self.save_device_info()
                for monitor in self.monitors:
                    #启动所有的monitors
                    try:
                        monitor.start(start_time)
                    except Exception as e:
                        logger.error(e)
                # logcat的代码可能会引起死锁,拎出来单独处理logcat
                try:
                    self.logcat_monitor = LogcatMonitor(
                        self.serialnum, self.packages[0])
                    # 如果有异常日志标志,才启动这个模块
                    if self.exceptionlog_list:
                        self.logcat_monitor.set_exception_list(
                            self.exceptionlog_list)
                        self.logcat_monitor.add_log_handle(
                            self.logcat_monitor.handle_exception)
                    time.sleep(1)
                    self.logcat_monitor.start(start_time)
                except Exception as e:
                    logger.error(e)

                timeout = time_out if time_out != None else self.config_dic[
                    'timeout']
                endtime = time.time() + timeout
                while (time.time() < endtime):  #吊着主线程防止线程中断
                    # 时间到或测试过程中检测到异常
                    if self.check_exit_signal_quit():
                        logger.error("app " + str(self.packages[0]) +
                                     " exit signal, quit!")
                        break
                    time.sleep(self.frequency)
                logger.debug("time is up,finish!!!")
                self.stop()

                # try:
                #     datahandle.stop()
                #     time.sleep(self.frequency*2)
                #     #               延迟一点时间结束上报,已让数据上报完
                #     # report.stop()
                # except:
                #     logger.debug("report or datahandle stop exception")
                # finally:
                #     logger.info("time is up, end")
                #     os._exit(0)

        except KeyboardInterrupt:  #捕获键盘异常的事件,例如ctrl c
            logger.debug(" catch keyboardInterrupt, goodbye!!!")
            # 收尾工作
            self.stop()
            os._exit(0)
        except Exception as e:
            logger.error("Exception in run")
            logger.error(e)
Пример #6
0
    def _calculator_thread(self, start_time):
        '''处理surfaceflinger数据
        '''
        fps_file = os.path.join(RuntimeData.package_save_path, 'fps.csv')
        if self.use_legacy_method:
            fps_title = ['datetime', 'fps']
        else:
            fps_title = ['datetime', "activity window", 'fps', 'jank']
        try:
            with open(fps_file, 'a+') as df:
                csv.writer(df, lineterminator='\n').writerow(fps_title)
                if self.fps_queue:
                    fps_file_dic = {'fps_file': fps_file}
                    self.fps_queue.put(fps_file_dic)
        except RuntimeError as e:
            logger.exception(e)

        while True:
            try:
                data = self.data_queue.get()
                if isinstance(data, str) and data == 'Stop':
                    break
                before = time.time()
                if self.use_legacy_method:
                    td = data['timestamp'] - self.surface_before['timestamp']
                    seconds = td.seconds + td.microseconds / 1e6
                    frame_count = (data['page_flip_count'] -
                                   self.surface_before['page_flip_count'])
                    fps = int(round(frame_count / seconds))
                    if fps > 60:
                        fps = 60
                    self.surface_before = data
                    logger.debug('FPS:%2s' % fps)
                    tmp_list = [TimeUtils.getCurrentTimeUnderline(), fps]
                    try:
                        with open(fps_file, 'a+') as f:
                            # tmp_list[0] = TimeUtils.formatTimeStamp(tmp_list[0])
                            csv.writer(f,
                                       lineterminator='\n').writerow(tmp_list)
                    except RuntimeError as e:
                        logger.exception(e)
                else:
                    refresh_period = data[0]
                    timestamps = data[1]
                    collect_time = data[2]
                    fps, jank = self._calculate_results(
                        refresh_period, timestamps)
                    logger.debug('FPS:%2s Jank:%s' % (fps, jank))
                    fps_list = [collect_time, self.focus_window, fps, jank]
                    if self.fps_queue:
                        self.fps_queue.put(fps_list)
                    if not self.fps_queue:  #为了让单个脚本运行时保存数据
                        try:
                            with open(fps_file, 'a+') as f:
                                tmp_list = copy.deepcopy(fps_list)
                                tmp_list[0] = TimeUtils.formatTimeStamp(
                                    tmp_list[0])
                                csv.writer(
                                    f, lineterminator='\n').writerow(tmp_list)
                        except RuntimeError as e:
                            logger.exception(e)
                time_consume = time.time() - before
                delta_inter = self.frequency - time_consume
                if delta_inter > 0:
                    time.sleep(delta_inter)
            except:
                logger.error(
                    "an exception hanpend in fps _calculator_thread ,reason unkown!"
                )
                s = traceback.format_exc()
                logger.debug(s)
                if self.fps_queue:
                    self.fps_queue.task_done()
Пример #7
0
    def save(self):
        pass

    def parse(self, file_path):
        '''解析
        :param str file_path: 要解析数据文件的路径
        '''
        pass

    def get_fps_collector(self):
        '''获得fps收集器,收集器里保存着time fps jank的列表
        
        :return: fps收集器
        :rtype: SurfaceStatsCollector
        '''
        return self.fpscollector


if __name__ == '__main__':
    #    tulanduo android8.0 api level 27
    monitor = FPSMonitor('TC79SSDMO7HEY5Z9',
                         "com.alibaba.ailabs.genie.smartapp", 1)
    #  mate 9 android8.0
    #     monitor  = FPSMonitor('MKJNW18226007860',"com.sankuai.meituan",2)
    # android8.0 Google Pixel 2
    #     monitor  = FPSMonitor('HT7B81A05143',package_name = "com.alibaba.ailibs.genie.contacts",1)
    monitor.start(TimeUtils.getCurrentTimeUnderline())
    time.sleep(600)
    monitor.stop()
Пример #8
0
 def dump_native_heap(self, package, save_path):
     native_heap_file = "/data/local/tmp/%s_native_heap_%s.txt" % (package, TimeUtils.getCurrentTimeUnderline())
     self.run_shell_cmd("am dumpheap -n %s %s" % (package, native_heap_file))
Пример #9
0
 def dumpheap(self, package, save_path):
     heapfile = "/data/local/tmp/%s_dumpheap_%s.hprof" % (package, TimeUtils.getCurrentTimeUnderline())
     self.run_shell_cmd("am dumpheap %s %s" % (package, heapfile))
     time.sleep(10)
     self.pull_file(heapfile,save_path)
Пример #10
0
    def _logcat_thread_func(self, save_dir, process_list, params=""):
        '''获取logcat线程
                '''
        self.append_log_line_num = 0
        self.file_log_line_num = 0
        self.log_file_create_time = None
        logs = []
        logger.debug("logcat_thread_func")
        log_is_none = 0
        while self._logcat_running:
            try:
                log = self._log_pipe.stdout.readline().strip()
                if not isinstance(log, str):
                    try:
                        log = str(log,"utf8")
                    except Exception as e:
                        log = repr(log)
                        logger.error('str error:'+log)
                        logger.error(e)
                if log:
                    log_is_none = 0
                    # logger.debug(log)
                    logs.append(log)
                    # if self._log_pipe.poll() != None:
                    #     logger.debug('process:%s have exited' % self._log_pipe.pid)
                    #     if self._logcat_running :
                    #         self._log_pipe = self.run_shell_cmd('logcat ' + params, sync=False)
                    #     else :
                    #         break
                    for _handle in self._logcat_handle:
                        try:
                            _handle(log)
                        except Exception as e:
                            logger.error("an exception happen in logcat handle log , reason unkown!, e:")
                            logger.error(e)

                    self.append_log_line_num = self.append_log_line_num + 1
                    self.file_log_line_num = self.file_log_line_num + 1
                    # if self.append_log_line_num > 1000:
                    if self.append_log_line_num > 100:
                        if not self.log_file_create_time:
                            self.log_file_create_time = TimeUtils.getCurrentTimeUnderline()
                        logcat_file = os.path.join(save_dir,
                                                'logcat_%s.log' % self.log_file_create_time)
                        self.append_log_line_num = 0
                        self.save(logcat_file, logs)
                        logs = []
                    # 新建文件
                    if self.file_log_line_num > 600000:
                    # if self.file_log_line_num > 200:
                        self.file_log_line_num = 0
                        self.log_file_create_time = TimeUtils.getCurrentTimeUnderline()
                        logcat_file = os.path.join(save_dir, 'logcat_%s.log' % self.log_file_create_time)
                        self.save(logcat_file, logs)
                        logs = []
                else:
                    log_is_none = log_is_none + 1
                    if log_is_none % 1000 == 0:
                        logger.info("log is none")
                        self._log_pipe = self.run_shell_cmd('logcat -v threadtime ' + params, sync=False)
            except:
                logger.error("an exception hanpend in logcat thread, reason unkown!")
                s = traceback.format_exc()
                logger.debug(s)
Пример #11
0
            "time": timestamp,
            "act_name": content[1],
            "this_time": content[2],
            "total_time": content[3],
            "launch_type": content[4]
        }
        perf_data['launch_time'].append(dic)
        # perf_queue.put(perf_data)

        with open(tmp_file, "a+") as f:
            csvwriter = csv.writer(f, lineterminator='\n')  #这种方式可以去除csv的空行
            logger.debug("save launchtime data to csv: " +
                         str(self.launch_list))
            csvwriter.writerows(self.launch_list)
            del self.launch_list[:]


if __name__ == '__main__':
    logcat_monitor = LogcatMonitor("85I7UO4PFQCINJL7", "com.yunos.tv.alitvasr")
    # 如果有异常日志标志,才启动这个模块
    exceptionlog_list = ["fatal exception", "has died"]
    if exceptionlog_list:
        logcat_monitor.set_exception_list(exceptionlog_list)
        logcat_monitor.add_log_handle(logcat_monitor.handle_exception)
    start_time = TimeUtils.getCurrentTimeUnderline()
    RuntimeData.package_save_path = os.path.join(FileUtils.get_top_dir(),
                                                 'results',
                                                 "com.yunos.tv.alitvasr",
                                                 start_time)
    logcat_monitor.start(start_time)