diff --git a/awx/main/tasks/receptor.py b/awx/main/tasks/receptor.py index 172d68b2b5b7..02b2cb497be2 100644 --- a/awx/main/tasks/receptor.py +++ b/awx/main/tasks/receptor.py @@ -398,9 +398,11 @@ def _run_internal(self, receptor_ctl): unit_status = receptor_ctl.simple_command(f'work status {self.unit_id}') detail = unit_status.get('Detail', None) state_name = unit_status.get('StateName', None) + stdout_size = unit_status.get('StdoutSize', 0) except Exception: detail = '' state_name = '' + stdout_size = 0 logger.exception(f'An error was encountered while getting status for work unit {self.unit_id}') if 'exceeded quota' in detail: @@ -411,15 +413,23 @@ def _run_internal(self, receptor_ctl): return try: - resultsock = receptor_ctl.get_work_results(self.unit_id, return_sockfile=True) - lines = resultsock.readlines() - receptor_output = b"".join(lines).decode() + receptor_output = '' + if state_name == 'Failed' and self.task.runner_callback.event_ct == 0: + # if receptor work unit failed and no events were emitted, work results may + # contain useful information about why the job failed. In case stdout is + # massive, only ask for last 1000 bytes + startpos = max(stdout_size - 1000, 0) + resultsock = receptor_ctl.get_work_results(self.unit_id, startpos=startpos, return_sockfile=True) + result.setblocking(False) + lines = resultsock.readlines() + receptor_output = b"".join(lines).decode() if receptor_output: self.task.runner_callback.delay_update(result_traceback=receptor_output) elif detail: self.task.runner_callback.delay_update(result_traceback=detail) else: logger.warning(f'No result details or output from {self.task.instance.log_format}, status:\n{state_name}') + except Exception: raise RuntimeError(detail)