cbb94f1d88bc09f69b250def6d07ba7f7b281525
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

1) #! /usr/bin/env python3
2) 
3) import gi
4) import os
5) import shlex
6) import sys
7) import time
8) gi.require_version('Gtk', '3.0')
9) from gi.repository import Gtk
10) 
11) import uproctrace.processes
12) 
13) 
14) def cmdline2str(cmdline: list) -> str:
15)     """
16)     Convert command line to string.
17)     """
18)     if cmdline is None:
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

19)         return '???'
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

20)     return ' '.join([shlex.quote(s) for s in cmdline])
21) 
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

22) 
23) def duration2str(duration: float) -> str:
24)     """
25)     Convert duration to string.
26)     """
27)     if duration is None:
28)         return '???'
29)     # split into day, hours, minutes, seconds
30)     s = int(duration)
31)     m = s // 60
32)     s = s % 60
33)     h = m // 60
34)     m = m % 60
35)     d = h // 24
36)     h = h % 24
37)     # split into ms, us, ns
38)     ns = int((duration - s) * 1e9)
39)     us = ns // 1000
40)     ns = ns % 1000
41)     ms = us // 1000
42)     us = us % 1000
43)     # assemble text
44)     txt = ''
45)     if d > 0:
46)         txt += f'{d:d} d '
47)     if h > 0 or txt:
48)         txt += f'{h:d} h '
49)     if m > 0 or txt:
50)         txt += f'{m:d} m '
51)     if s > 0 or txt:
52)         txt += f'{s:d} s '
53)     if ms > 0 or txt:
54)         txt += f'{ms:d} ms '
55)     if us > 0 or txt:
56)         txt += f'{us:d} us '
57)     txt += f'{ns:d} ns '
58)     txt += f'({duration:f} s)'
59)     return txt
60) 
61) 
62) def kb2str(kb: int) -> str:
63)     """
64)     Convert size in KiB to string.
65)     """
66)     if kb is None:
67)         return '???'
68)     # split into GiB, MiB, KiB
69)     mib = kb // 1024
70)     kib = kb % 1024
71)     gib = mib // 1024
72)     mib = mib % 1024
73)     # assemble text
74)     txt = ''
75)     if gib > 0:
76)         txt += f'{gib:d} GiB '
77)     if mib > 0 or txt:
78)         txt += f'{mib:d} MiB '
79)     txt += f'{kib:d} KiB '
80)     txt += f'({kb:d} KiB)'
81)     return txt
82) 
83) 
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

84) def timestamp2str(timestamp: float) -> str:
85)     """
86)     Convert a timestamp to a human-reable time string."
87)     """
88)     if timestamp is None:
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

89)         return '???'
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

90)     sec = int(timestamp)
91)     nsec = int((timestamp - sec) * 1e9)
92)     time_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(sec))
93)     return time_str + f'.{nsec:09d}'
94) 
95) 
96) class UptGui:
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

97) 
98)     DETAIL_KEY = 0
99)     DETAIL_VALUE = 1
100)     PROC_PROC_ID = 0
101)     PROC_BEGIN = 1
102)     PROC_END = 2
103)     PROC_COMMAND = 3
104) 
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

105)     def __init__(self, proto_filename):
106)         """
107)         Construct the GUI.
108)         """
109)         self.builder = Gtk.Builder()
110)         script_dir = os.path.dirname(os.path.abspath(__file__))
111)         self.builder.add_from_file(os.path.join(script_dir, 'upt-gui.glade'))
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

112)         self.widDetailsTree = self.builder.get_object('DetailsTree')
113)         self.widDetailsView = self.builder.get_object('DetailsView')
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

114)         self.widProcessesTree = self.builder.get_object('ProcessesTree')
115)         self.widProcessesView = self.builder.get_object('ProcessesView')
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

116)         handlers = {
117)             'onDestroy': self.onDestroy,
118)             'onProcessesCursorChanged': self.onProcessesCursorChanged
119)         }
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

120)         self.builder.connect_signals(handlers)
121)         # open trace file
122)         self.openTrace(proto_filename)
123) 
124)     def onDestroy(self, widget):
125)         """
126)         Window will be destroyed.
127)         """
128)         Gtk.main_quit()
129) 
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

130)     def onProcessesCursorChanged(self, widget):
131)         """
132)         Cursor changed in processes tree view.
133)         """
134)         # get proc_id of selected process
135)         proc_id = None
136)         proc_sel = self.widProcessesView.get_selection()
137)         if proc_sel is not None:
138)             proc_iter = proc_sel.get_selected()[1]
139)             if proc_iter is not None:
140)                 proc_id = self.widProcessesTree.get_value(
141)                     proc_iter, self.PROC_PROC_ID)
142)         # forget old details
143)         self.widDetailsTree.clear()
144)         # leave if no process selected
145)         if proc_id is None:
146)             return
147)         # get process, leave if not found
148)         proc = self.processes.getProcess(proc_id)
149)         if proc is None:
150)             return
151)         # add details of new process
152)         def add(key: str, value: str, parent_iter = None):
153)             detail_iter = self.widDetailsTree.append(parent_iter)
154)             self.widDetailsTree.set_value(detail_iter, self.DETAIL_KEY, key)
155)             self.widDetailsTree.set_value(detail_iter, self.DETAIL_VALUE,
156)                                           value)
157)             return detail_iter
158) 
159)         def add_list(key: str, values: list, parent_iter = None):
160)             if values is None:
161)                 return add(key, '???', parent_iter)
162)             list_iter = add(key, f'{len(values):d} entries', parent_iter)
163)             for i, value in enumerate(values):
164)                 add(f'{key} {i:d}', value, list_iter)
165) 
166)         add('begin time', timestamp2str(proc.begin_timestamp))
167)         add_list('command line', proc.cmdline)
168)         add('CPU time', duration2str(proc.cpu_time))
169)         add('end time', timestamp2str(proc.end_timestamp))
170)         add_list('environment', sorted(proc.environ))
171)         add('executable', proc.exe)
172)         add('max. resident memory', kb2str(proc.max_rss_kb))
173)         add('system CPU time', duration2str(proc.sys_time))
174)         add('user CPU time', duration2str(proc.user_time))
175)         add('working directory', proc.cwd)
176)         # TODO
177) 
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

178)     def openTrace(self, proto_filename: str):
179)         """
180)         Open a trace file.
181)         """
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

182)         # forget old processes
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

183)         self.widProcessesTree.clear()
184)         # lead new data
185)         with open(proto_filename, 'rb') as proto_file:
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

186)             self.processes = uproctrace.processes.Processes(proto_file)
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

187)         # add processes to processes tree store
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

188)         to_be_output = [(self.processes.toplevel, None)]
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

189)         while to_be_output:
190)             procs, parent_iter = to_be_output[-1]
191)             if not procs:
192)                 del to_be_output[-1]
193)                 continue
194)             proc = procs[0]
195)             del procs[0]
196)             proc_iter = self.widProcessesTree.append(parent_iter)
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

197)             self.widProcessesTree.set_value(proc_iter, self.PROC_PROC_ID,
198)                                             proc.proc_id)
199)             self.widProcessesTree.set_value(
200)                 proc_iter, self.PROC_BEGIN,
201)                 timestamp2str(proc.begin_timestamp))
202)             self.widProcessesTree.set_value(proc_iter, self.PROC_END,
203)                                             timestamp2str(proc.end_timestamp))
204)             self.widProcessesTree.set_value(proc_iter, self.PROC_COMMAND,
205)                                             cmdline2str(proc.cmdline))