|
1 | 1 | import glob |
2 | 2 | import os |
| 3 | +import re |
3 | 4 | import subprocess |
4 | 5 | import sys |
5 | 6 | import time |
@@ -63,6 +64,38 @@ def _exec_rms(self) -> int: |
63 | 64 | comp_process = subprocess.run(args=args, check=False) |
64 | 65 | return comp_process.returncode |
65 | 66 |
|
| 67 | + def _find_job_failures(self, logfile_path: Path) -> str: |
| 68 | + """Reads through a .log file and returns logs regarding failing jobs. |
| 69 | +
|
| 70 | + Any failure logs must be at the end of the log file as a failing job |
| 71 | + breaks the workflow and will be the last thing that is logged. |
| 72 | +
|
| 73 | + The method first finds the logs for the last job that was started and returns |
| 74 | + the findings as a formatted string if any job failures are found. |
| 75 | + """ |
| 76 | + current_job_line_no = 0 |
| 77 | + |
| 78 | + # Find the line number where the logging of the last job starts |
| 79 | + with open(logfile_path) as logfile: |
| 80 | + for line_no, line in enumerate(logfile, start=1): |
| 81 | + if line.strip().startswith("<pre>"): |
| 82 | + current_job_line_no = line_no |
| 83 | + last_job_line_no = current_job_line_no |
| 84 | + if last_job_line_no == 0: |
| 85 | + return "" |
| 86 | + |
| 87 | + # Collect the logs for the last job and look for failures |
| 88 | + with open(logfile_path) as logfile: |
| 89 | + job_failed_msg = "" |
| 90 | + for line_no, line in enumerate(logfile, start=1): |
| 91 | + if line_no >= last_job_line_no: |
| 92 | + cleaned_text = re.sub(r"<[^>]*>", "", line) |
| 93 | + if cleaned_text != "": |
| 94 | + job_failed_msg += cleaned_text |
| 95 | + # job_failed_msg.removeprefix("\n") |
| 96 | + |
| 97 | + return job_failed_msg if "failed" in job_failed_msg else "" |
| 98 | + |
66 | 99 | def print_failure(self, exit_status: int) -> None: |
67 | 100 | run_path = self.config.run_path.resolve() |
68 | 101 | # Reverse sort so workflow.log is (probably) first and |
@@ -119,6 +152,20 @@ def print_failure(self, exit_status: int) -> None: |
119 | 152 | ) |
120 | 153 | fail_msg += "\n".join([f"* {f}" for f in log_files]) |
121 | 154 |
|
| 155 | + for log_file in log_files: |
| 156 | + try: |
| 157 | + job_failed_msg = self._find_job_failures(run_path / Path(log_file)) |
| 158 | + except Exception: |
| 159 | + job_failed_msg = "" |
| 160 | + if job_failed_msg: |
| 161 | + fail_msg += dedent( |
| 162 | + f""" |
| 163 | + \nThe following logs regarding failed jobs were found in the log file {log_file}:" |
| 164 | + """ |
| 165 | + ) |
| 166 | + fail_msg += job_failed_msg |
| 167 | + break |
| 168 | + |
122 | 169 | print(fail_msg, file=sys.stderr) |
123 | 170 |
|
124 | 171 | @property |
|
0 commit comments