Skip to content
Snippets Groups Projects
graph2.py 4.34 KiB
Newer Older
  • Learn to ignore specific revisions
  • # Copyright 2014 OpenMarket Ltd
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    
    import sqlite3
    import pydot
    import cgi
    import json
    import datetime
    import argparse
    
    from synapse.events import FrozenEvent
    
    from synapse.util.frozenutils import unfreeze
    
    def make_graph(db_name, room_id, file_prefix, limit):
    
        conn = sqlite3.connect(db_name)
    
    
        sql = (
            "SELECT json FROM event_json as j "
            "INNER JOIN events as e ON e.event_id = j.event_id "
            "WHERE j.room_id = ?"
    
        args = [room_id]
    
        if limit:
            sql += (
                " ORDER BY topological_ordering DESC, stream_ordering DESC "
                "LIMIT ?"
            )
    
            args.append(limit)
    
        c = conn.execute(sql, args)
    
    
        events = [FrozenEvent(json.loads(e[0])) for e in c.fetchall()]
    
        events.sort(key=lambda e: e.depth)
    
        node_map = {}
        state_groups = {}
    
        graph = pydot.Dot(graph_name="Test")
    
        for event in events:
            c = conn.execute(
                "SELECT state_group FROM event_to_state_groups "
                "WHERE event_id = ?",
                (event.event_id,)
            )
    
            res = c.fetchone()
            state_group = res[0] if res else None
    
            if state_group is not None:
                state_groups.setdefault(state_group, []).append(event.event_id)
    
            t = datetime.datetime.fromtimestamp(
                float(event.origin_server_ts) / 1000
            ).strftime('%Y-%m-%d %H:%M:%S,%f')
    
    
            content = json.dumps(unfreeze(event.get_dict()["content"]))
    
    
            label = (
                "<"
                "<b>%(name)s </b><br/>"
                "Type: <b>%(type)s </b><br/>"
                "State key: <b>%(state_key)s </b><br/>"
                "Content: <b>%(content)s </b><br/>"
                "Time: <b>%(time)s </b><br/>"
                "Depth: <b>%(depth)s </b><br/>"
                "State group: %(state_group)s<br/>"
                ">"
            ) % {
                "name": event.event_id,
                "type": event.type,
                "state_key": event.get("state_key", None),
                "content": cgi.escape(content, quote=True),
                "time": t,
                "depth": event.depth,
                "state_group": state_group,
            }
    
            node = pydot.Node(
                name=event.event_id,
                label=label,
            )
    
            node_map[event.event_id] = node
            graph.add_node(node)
    
        for event in events:
            for prev_id, _ in event.prev_events:
                try:
                    end_node = node_map[prev_id]
                except:
                    end_node = pydot.Node(
                        name=prev_id,
                        label="<<b>%s</b>>" % (prev_id,),
                    )
    
                    node_map[prev_id] = end_node
                    graph.add_node(end_node)
    
                edge = pydot.Edge(node_map[event.event_id], end_node)
                graph.add_edge(edge)
    
        for group, event_ids in state_groups.items():
            if len(event_ids) <= 1:
                continue
    
            cluster = pydot.Cluster(
                str(group),
                label="<State Group: %s>" % (str(group),)
            )
    
            for event_id in event_ids:
                cluster.add_node(node_map[event_id])
    
            graph.add_subgraph(cluster)
    
        graph.write('%s.dot' % file_prefix, format='raw', prog='dot')
        graph.write_svg("%s.svg" % file_prefix, prog='dot')
    
    if __name__ == "__main__":
        parser = argparse.ArgumentParser(
            description="Generate a PDU graph for a given room by talking "
                        "to the given homeserver to get the list of PDUs. \n"
                        "Requires pydot."
        )
        parser.add_argument(
            "-p", "--prefix", dest="prefix",
    
            help="String to prefix output files with",
            default="graph_output"
        )
        parser.add_argument(
            "-l", "--limit",
            help="Only retrieve the last N events.",
    
        )
        parser.add_argument('db')
        parser.add_argument('room')
    
        args = parser.parse_args()
    
    
        make_graph(args.db, args.room, args.prefix, args.limit)