async def run_instruments( self, stop: asyncio.Event, template: str, app_bundle_id: str, trace_path: str, post_process_arguments: Optional[List[str]] = None, env: Optional[Dict[str, str]] = None, app_args: Optional[List[str]] = None, started: Optional[asyncio.Event] = None, timings: Optional[InstrumentsTimings] = None, ) -> str: trace_path = os.path.realpath(trace_path) self.logger.info(f"Starting instruments connection, writing to {trace_path}") async with self.get_stub() as stub, stub.instruments_run.open() as stream: self.logger.info("Sending instruments request") await stream.send_message( InstrumentsRunRequest( start=InstrumentsRunRequest.Start( file_path=None, template_name=template, app_bundle_id=app_bundle_id, environment=env, arguments=app_args, timings=translate_instruments_timings(timings), ) ) ) self.logger.info("Starting instruments") await drain_until_running(stream=stream, logger=self.logger) if started: started.set() self.logger.info("Instruments has started, waiting for stop") async for response in stop_wrapper(stream=stream, stop=stop): output = response.log_output if len(output): self.logger.info(output.decode()) self.logger.info("Stopping instruments") await stream.send_message( InstrumentsRunRequest( stop=InstrumentsRunRequest.Stop( post_process_arguments=post_process_arguments ) ) ) await stream.end() self.logger.info(f"Writing instruments from tar to {trace_path}") await drain_untar( instruments_generate_bytes(stream=stream, logger=self.logger), output_path=trace_path, ) self.logger.info(f"Instruments trace written to {trace_path}") return trace_path
async def run_instruments( self, stop: asyncio.Event, trace_basename: str, template_name: str, app_bundle_id: str, app_environment: Optional[Dict[str, str]] = None, app_arguments: Optional[List[str]] = None, tool_arguments: Optional[List[str]] = None, started: Optional[asyncio.Event] = None, timings: Optional[InstrumentsTimings] = None, post_process_arguments: Optional[List[str]] = None, ) -> List[str]: self.logger.info(f"Starting instruments connection") async with self.get_stub() as stub, stub.instruments_run.open() as stream: self.logger.info("Sending instruments request") await stream.send_message( InstrumentsRunRequest( start=InstrumentsRunRequest.Start( template_name=template_name, app_bundle_id=app_bundle_id, environment=app_environment, arguments=app_arguments, tool_arguments=tool_arguments, timings=translate_instruments_timings(timings), ) ) ) self.logger.info("Starting instruments") await instruments_drain_until_running(stream=stream, logger=self.logger) if started: started.set() self.logger.info("Instruments has started, waiting for stop") async for response in stop_wrapper(stream=stream, stop=stop): output = response.log_output if len(output): self.logger.info(output.decode()) self.logger.info("Stopping instruments") await stream.send_message( InstrumentsRunRequest( stop=InstrumentsRunRequest.Stop( post_process_arguments=post_process_arguments ) ) ) await stream.end() result = [] with tempfile.TemporaryDirectory() as tmp_trace_dir: self.logger.info( f"Writing instruments data from tar to {tmp_trace_dir}" ) await drain_untar( instruments_generate_bytes(stream=stream, logger=self.logger), output_path=tmp_trace_dir, ) if os.path.exists( os.path.join(os.path.abspath(tmp_trace_dir), "instrument_data") ): # tar is an instruments trace (old behavior) trace_file = f"{trace_basename}.trace" shutil.copytree(tmp_trace_dir, trace_file) result.append(trace_file) self.logger.info(f"Trace written to {trace_file}") else: # tar is a folder containing one or more trace files for file in os.listdir(tmp_trace_dir): _, file_extension = os.path.splitext(file) tmp_trace_file = os.path.join( os.path.abspath(tmp_trace_dir), file ) trace_file = f"{trace_basename}{file_extension}" shutil.move(tmp_trace_file, trace_file) result.append(trace_file) self.logger.info(f"Trace written to {trace_file}") return result
async def xctrace_record( self, stop: asyncio.Event, # original 'xctrace record' options output: str, template_name: str, all_processes: bool = False, time_limit: Optional[float] = None, package: Optional[str] = None, process_to_attach: Optional[str] = None, process_to_launch: Optional[str] = None, process_env: Optional[Dict[str, str]] = None, launch_args: Optional[List[str]] = None, target_stdin: Optional[str] = None, target_stdout: Optional[str] = None, # FB options post_args: Optional[List[str]] = None, stop_timeout: Optional[float] = None, # control events started: Optional[asyncio.Event] = None, ) -> List[str]: self.logger.info("Starting xctrace connection") async with self.stub.xctrace_record.open() as stream: self.logger.info("Sending xctrace record request") target = None if all_processes: target = XctraceRecordRequest.Target( all_processes=all_processes) elif process_to_attach: target = XctraceRecordRequest.Target( process_to_attach=process_to_attach) else: target = XctraceRecordRequest.Target( launch_process=XctraceRecordRequest.LauchProcess( process_to_launch=process_to_launch, launch_args=launch_args, target_stdin=target_stdin, target_stdout=target_stdout, process_env=process_env, )) await stream.send_message( XctraceRecordRequest(start=XctraceRecordRequest.Start( template_name=template_name, time_limit=time_limit, package=package, target=target, ))) self.logger.info("Starting xctrace record") await xctrace_drain_until_running(stream=stream, logger=self.logger) if started: started.set() self.logger.info("Xctrace record has started, waiting for stop") async for response in stop_wrapper(stream=stream, stop=stop): log = response.log if len(log): self.logger.info(log.decode()) self.logger.info("Stopping xctrace record") await stream.send_message( XctraceRecordRequest(stop=XctraceRecordRequest.Stop( timeout=stop_timeout, args=post_args, ))) await stream.end() result = [] with tempfile.TemporaryDirectory() as tmp_trace_dir: self.logger.info( f"Writing xctrace data from tar to {tmp_trace_dir}") await drain_untar( xctrace_generate_bytes(stream=stream, logger=self.logger), output_path=tmp_trace_dir, ) if os.path.exists( os.path.join(os.path.abspath(tmp_trace_dir), "instrument_data")): trace_file = f"{output}.trace" shutil.copytree(tmp_trace_dir, trace_file) result.append(trace_file) self.logger.info(f"Trace written to {trace_file}") else: # tar is a folder containing one or more trace files for file in os.listdir(tmp_trace_dir): _, file_extension = os.path.splitext(file) tmp_trace_file = os.path.join( os.path.abspath(tmp_trace_dir), file) trace_file = f"{output}{file_extension}" shutil.move(tmp_trace_file, trace_file) result.append(trace_file) self.logger.info(f"Trace written to {trace_file}") return result