87b12499aea132826f147aca3e08716a30390e1f
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
102)     PROC_BEGIN = 1
103)     PROC_END = 2
104)     PROC_COMMAND = 3
105) 
Stefan Schuermans begin of upt-gui: processes...

Stefan Schuermans authored 4 years ago

106)     def __init__(self, proto_filename):
107)         """
108)         Construct the GUI.
109)         """
110)         self.builder = Gtk.Builder()
111)         script_dir = os.path.dirname(os.path.abspath(__file__))
112)         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

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

154)             detail_iter = self.widDetailsTree.append(parent_iter)
155)             self.widDetailsTree.set_value(detail_iter, self.DETAIL_KEY, key)
156)             self.widDetailsTree.set_value(detail_iter, self.DETAIL_VALUE,
157)                                           value)
158)             return detail_iter
159) 
Stefan Schuermans upt-gui: show parent/children

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

197)     def openTrace(self, proto_filename: str):
198)         """
199)         Open a trace file.
200)         """
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

208)         while to_be_output:
209)             procs, parent_iter = to_be_output[-1]
210)             if not procs:
211)                 del to_be_output[-1]
212)                 continue
213)             proc = procs[0]
214)             del procs[0]
215)             proc_iter = self.widProcessesTree.append(parent_iter)
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

216)             self.widProcessesTree.set_value(proc_iter, self.PROC_PROC_ID,
217)                                             proc.proc_id)
218)             self.widProcessesTree.set_value(
219)                 proc_iter, self.PROC_BEGIN,
220)                 timestamp2str(proc.begin_timestamp))
221)             self.widProcessesTree.set_value(proc_iter, self.PROC_END,
222)                                             timestamp2str(proc.end_timestamp))
223)             self.widProcessesTree.set_value(proc_iter, self.PROC_COMMAND,
224)                                             cmdline2str(proc.cmdline))