Skip to content

Commit 2503762

Browse files
committed
fix: only print progress if totel_jops > 0
1 parent ab71804 commit 2503762

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

ptop.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import time
2+
import argparse
3+
4+
parser = argparse.ArgumentParser(
5+
prog="ptop",
6+
description="Top-like dashboard for GNU Parallel joblog files",
7+
)
8+
9+
parser.add_argument("logfile", help="Path to the log file")
10+
parser.add_argument(
11+
"--total-jobs",
12+
"-tj",
13+
dest="tj",
14+
type=int,
15+
help="The number of jobs in the order",
16+
)
17+
args = parser.parse_args()
18+
tj = args.tj
19+
20+
21+
def clear_console():
22+
print("\033[H\033[J", end="")
23+
24+
25+
def parse(input_line: str) -> dict:
26+
columns = input_line.split()
27+
parsed = {
28+
"seq": int(columns[0]),
29+
"host": columns[1],
30+
"starttime": time.gmtime(float(columns[2])),
31+
"jobRuntime": float(columns[3]),
32+
"send": int(columns[4]),
33+
"receive": int(columns[5]),
34+
"exitval": int(columns[6]),
35+
"signal": int(columns[7]),
36+
"command": " ".join(columns[8:]),
37+
}
38+
return parsed
39+
40+
41+
def progress(lines, total_jops):
42+
return (len(lines) / tj) * 100 if tj else 0
43+
44+
45+
def ascii_progress_bar(percentage, total_jobs, bar_length=50):
46+
if total_jobs > 0:
47+
filled_length = int(bar_length * percentage // 100)
48+
bar = "█" * filled_length + "-" * (bar_length - filled_length)
49+
return f"[{bar}] {percentage:.2f}%"
50+
51+
52+
try:
53+
with open(args.logfile, "r") as file:
54+
lines = []
55+
hosts = {}
56+
file.readline()
57+
58+
while True:
59+
new_lines = file.readlines()
60+
if new_lines:
61+
lines.extend(new_lines)
62+
63+
clear_console()
64+
print(ascii_progress_bar(progress(lines, tj),tj))
65+
print(
66+
"--------------------------------------------------------------"
67+
)
68+
print(
69+
"Host Throughput (jobs/s) Total Successful Failed"
70+
)
71+
print(
72+
"--------------------------------------------------------------"
73+
)
74+
75+
for line in new_lines:
76+
parsed_line = parse(line.replace("\x00", ""))
77+
host = parsed_line["host"]
78+
79+
if host not in hosts:
80+
hosts[host] = {
81+
"jobs": [],
82+
"total": 0,
83+
"successful": 0,
84+
"failed": 0,
85+
}
86+
87+
hosts[host]["jobs"].append(parsed_line)
88+
hosts[host]["total"] += 1
89+
if parsed_line["exitval"] == 0:
90+
hosts[host]["successful"] += 1
91+
else:
92+
hosts[host]["failed"] += 1
93+
94+
throughput_overall = 0
95+
totel_overall = 0
96+
succsessful_overall = 0
97+
failed_overall = 0
98+
99+
for host, stats in hosts.items():
100+
throughput = len(stats["jobs"]) / (
101+
time.mktime(time.gmtime())
102+
- time.mktime(stats["jobs"][0]["starttime"])
103+
)
104+
throughput_overall += throughput
105+
totel_overall += stats["total"]
106+
succsessful_overall += stats["successful"]
107+
failed_overall += stats["failed"]
108+
109+
print(
110+
f"{host:12} {throughput:.2f} {stats['total']:5} {stats['successful']:5} {stats['failed']:5}"
111+
)
112+
113+
print(
114+
"--------------------------------------------------------------"
115+
)
116+
print(
117+
f"{'overall':12} {throughput_overall:.2f} {totel_overall:5} {succsessful_overall:5} {failed_overall:5}"
118+
)
119+
120+
if progress(lines, tj) == 100:
121+
break
122+
123+
time.sleep(1)
124+
except FileNotFoundError:
125+
print(f"Error: The file '{args.logfile}' was not found.")
126+
except IOError as e:
127+
print(f"Error reading the file '{args.logfile}': {e}")
128+
except ZeroDivisionError:
129+
print("Error: Total jobs parameter must be a positive integer.")

0 commit comments

Comments
 (0)