Architecture Visualization¶
EventVisualizer generates graphviz diagrams that show the publishers, subscribers, and event connections in your system.
Requirements¶
The graphviz Python package is a core dependency of EventsPype. You also need the Graphviz system binaries:
# macOS
brew install graphviz
# Ubuntu / Debian
sudo apt-get install graphviz
Basic Usage¶
from eventspype import EventVisualizer
visualizer = EventVisualizer()
visualizer.add_publisher(OrderService)
visualizer.add_subscriber(OrderHandler)
# Render to a PNG file (creates "architecture.png")
visualizer.render("architecture", graph_format="png")
Defining Classes for Visualization¶
EventVisualizer works with MultiPublisher and MultiSubscriber subclasses. It reads the class-level EventPublication and EventSubscription attributes to build the diagram automatically.
from dataclasses import dataclass
from eventspype import MultiPublisher, MultiSubscriber, EventPublication, EventSubscription
@dataclass
class OrderPlacedEvent:
order_id: int
@dataclass
class OrderCancelledEvent:
order_id: int
class OrderService(MultiPublisher):
ORDER_PLACED = EventPublication("order_placed", OrderPlacedEvent)
ORDER_CANCELLED = EventPublication("order_cancelled", OrderCancelledEvent)
class OrderHandler(MultiSubscriber):
on_placed = EventSubscription(
publisher_class=OrderService,
event_tag="order_placed",
callback=lambda self, event, tag, caller: None,
)
on_cancelled = EventSubscription(
publisher_class=OrderService,
event_tag="order_cancelled",
callback=lambda self, event, tag, caller: None,
)
Rendering¶
render(output_path, graph_name, graph_format, view)¶
Renders the diagram to a file and returns the output path:
path = visualizer.render(
output_path="docs/architecture", # path without extension
graph_name="OrderSystem", # name shown in the diagram
graph_format="png", # png, pdf, svg, etc.
view=False, # open with system viewer after rendering
)
print(f"Diagram saved to: {path}")
generate_graph(graph_name, graph_format)¶
Returns a graphviz.Digraph object for further customization:
graph = visualizer.generate_graph(graph_name="MySystem", graph_format="svg")
graph.attr(bgcolor="white")
graph.render("custom_output")
Diagram Layout¶
The generated diagram uses a left-to-right layout:
- Publisher nodes (blue boxes) show the class name and all defined
EventPublicationattributes with their tags. - Subscriber nodes (purple boxes) show the class name and all defined
EventSubscriptionattributes with their tags and the source publisher class. - Edges (green arrows) connect publishers to subscribers where the event tags match. The edge label shows the event tag.
Supported Output Formats¶
Any format supported by Graphviz works: png, pdf, svg, dot, jpg, and more.
visualizer.render("output", graph_format="svg")
visualizer.render("output", graph_format="pdf")
Managing the Visualizer¶
# Add multiple publishers and subscribers
visualizer.add_publisher(OrderService)
visualizer.add_publisher(UserService)
visualizer.add_subscriber(OrderHandler)
visualizer.add_subscriber(AuditHandler)
# Clear everything and start over
visualizer.clear()
Complete Example¶
from eventspype import EventVisualizer, MultiPublisher, MultiSubscriber
from eventspype import EventPublication, EventSubscription
from dataclasses import dataclass
import logging
@dataclass
class OrderPlacedEvent:
order_id: int
amount: float
@dataclass
class UserCreatedEvent:
user_id: int
username: str
class OrderService(MultiPublisher):
ORDER_PLACED = EventPublication("order_placed", OrderPlacedEvent)
class UserService(MultiPublisher):
USER_CREATED = EventPublication("user_created", UserCreatedEvent)
class AuditHandler(MultiSubscriber):
on_order = EventSubscription(
publisher_class=OrderService,
event_tag="order_placed",
callback=lambda self, e, t, c: None,
)
on_user = EventSubscription(
publisher_class=UserService,
event_tag="user_created",
callback=lambda self, e, t, c: None,
)
def logger(self) -> logging.Logger:
return logging.getLogger(__name__)
# Visualize
viz = EventVisualizer()
viz.add_publisher(OrderService)
viz.add_publisher(UserService)
viz.add_subscriber(AuditHandler)
viz.render("system_architecture", graph_format="png")