Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

138 righe
3.7 KiB

  1. import sqlite3
  2. import pydot
  3. import cgi
  4. import json
  5. import datetime
  6. import argparse
  7. import urllib2
  8. def make_name(pdu_id, origin):
  9. return "%s@%s" % (pdu_id, origin)
  10. def make_graph(pdus, room, filename_prefix):
  11. pdu_map = {}
  12. node_map = {}
  13. origins = set()
  14. colors = set(("red", "green", "blue", "yellow", "purple"))
  15. for pdu in pdus:
  16. origins.add(pdu.get("origin"))
  17. color_map = {color: color for color in colors if color in origins}
  18. colors -= set(color_map.values())
  19. color_map[None] = "black"
  20. for o in origins:
  21. if o in color_map:
  22. continue
  23. try:
  24. c = colors.pop()
  25. color_map[o] = c
  26. except:
  27. print "Run out of colours!"
  28. color_map[o] = "black"
  29. graph = pydot.Dot(graph_name="Test")
  30. for pdu in pdus:
  31. name = make_name(pdu.get("pdu_id"), pdu.get("origin"))
  32. pdu_map[name] = pdu
  33. t = datetime.datetime.fromtimestamp(
  34. float(pdu["ts"]) / 1000
  35. ).strftime('%Y-%m-%d %H:%M:%S,%f')
  36. label = (
  37. "<"
  38. "<b>%(name)s </b><br/>"
  39. "Type: <b>%(type)s </b><br/>"
  40. "State key: <b>%(state_key)s </b><br/>"
  41. "Content: <b>%(content)s </b><br/>"
  42. "Time: <b>%(time)s </b><br/>"
  43. "Depth: <b>%(depth)s </b><br/>"
  44. ">"
  45. ) % {
  46. "name": name,
  47. "type": pdu.get("pdu_type"),
  48. "state_key": pdu.get("state_key"),
  49. "content": cgi.escape(json.dumps(pdu.get("content")), quote=True),
  50. "time": t,
  51. "depth": pdu.get("depth"),
  52. }
  53. node = pydot.Node(
  54. name=name,
  55. label=label,
  56. color=color_map[pdu.get("origin")]
  57. )
  58. node_map[name] = node
  59. graph.add_node(node)
  60. for pdu in pdus:
  61. start_name = make_name(pdu.get("pdu_id"), pdu.get("origin"))
  62. for i, o in pdu.get("prev_pdus", []):
  63. end_name = make_name(i, o)
  64. if end_name not in node_map:
  65. print "%s not in nodes" % end_name
  66. continue
  67. edge = pydot.Edge(node_map[start_name], node_map[end_name])
  68. graph.add_edge(edge)
  69. # Add prev_state edges, if they exist
  70. if pdu.get("prev_state_id") and pdu.get("prev_state_origin"):
  71. prev_state_name = make_name(
  72. pdu.get("prev_state_id"), pdu.get("prev_state_origin")
  73. )
  74. if prev_state_name in node_map:
  75. state_edge = pydot.Edge(
  76. node_map[start_name], node_map[prev_state_name],
  77. style='dotted'
  78. )
  79. graph.add_edge(state_edge)
  80. graph.write('%s.dot' % filename_prefix, format='raw', prog='dot')
  81. graph.write_png("%s.png" % filename_prefix, prog='dot')
  82. graph.write_svg("%s.svg" % filename_prefix, prog='dot')
  83. def get_pdus(host, room):
  84. transaction = json.loads(
  85. urllib2.urlopen(
  86. "http://%s/context/%s/" % (host, room)
  87. ).read()
  88. )
  89. return transaction["pdus"]
  90. if __name__ == "__main__":
  91. parser = argparse.ArgumentParser(
  92. description="Generate a PDU graph for a given room by talking "
  93. "to the given homeserver to get the list of PDUs. \n"
  94. "Requires pydot."
  95. )
  96. parser.add_argument(
  97. "-p", "--prefix", dest="prefix",
  98. help="String to prefix output files with"
  99. )
  100. parser.add_argument('host')
  101. parser.add_argument('room')
  102. args = parser.parse_args()
  103. host = args.host
  104. room = args.room
  105. prefix = args.prefix if args.prefix else "%s_graph" % (room)
  106. pdus = get_pdus(host, room)
  107. make_graph(pdus, room, prefix)