bc0186d0707dfb77a5b6f8574dcddf3269ff41e7
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
Stefan Schuermans show cpu time and memory in...

Stefan Schuermans authored 4 years ago

104)     PROC_CMDLINE = 3
105)     PROC_CPU_TIME = 4
106)     PROC_MAX_RSS_KB = 5
Stefan Schuermans upt-gui: implement details...

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

218)             self.widProcessesTree.set_value(proc_iter, self.PROC_PROC_ID,
219)                                             proc.proc_id)
220)             self.widProcessesTree.set_value(
221)                 proc_iter, self.PROC_BEGIN,
222)                 timestamp2str(proc.begin_timestamp))
223)             self.widProcessesTree.set_value(proc_iter, self.PROC_END,
224)                                             timestamp2str(proc.end_timestamp))
Stefan Schuermans show cpu time and memory in...

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

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

Stefan Schuermans authored 4 years ago

227)             self.widProcessesTree.set_value(proc_iter, self.PROC_CPU_TIME,
228)                                             duration2str(proc.cpu_time))
229)             self.widProcessesTree.set_value(proc_iter, self.PROC_MAX_RSS_KB,
230)                                             kb2str(proc.max_rss_kb))