Diagrammen maken met Mermaid
Steeds weer kom ik Mermaid tegen als het gaat om het maken van diagrammen. Persoonlijk werk ik graag met (Plant)uml maar meestal moet ik diagrammen dan exporteren naar een afbeelding voordat ik het in de documentatie kan gebruiken.
Microsoft DevOps heeft ondertussen ondersteuning voor Mermaid , Github heeft nu ondersteuning voor Mermaid en aangezien dat twee platformen zijn die ik veelvuldig gebruik lijkt het me tijd om me eens te gaan verdiepen in Mermaid .
Wat is Mermaid
Mermaid is een tool om diagrammen te maken en te visualiseren door middel van het gebruik van code, gebaseerd op Javascript.
Een simpel voorbeeld van een Mermaid diagram in code:
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
Ziet er zo uit als afbeelding:
Voorbeelden
Op de website van Mermaid staan veel voorbeelden maar niet veel complexe voorbeelden. Ik ga proberen een paar mooie voorbeelden te maken die laten zien wat edMermaid] 1 allemaal kan.
Flowchart
Het is mogelijk om verschillende vormen te gebruiken, zo kun je ook designs van je architectuur maken:
graph TD;
Customer(("Customer"))--Ordering pizzas-->App;
App--Pizza order-->GraphQL_API;
GraphQL_API-->Events(["Events"]);
Events-->OrderMicroservice["Order Microservice"]
OrderMicroservice-->OrderDatabase[("Order Data")]
Events-->RestaurantMicroservice["Restaurant Microservice"]
RestaurantMicroservice-->RestaurantDatabase[("Restaurant Data")]
Events-->DeliveryMicroservice["Delivery Microservice"]
DeliveryMicroservice<-->DeliveryDatabase[("Delivery Data")]
Bovenstaande is wel een beetje misbruik maken van een flowchart, onderstaande is iets meer waar het echt voor bedoeld is:
De mermaid code:
flowchart TD
A(Begin)= =>B[Plan onderhoudsbeurt in] ==> C{Succesvol?}
C- ->|nee|D[Internal Server Error]
D-->E[Opslaan in wachtrij]
E-->F(einde)
C===>|Ja|G[verwerk reservering]
G==>F(einde)
C-->|nee|H[Too Many Requests] --> K{Circuit vaker dan 3x verbroken?}
K-->|Nee|I[Verbreek het circuit]
K-->|Ja|E[Opslaan in wachtrij]
I - -> J[Wacht 30 seconden, retry]
J-->B
State diagram
Ongeveer hetzelfde diagram als hierboven maar nu met het `state diagram`:
stateDiagram-v2
state request_state <<choice>>
state error_state <<choice>>
[*] --> Plan_Onderhoud_In
Plan_Onderhoud_In --> request_state
request_state --> error_state: Fouten
error_state --> Opslaan_In_Wachtrij: InternalServerError
Opslaan_In_Wachtrij --> [*]
error_state --> ErrorHandling: TooManyRequests
request_state --> VerwerkReservering: Succes
VerwerkReservering --> [*]
state ErrorHandling {
state retry_state <<choice>>
[*] --> Retry_Request
Retry_Request --> retry_state
retry_state --> BreakCircuit: broken < 3 times
retry_state --> Opslaan_In_Wachtrij: broken >= 3 times
BreakCircuit --> Wait30Seconds
Wait30Seconds --> Retry_Request
}
Sequence diagram
Hieronder staat een diagram van een mogelijke applicatie. Er is een menu aan toegevoegd, als je met je muis over de actor `Custom Application` gaat zie je twee menu items verschijnen.
sequenceDiagram
autonumber
participant Custom Application
participant Azure AD B2C
participant Azure Api Management
participant Azure Blob Storage
link Custom Application: Wiki @https://google.com/search?q=mermaid+menu
link Custom Application: Source @https://google.com/search?q=mermaid+menu
Custom Application->>Azure AD B2C: authenticate
Azure AD B2C->>Custom Application: token
Azure AD B2C->>Azure Api Management: request new SAS token
Azure Api Management->>Azure AD B2C: newly generated SAS token with expiration time
Azure Api Management->>Custom Application: newly generated SAS token with expiration time
Custom Application->>Azure Blob Storage: upload new file with SAS token
C4 Models
Helaas is het nog niet mogelijk om C4 te gebruiken zoals wel mogelijk is met C4-PlantUML . Nu grotere platformen Mermaid omarmen hoop ik dat hier snel ondersteuning voor komt zodat het visualiseren van een architectuur ook met Mermaid en C4 mogelijk wordt.
Het is overigens niet onmogelijk om dergelijke diagrammen te tekenen, er is alleen geen echte C4 ondersteuning voor. Een voorbeeld van het internet:
(JavaScript/Angular)
Allow customers to manage their profile"]--"Updates customer informationusing
[async, JSON/HTTPS]"-->CustomerService["Customer Service
(Java, Spring Boot)
The point of access for customer information"] CustomerService--"Sends events to
[WebSocket]"-->CustomerApp CustomerService--"Stores data in
[jdbc]"-->CustomerDatabase("Customer Database
(Oracle, 12c)
Stores customer information") CustomerService--"Sends customer update
events to"-->MessageBus MessageBus--"Sends customer update
events to"-->ReportingService MessageBus--"Sends customer update
events to"-->AuditService["Audit Service
[C#,.Net]
Provides organization wide
auditing facilities"] ReportingService["Reporting Service
[Ruby]
Creates normalized data for
reporting purposes"]--"Stores data in"-->ReportingDatabase("Reporting Database
[MySql]
Stores a normalized version
of all business data for
ad hoc reporting purposes") AuditService--"Stores events in"-->AuditStore["Audit Store
[Event store]
Stores information about
events that have happened"] end
test
graph TB
Customer--"Uses (https)"-->CustomerApp("Customer Application")
subgraph "Customer Information (System)"
CustomerApp["Customer Application<br/>(JavaScript/Angular)<br/><br/>Allow customers to manage their profile"]--"Updates customer informationusing<br/>[async, JSON/HTTPS]"-->CustomerService["Customer Service<br/>(Java, Spring Boot)<br/><br/>The point of access for customer information"]
CustomerService--"Sends events to<br/>[WebSocket]"-->CustomerApp
CustomerService--"Stores data in<br/>[jdbc]"-->CustomerDatabase("Customer Database<br/>(Oracle, 12c)<br/><br/>Stores customer information")
CustomerService--"Sends customer update<br/>events to"-->MessageBus
MessageBus--"Sends customer update<br/>events to"-->ReportingService
MessageBus--"Sends customer update<br/>events to"-->AuditService["Audit Service<br/>[C#,.Net]<br/><br/>Provides organization wide<br/>auditing facilities"]
ReportingService["Reporting Service<br/>[Ruby]<br/><br/>Creates normalized data for<br/>reporting purposes"]--"Stores data in"-->ReportingDatabase("Reporting Database<br/>[MySql]<br/><br/>Stores a normalized version<br/>of all business data for<br/>ad hoc reporting purposes")
AuditService--"Stores events in"-->AuditStore["Audit Store<br/>[Event store]<br/><br/>Stores information about<br/>events that have happened"]
end
Styling
Mermaid maakt gebruik van verschillende stijlen. In mijn blog gebruik ik de `default` stijl maar er zijn dus andere mogelijkheden. Daarnaast is het ook nog mogelijk om, met behulp van stylesheets, zelf aanpassingen te doen. Een voorbeeld van een aanpassing:
flowchart LR
id1(Start)-->id2(Stop)
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
Configuration
Mermaid is te configureren in javascript:
mermaid.initialize({
startOnLoad:true,
theme:"default",
flowchart: {
curve: "linear"
}
});
Je kunt deze configuratie ook per diagram doen of een globale configuratie overschrijven. In onderstaande voorbeeld gebruik ik geen rechte maar ronde lijnen voor de en het donkere thema flowchart:
%%{init: {"theme": "dark", "flowchart": { "curve": "basis" }}}%%
flowchart LR
a --> b & c--> d
Zelf uitproberen
Ik moet zelf nog erg wennen aan de syntax en de mogelijkheden van Mermaid. Ik ga er de komende tijd mee aan de slag en waarschijnlijk word ik er dan vanzelf wel beter in. Wil je er zelf ook eens mee spelen? Je kunt makkelijk aan de slag met een online editor zodat je niets hoeft te installeren.
Deel je creaties als je die hebt, misschien kan ik deze post dan uitbreiden met wat meer voorbeelden.