|
1 | 1 | """Check the frequency of the rebuild loop. |
2 | 2 |
|
3 | | -This must be run in a directory that has the ``docsbuild.log*`` files. |
| 3 | +This must be run in a directory that has the ``docsbuild*`` log files. |
4 | 4 | For example: |
5 | 5 |
|
6 | 6 | .. code-block:: bash |
7 | 7 |
|
8 | 8 | $ mkdir -p docsbuild-logs |
9 | | - $ scp "[email protected]:/var/log/docsbuild/docsbuild.log*" docsbuild-logs/ |
| 9 | + $ scp "[email protected]:/var/log/docsbuild/docsbuild*" docsbuild-logs/ |
10 | 10 | $ python check_times.py |
11 | 11 | """ |
12 | 12 |
|
13 | | -import datetime as dt |
14 | 13 | import gzip |
| 14 | +import tomllib |
15 | 15 | from pathlib import Path |
16 | 16 |
|
17 | 17 | from build_docs import format_seconds |
18 | 18 |
|
19 | 19 | LOGS_ROOT = Path("docsbuild-logs").resolve() |
20 | 20 |
|
21 | 21 |
|
22 | | -def get_lines() -> list[str]: |
| 22 | +def get_lines(filename: str = "docsbuild.log") -> list[str]: |
23 | 23 | lines = [] |
24 | | - zipped_logs = list(LOGS_ROOT.glob("docsbuild.log.*.gz")) |
| 24 | + zipped_logs = list(LOGS_ROOT.glob(f"{filename}.*.gz")) |
25 | 25 | zipped_logs.sort(key=lambda p: int(p.name.split(".")[-2]), reverse=True) |
26 | 26 | for logfile in zipped_logs: |
27 | 27 | with gzip.open(logfile, "rt", encoding="utf-8") as f: |
28 | 28 | lines += f.readlines() |
29 | | - with open(LOGS_ROOT / "docsbuild.log", encoding="utf-8") as f: |
| 29 | + with open(LOGS_ROOT / filename, encoding="utf-8") as f: |
30 | 30 | lines += f.readlines() |
31 | 31 | return lines |
32 | 32 |
|
33 | 33 |
|
34 | 34 | def calc_time(lines: list[str]) -> None: |
35 | | - start = end = language = version = start_timestamp = None |
36 | | - reason = lang_ver = "" |
| 35 | + in_progress = False |
| 36 | + in_progress_line = "" |
37 | 37 |
|
38 | 38 | print("Start | Version | Language | Build | Trigger") |
39 | 39 | print(":-- | :--: | :--: | --: | :--:") |
40 | 40 |
|
41 | 41 | for line in lines: |
42 | 42 | line = line.strip() |
43 | 43 |
|
44 | | - if ": Should rebuild: " in line: |
45 | | - if "no previous state found" in line: |
46 | | - reason = "brand new" |
47 | | - elif "new translations" in line: |
48 | | - reason = "translation" |
49 | | - elif "Doc/ has changed" in line: |
50 | | - reason = "docs" |
51 | | - else: |
52 | | - reason = "" |
53 | | - lang_ver = line.split(" ")[3].removesuffix(":") |
54 | | - |
55 | | - if line.endswith("Build start."): |
56 | | - timestamp = line[:23].replace(",", ".") |
57 | | - language, version = line.split(" ")[3].removesuffix(":").split("/") |
58 | | - start = dt.datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S.%f") |
59 | | - start_timestamp = f"{line[:16]} UTC" |
60 | | - |
61 | | - if start and ": Build done " in line: |
62 | | - timestamp = line[:23].replace(",", ".") |
63 | | - language, version = line.split(" ")[3].removesuffix(":").split("/") |
64 | | - end = dt.datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S.%f") |
65 | | - |
66 | | - if start and end: |
67 | | - duration = (end - start).total_seconds() |
68 | | - fmt_duration = format_seconds(duration) |
69 | | - if lang_ver != f"{language}/{version}": |
70 | | - reason = "" |
| 44 | + if "Saved new rebuild state for" in line: |
| 45 | + _, state = line.split("Saved new rebuild state for", 1) |
| 46 | + key, state_toml = state.strip().split(": ", 1) |
| 47 | + language, version = key.strip("/").split("/", 1) |
| 48 | + state_data = tomllib.loads(f"t = {state_toml}")["t"] |
| 49 | + start = state_data["last_build_start"] |
| 50 | + fmt_duration = format_seconds(state_data["last_build_duration"]) |
| 51 | + reason = state_data["triggered_by"] |
71 | 52 | print( |
72 | | - f"{start_timestamp: <20} | {version: <7} | {language: <8} | {fmt_duration :<14} | {reason}" |
| 53 | + f"{start:%Y-%m-%d %H:%M UTC} | {version: <7} | {language: <8} | {fmt_duration :<14} | {reason}" |
73 | 54 | ) |
74 | | - start = end = start_timestamp = None |
75 | 55 |
|
76 | | - if ": Full build done" in line: |
77 | | - timestamp = f"{line[:16]} UTC" |
78 | | - _, fmt_duration = line.removesuffix(").").split("(") |
79 | | - print( |
80 | | - f"{timestamp: <20} | --FULL- | -BUILD-- | {fmt_duration :<14} | -----------" |
81 | | - ) |
| 56 | + if line.endswith("Build start."): |
| 57 | + in_progress = True |
| 58 | + in_progress_line = line |
| 59 | + |
| 60 | + if in_progress and ": Build done " in line: |
| 61 | + in_progress = False |
82 | 62 |
|
83 | | - if start and end is None: |
| 63 | + if in_progress: |
| 64 | + start_timestamp = f"{in_progress_line[:16]} UTC" |
| 65 | + language, version = in_progress_line.split(" ")[3].removesuffix(":").split("/") |
84 | 66 | print( |
85 | | - f"{start_timestamp: <20} | {version: <7} | {language: <8} | In progress... | {reason}" |
| 67 | + f"{start_timestamp: <20} | {version: <7} | {language: <8} | In progress... | ..." |
86 | 68 | ) |
87 | 69 |
|
| 70 | + print() |
| 71 | + |
88 | 72 |
|
89 | 73 | if __name__ == "__main__": |
90 | | - calc_time(get_lines()) |
| 74 | + print("Build times (HTML only)") |
| 75 | + print("=======================") |
| 76 | + print() |
| 77 | + calc_time(get_lines("docsbuild-only-html.log")) |
| 78 | + |
| 79 | + print("Build times (no HTML)") |
| 80 | + print("=====================") |
| 81 | + print() |
| 82 | + calc_time(get_lines("docsbuild-no-html.log")) |
0 commit comments