1946bf67c87f490f39235e55a5bcf9f04a4237e3
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) 
Stefan Schuermans upt-gui: show parent/children

Stefan Schuermans authored 4 years ago

98)     DETAIL_PROC_ID = 0
99)     DETAIL_KEY = 1
100)     DETAIL_VALUE = 2
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

101)     PROC_PROC_ID = 0
Stefan Schuermans upt-gui: use value (not str...

Stefan Schuermans authored 4 years ago

102)     PROC_BEGIN_TIMESTAMP = 1
103)     PROC_BEGIN_TIMESTAMP_TEXT = 2
104)     PROC_END_TIMESTAMP = 3
105)     PROC_END_TIMESTAMP_TEXT = 4
106)     PROC_CMDLINE = 5
107)     PROC_CPU_TIME = 6
108)     PROC_CPU_TIME_TEXT = 7
109)     PROC_MAX_RSS_KB = 8
110)     PROC_MAX_RSS_KB_TEXT = 9
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

111) 
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

112)     def __init__(self, proto_filename):
113)         """
114)         Construct the GUI.
115)         """
116)         self.builder = Gtk.Builder()
117)         script_dir = os.path.dirname(os.path.abspath(__file__))
118)         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

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

123)         handlers = {
124)             'onDestroy': self.onDestroy,
125)             'onProcessesCursorChanged': self.onProcessesCursorChanged
126)         }
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

127)         self.builder.connect_signals(handlers)
128)         # open trace file
129)         self.openTrace(proto_filename)
130) 
131)     def onDestroy(self, widget):
132)         """
133)         Window will be destroyed.
134)         """
135)         Gtk.main_quit()
136) 
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

137)     def onProcessesCursorChanged(self, widget):
138)         """
139)         Cursor changed in processes tree view.
140)         """
141)         # get proc_id of selected process
142)         proc_id = None
143)         proc_sel = self.widProcessesView.get_selection()
144)         if proc_sel is not None:
145)             proc_iter = proc_sel.get_selected()[1]
146)             if proc_iter is not None:
147)                 proc_id = self.widProcessesTree.get_value(
148)                     proc_iter, self.PROC_PROC_ID)
149)         # forget old details
150)         self.widDetailsTree.clear()
151)         # leave if no process selected
152)         if proc_id is None:
153)             return
154)         # get process, leave if not found
155)         proc = self.processes.getProcess(proc_id)
156)         if proc is None:
157)             return
158)         # add details of new process
Stefan Schuermans upt-gui: show parent/children

Stefan Schuermans authored 4 years ago

159)         def add(key: str, value: str, parent_iter=None):
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

160)             detail_iter = self.widDetailsTree.append(parent_iter)
161)             self.widDetailsTree.set_value(detail_iter, self.DETAIL_KEY, key)
162)             self.widDetailsTree.set_value(detail_iter, self.DETAIL_VALUE,
163)                                           value)
164)             return detail_iter
165) 
Stefan Schuermans upt-gui: show parent/children

Stefan Schuermans authored 4 years ago

166)         def add_list(key: str, values: list, parent_iter=None):
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

167)             if values is None:
168)                 return add(key, '???', parent_iter)
169)             list_iter = add(key, f'{len(values):d} entries', parent_iter)
170)             for i, value in enumerate(values):
171)                 add(f'{key} {i:d}', value, list_iter)
172) 
173)         add('begin time', timestamp2str(proc.begin_timestamp))
174)         add_list('command line', proc.cmdline)
175)         add('CPU time', duration2str(proc.cpu_time))
176)         add('end time', timestamp2str(proc.end_timestamp))
177)         add_list('environment', sorted(proc.environ))
178)         add('executable', proc.exe)
179)         add('max. resident memory', kb2str(proc.max_rss_kb))
180)         add('system CPU time', duration2str(proc.sys_time))
181)         add('user CPU time', duration2str(proc.user_time))
182)         add('working directory', proc.cwd)
Stefan Schuermans upt-gui: show parent/children

Stefan Schuermans authored 4 years ago

183)         # add parent
184)         parent_proc = proc.parent
185)         if parent_proc is None:
186)             add('parent', '???')
187)         else:
188)             parent_iter = add('parent', cmdline2str(parent_proc.cmdline))
189)             self.widDetailsTree.set_value(parent_iter, self.DETAIL_PROC_ID,
190)                                           parent_proc.proc_id)
191)         # add children
192)         child_procs = proc.children
193)         if child_procs is None:
194)             add('children', '???')
195)         else:
196)             list_iter = add('children', f'{len(child_procs):d} entries')
197)             for i, child_proc in enumerate(child_procs):
198)                 child_iter = add(f'child {i:d}',
199)                                  cmdline2str(child_proc.cmdline), list_iter)
200)                 self.widDetailsTree.set_value(child_iter, self.DETAIL_PROC_ID,
201)                                               child_proc.proc_id)
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

202) 
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

203)     def openTrace(self, proto_filename: str):
204)         """
205)         Open a trace file.
206)         """
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

214)         while to_be_output:
215)             procs, parent_iter = to_be_output[-1]
216)             if not procs:
217)                 del to_be_output[-1]
218)                 continue
219)             proc = procs[0]
220)             del procs[0]
221)             proc_iter = self.widProcessesTree.append(parent_iter)
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

222)             self.widProcessesTree.set_value(proc_iter, self.PROC_PROC_ID,
223)                                             proc.proc_id)
Stefan Schuermans upt-gui: use value (not str...

Stefan Schuermans authored 4 years ago

224)             self.widProcessesTree.set_value(proc_iter,
225)                                             self.PROC_BEGIN_TIMESTAMP,
226)                                             proc.begin_timestamp)
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

227)             self.widProcessesTree.set_value(
Stefan Schuermans upt-gui: use value (not str...

Stefan Schuermans authored 4 years ago

228)                 proc_iter, self.PROC_BEGIN_TIMESTAMP_TEXT,
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

229)                 timestamp2str(proc.begin_timestamp))
Stefan Schuermans upt-gui: use value (not str...

Stefan Schuermans authored 4 years ago

230)             self.widProcessesTree.set_value(proc_iter, self.PROC_END_TIMESTAMP,
231)                                             proc.end_timestamp)
232)             self.widProcessesTree.set_value(proc_iter,
233)                                             self.PROC_END_TIMESTAMP_TEXT,
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

234)                                             timestamp2str(proc.end_timestamp))
Stefan Schuermans show cpu time and memory in...

Stefan Schuermans authored 4 years ago

235)             self.widProcessesTree.set_value(proc_iter, self.PROC_CMDLINE,
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

236)                                             cmdline2str(proc.cmdline))
Stefan Schuermans show cpu time and memory in...

Stefan Schuermans authored 4 years ago

237)             self.widProcessesTree.set_value(proc_iter, self.PROC_CPU_TIME,
Stefan Schuermans upt-gui: use value (not str...

Stefan Schuermans authored 4 years ago

238)                                             proc.cpu_time)
239)             self.widProcessesTree.set_value(proc_iter, self.PROC_CPU_TIME_TEXT,
Stefan Schuermans show cpu time and memory in...

Stefan Schuermans authored 4 years ago

240)                                             duration2str(proc.cpu_time))
241)             self.widProcessesTree.set_value(proc_iter, self.PROC_MAX_RSS_KB,
Stefan Schuermans upt-gui: use value (not str...

Stefan Schuermans authored 4 years ago

242)                                             proc.max_rss_kb)
243)             self.widProcessesTree.set_value(proc_iter,
244)                                             self.PROC_MAX_RSS_KB_TEXT,
Stefan Schuermans show cpu time and memory in...

Stefan Schuermans authored 4 years ago

245)                                             kb2str(proc.max_rss_kb))