FSL.Diagram.PlantUML (fsl v0.2.0)

Copy Markdown View Source

Renders a run recorded by FSL.Journal as a PlantUML sequence diagram. The default renderer; FSL.Diagram.Mermaid is the alternative, and an application chooses with FSL.Host.diagram_renderer/0.

A diagram is built from what the instrumentation already collected, which bounds how detailed it can be: command names become outgoing arrows, state transitions become notes, and a transition caused by an event becomes an incoming arrow labelled with the description the machine's author gave it — goto talking, "200 OK" draws an arrow labelled 200 OK.

Three lanes, and which one an event is drawn on

The rule is by exclusion, which is what lets this renderer serve an application it has never heard of:

Event / command typeLane
:mediathe media server
:scenario, :control, :timer, :http, :db, nila note over the local lane
anything else:sip, :matrix, :xmpp, …the peer

Written the other way round — naming the types that go to the peer — an application emitting a type this renderer predates would fall through to the self-note and get a worse diagram for no reason. By exclusion it reproduces today's rendering exactly for every type Elixip emits, and does something sensible for one it has never seen.

What looks like protocol vocabulary in the rules below is naming convention, and generalises for free: send_INVITE → INVITE and media_play → play are prefix rules over command names, and they read send_message → MESSAGE just as well.

Summary

Functions

Build the .puml filename from metadata: <scenario>_<pid>.puml, with the pid sanitized to keep only digits and dots (#PID<0.123.0>0.123.0).

Render the full PlantUML document as a String.

The PlantUML document, under the name it had before renderers were pluggable. render/2 is the callback; this delegates to it, because a document produced by this module is a PlantUML one and calling it so reads better at a call site that chose it deliberately.

Functions

filename(meta)

@spec filename(map()) :: String.t()

Build the .puml filename from metadata: <scenario>_<pid>.puml, with the pid sanitized to keep only digits and dots (#PID<0.123.0>0.123.0).

render(events, meta)

@spec render([map()], map()) :: String.t()

Render the full PlantUML document as a String.

safe_pid(pid_string)

@spec safe_pid(String.t()) :: String.t()

See FSL.Diagram.safe_pid/1.

to_plantuml(events, meta)

@spec to_plantuml([map()], map()) :: String.t()

The PlantUML document, under the name it had before renderers were pluggable. render/2 is the callback; this delegates to it, because a document produced by this module is a PlantUML one and calling it so reads better at a call site that chose it deliberately.