22 from typing
import List, Dict
23 from graphviz
import Digraph
24 from copy
import deepcopy
25 from req_utils
import *
28 def _graph_add_relations(graph, relations, is_meta=False):
31 schema = [(
"client_id" ,
"client_id" ,
"dix_id" ,
"" ,
"C1"),
32 (
"cas_id" ,
"cas_id" ,
"rpc_id" ,
"cas_to_rpc" ,
"C" ),
33 (
"crpc_id" ,
"crpc_id" ,
"srpc_id" ,
"" ,
"C1"),
34 (
"crpc_id" ,
"rpc_id" ,
"bulk_id" ,
"bulk_to_rpc" ,
"Cs"),
35 (
"srpc_id" ,
"srpc_id" ,
"fom_id" ,
"" ,
"S1"),
36 (
"fom_id" ,
"fom_id" ,
"tx_id" ,
"" ,
"S1"),
37 (
"tx_id" ,
"" ,
"" ,
"" ,
"Sl"),
38 (
"fom_id" ,
"fom_id" ,
"crow_fom_id" ,
"" ,
"S1"),
39 (
"crow_fom_id",
"crow_fom_id",
"crow_tx_id" ,
"" ,
"S1"),
40 (
"crow_tx_id" ,
"" ,
"" ,
"" ,
"Sl")]
44 schema.insert(1, (
"dix_id",
"dix_id",
"mdix_id",
"dix_to_mdix",
"C"))
45 schema.insert(2, (
"mdix_id",
"dix_id",
"cas_id",
"dix_to_cas",
"C"))
47 schema.insert(1, (
"dix_id",
"dix_id",
"cas_id",
"dix_to_cas",
"C"))
51 def graph_build(m_relations, relations, ext_graph: Digraph=
None):
52 graph = ext_graph
if ext_graph
is not None else Digraph(
53 strict=
True, format=
'png', node_attr = {
'shape':
'plaintext'})
56 _graph_add_relations(graph, m_relations,
True)
58 _graph_add_relations(graph, relations)
61 rel = relations
if relations
else m_relations
62 graph.render(filename=
'md_graph_{}'.
format(rel[0][
'client_id']))
72 DISTINCT(cas_to_rpc.rpc_id), 73 client_to_dix.client_id, 78 rpc_to_sxid.xid, rpc_to_sxid.session_id, 79 sxid_to_rpc.xid, sxid_to_rpc.session_id, 80 fom_desc.rpc_sm_id, fom_desc.fom_sm_id, fom_desc.fom_state_sm_id, 81 fom_to_tx.tx_id, tx_to_gr.gr_id, 82 crow_fom_desc.fom_sm_id, crow_fom_desc.fom_state_sm_id, 89 JOIN dix_to_cas on {}=dix_to_cas.dix_id 90 JOIN cas_to_rpc on dix_to_cas.cas_id=cas_to_rpc.cas_id 91 JOIN rpc_to_sxid on cas_to_rpc.rpc_id=rpc_to_sxid.id 92 JOIN sxid_to_rpc on rpc_to_sxid.xid=sxid_to_rpc.xid AND rpc_to_sxid.session_id=sxid_to_rpc.session_id 93 JOIN fom_desc on sxid_to_rpc.id=fom_desc.rpc_sm_id 94 LEFT JOIN fom_to_tx on fom_desc.fom_sm_id=fom_to_tx.fom_id 95 LEFT JOIN tx_to_gr on fom_to_tx.tx_id=tx_to_gr.tx_id 96 LEFT JOIN cas_fom_to_crow_fom on fom_desc.fom_sm_id=cas_fom_to_crow_fom.fom_id 97 LEFT JOIN fom_desc crow_fom_desc on cas_fom_to_crow_fom.crow_fom_id=crow_fom_desc.fom_sm_id 98 LEFT JOIN fom_to_tx crow_fom_to_tx on crow_fom_desc.fom_sm_id=crow_fom_to_tx.fom_id 100 WHERE sxid_to_rpc.opcode in (230,231,232,233) and rpc_to_sxid.opcode in (230,231,232,233) 101 AND rpc_to_sxid.xid > 0 102 AND rpc_to_sxid.session_id > 0 104 AND client_to_dix.pid=dix_to_cas.pid 105 AND client_to_dix.pid=cas_to_rpc.pid AND client_to_dix.pid=rpc_to_sxid.pid 107 AND sxid_to_rpc.pid=fom_desc.pid 108 AND (fom_to_tx.tx_id is NULL OR fom_desc.pid=fom_to_tx.pid) 109 AND (tx_to_gr.gr_id is NULL OR fom_desc.pid=tx_to_gr.pid) 111 AND (crow_fom_desc.fom_sm_id is NULL OR fom_desc.pid=crow_fom_desc.pid) 112 AND (crow_fom_to_tx.tx_id is NULL OR fom_desc.pid=crow_fom_to_tx.pid) 113 AND (tx_to_gr.gr_id is NULL OR fom_desc.pid=tx_to_gr.pid) 115 AND client_to_dix.client_id={}; 119 rpc_fom_s = set([(o[
'cas_id'],
130 o[
'crow_fom_state_id'],
131 o[
'crow_tx_id'])
for o
in relations])
133 for cas_id, opcode, cli_pid, srv_pid, crpc_id, srpc_id, fom_id, fom_state_id, \
134 tx_id, gr_id, crow_fom_id, crow_fom_state_id, crow_tx_id
in rpc_fom_s:
135 cas_req_d =
query2dlist(cas_req.select().where((cas_req.id==cas_id)&
136 (cas_req.pid==cli_pid)))
138 time_table.append(cas_req_d)
140 for tag,(rpc_id,pid)
in {
"c": (crpc_id, cli_pid),
141 "s": (srpc_id, srv_pid)}.items():
142 rpc_req_d =
query2dlist(rpc_req.select().where((rpc_req.id==rpc_id)&
145 time_table.append(rpc_req_d)
147 fom_req_st_d =
query2dlist(fom_req_state.select().where((fom_req_state.id==fom_state_id)&
148 (fom_req_state.pid==srv_pid)))
150 time_table.append(fom_req_st_d)
152 fom_req_d =
query2dlist(fom_req.select().where((fom_req.id==fom_id)&
153 (fom_req.pid==srv_pid)))
155 time_table.append(fom_req_d)
158 be_tx_d =
query2dlist(be_tx.select().where((be_tx.id==tx_id)&
159 (be_tx.pid==srv_pid)))
161 time_table.append(be_tx_d)
166 left =
query2dlist(fom_req.select().where((fom_req.id==gr_id)&
167 (fom_req.pid==srv_pid)&
168 (fom_req.time<client_start_time)).limit(grange[0]))
170 right =
query2dlist(fom_req.select().where((fom_req.id==gr_id)&
171 (fom_req.pid==srv_pid)&
172 (fom_req.time>=client_start_time)).limit(grange[1]))
173 if grange[0]>0
or grange[1]>0:
174 gr_d = [*left, *right]
176 time_table.append(gr_d)
179 crow_fom_req_st_d =
query2dlist(fom_req_state.select().\
180 where((fom_req_state.id==crow_fom_state_id)&
181 (fom_req_state.pid==srv_pid)))
182 times_tag_append(crow_fom_req_st_d,
'op', f
"crow-fom-state {crow_fom_state_id}")
183 time_table.append(crow_fom_req_st_d)
185 crow_fom_req_d =
query2dlist(fom_req.select().where((fom_req.id==crow_fom_id)&
186 (fom_req.pid==srv_pid)))
188 time_table.append(crow_fom_req_d)
191 crow_be_tx_d =
query2dlist(be_tx.select().where((be_tx.id==crow_tx_id)&
192 (be_tx.pid==srv_pid)))
194 time_table.append(crow_be_tx_d)
197 def get_timelines(client_id: str, grange: int, client_pid: int=
None, create_attr_graph: bool=
False,
198 export_only: bool=
False, ext_graph: Digraph=
None):
201 queue_start_time = []
202 client_start_time = 0
205 pid_filter = f
"AND client_to_dix.pid={client_pid}" if client_pid
is not None else "" 206 query = query_gen.format(
"",
"",
"client_to_dix.dix_id", pid_filter, client_id)
207 mquery = query_gen.format(
"dix_to_mdix.mdix_id,",
208 "JOIN dix_to_mdix on client_to_dix.dix_id=dix_to_mdix.dix_id",
209 "dix_to_mdix.mdix_id", pid_filter, client_id)
212 cursor = DB.execute_sql(query)
213 fields =
list(cursor.fetchall())
214 cursor = DB.execute_sql(mquery)
215 m_fields =
list(cursor.fetchall())
216 labels = (
"crpc_id",
"client_id",
"dix_id",
"cas_id",
"opcode",
217 "cxid",
"csess",
"sxid",
"ssess",
"srpc_id",
"fom_id",
218 "fom_state_id",
"tx_id",
"gr_id",
"crow_fom_id",
"crow_fom_state_id",
219 "crow_tx_id",
"cli_pid",
"srv_pid")
220 m_labels = labels[:3] + (
"mdix_id",) + labels[3:]
221 relations = [dict(zip(labels, f))
for f
in fields]
222 m_relations = [dict(zip(m_labels, f))
for f
in m_fields]
227 if not relations
and not m_relations:
228 print(
"Incomplete data for client id {} (pid {})".
format(client_id, client_pid))
231 client_id = set([o[
'client_id']
for o
in relations]).pop()
233 dix_id = set([o[
'dix_id']
for o
in relations]).pop()
235 m_dix_id = set([o[
'mdix_id']
for o
in m_relations]).pop()
238 client_req.select().where(client_req.id==client_id)
if client_pid
is None else 239 client_req.select().where((client_req.id==client_id)&(client_req.pid==client_pid)))
241 time_table.append(client_req_d)
242 client_start_time=
min([t[
'time']
for t
in client_req_d])
246 dix_req.select().where(dix_req.id==dix_id)
if client_pid
is None else 247 dix_req.select().where((dix_req.id==dix_id)&(dix_req.pid==client_pid)))
249 time_table.append(dix_req_d)
253 dix_req.select().where(dix_req.id==m_dix_id)
if client_pid
is None else 254 dix_req.select().where((dix_req.id==m_dix_id)&(dix_req.pid==client_pid)))
256 time_table.append(m_dix_req_d)
268 if create_attr_graph:
269 print(
"Building attributes graph...")
270 attr_graph =
graph_build(m_relations, relations, ext_graph)
272 return time_table, queue_table, queue_start_time, client_start_time, attr_graph
275 parser = argparse.ArgumentParser(prog=sys.argv[0], description=
""" 276 md_req.py: Display significant performance counters for MD Motr stack. 278 parser.add_argument(
"-p",
"--pid", type=int, default=
None,
279 help=
"Client pid to get requests for")
280 parser.add_argument(
"-m",
"--maximize", action=
'store_true', help=
"Display in maximised window")
281 parser.add_argument(
"-q",
"--queues", action=
'store_true', help=
"Display queues also")
282 parser.add_argument(
"-r",
"--qrange", type=int, default=10,
283 help=
"Limit quantity of queue-related samples")
284 parser.add_argument(
"-g",
"--grange", default=[0, 0],
285 nargs=2, metavar=(
'left',
'right'), type=int,
286 help=
"Limit quantity of tx group-related samples")
287 parser.add_argument(
"-a",
"--attr", action=
'store_true', help=
"Create attributes graph")
288 parser.add_argument(
"-v",
"--verbose", action=
'count', default=0)
289 parser.add_argument(
"-u",
"--time-unit", choices=[
'ms',
'us'], default=
'us',
290 help=
"Default time unit")
291 parser.add_argument(
"-d",
"--db", type=str, default=
"m0play.db",
292 help=
"Performance database (m0play.db)")
293 parser.add_argument(
"client_id", type=str, help=
"Client request id")
295 return parser.parse_args()
297 if __name__ ==
'__main__':
303 print(
"Getting timelines...")
305 time_table, queue_table, queue_start_time, client_start_time, _ = \
306 get_timelines(args.client_id, args.grange, args.pid, args.attr,
False)
313 print(
"Plotting timelines...")
315 draw_timelines(time_table, queue_table, client_start_time, queue_start_time,
316 args.time_unit, args.queues, args.maximize)
static struct m0_list list
def prepare_time_table(time_table)
static M0_UNUSED void print(struct m0_be_list *list)
static long long min(long long a, long long b)