in common_components/monitoring/json_to_dot.py [0:0]
def render_dot(nodes,
left_right=False,
seconds_per_block=1,
fontsize=24,
debug=False):
"""Render graph into a DOT graph
Parameters
----------
nodes : Nodes
Node graph for rendering
left_right : bool
Whether to use left to right or top to bottom for query timelines
seconds_per_block : int
Number of seconds per block size
fontsize : int
Font size for nodes
debug : bool
Whether to produce a DOT graph that is debuggable
"""
start_time = min([v["start_time"] for v in nodes.values() if v["start_time"]])
end_time = max([v["end_time"] for v in nodes.values() if v["end_time"]])
def find_block(time_stamp):
return int(time_stamp - start_time) // seconds_per_block
print("digraph {\n")
print('newrank=true;')
print('compound=true;')
print(f'rankdir="{"LR" if left_right else "TB"}";')
print('ranksep="equally";')
print('overlap="false";')
print(f'node [fontsize={fontsize}, shape = plaintext];')
print('\n/* Timeline */\n')
print('edge [style="invis"];')
for blk in range(find_block(end_time)):
print(f"{blk} -> {blk+1}")
print(f"{blk} [label=\"{get_elapsed_time(blk * seconds_per_block)}\"] ")
print('\n/* Main Styling */\n')
print('edge [style="solid"];')
if debug:
print('node [shape="box"];')
print('\n/* Main Data */\n')
for node_id, node in nodes.items():
print(f"subgraph cluster_{node_id} {{")
print(f' bgcolor="{"red" if "critical" in node else "steelblue1"}"')
print(" style=\"rounded\"")
# Find start and end time block for alignment
start_align = find_block(node["start_time"])
end_align = find_block(node["end_time"]) - 1
if start_align < end_align:
print(f" {node_id}_start [fontsize={fontsize}, label=\"{node['name']}\" width=0]")
print(f" {node_id} [style=\"invis\" label=\"{node['name']}\"]")
else:
print(f" {node_id} [fontsize={fontsize}, label=\"{node['name']}\"]")
print("}")
if start_align < end_align:
print(f"{{ rank=same; {start_align} {node_id}_start }}")
print(f"{{ rank=same; {end_align} {node_id} }}")
else:
print(f"{{ rank=same; {start_align} {node_id} }}")
# Upstream dependencies
for depends in node["depends_on"]:
print(f"{depends} -> {node_id}{'_start' if start_align < end_align else ''} " +
f"[ltail=\"cluster_{depends}\" lhead=\"cluster_{node_id}\"]")
print("}\n")