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