structurizr / dsl Goto Github PK
View Code? Open in Web Editor NEWStructurizr DSL
Home Page: https://docs.structurizr.com/dsl
License: Apache License 2.0
Structurizr DSL
Home Page: https://docs.structurizr.com/dsl
License: Apache License 2.0
I'm trying to model a system at work that is effectively a system of services built on AWS components. Trying to apply the c4 model to this situations I have:
Context: The system with it's external services (for example email provider) and users
Container: Each of the containers are the individual services that consist within the system (e.g. user management, sign in, asset)
Component: Each container is then broken down into it's components, for example asset management consists of (user gateway (AWS API Gateway), user api Controller (AWS Lambda), service gateway (AWS API Gateway), service api controller (AWS Lambda).
I'd like to be able to create deployment views for each of those components (similar to the AWS example on the website), however, from the documentation it appears that there is only the option for creating an instance for softwaresystem and container.
Am I missing something? or am I completely using the model wrong? or would it be possible to add the ability to create a component instance within the DSL?
Thanks
### deploymentNode
The `deploymentNode` keyword is used to define a deployment node.
deploymentNode <name> [description] [technology] [tags] [instances] {
...
}
I'm struggling to work out how the deploymentNode
keyword should be used and what the concept represents. Some examples of what this represents would be useful, such as those included in the infrastructureNode
documentation.
https://github.com/structurizr/dsl/blob/master/docs/language-reference.md#deploymentnode
The following example retuns a completely empty workspace. Even the comment at the beginning is a valid one, the parser seems not to be able to handle the closing **/
/**
this is a comment
**/
workspace "Getting Started" "This is a model of my software system." {
model {
user = person "User" "A user of my software system."
softwareSystem = softwareSystem "Software System" "My software system."
user -> softwareSystem "Uses"
}
views {
systemContext softwareSystem "SystemContext" "An example of a System Context diagram." {
include *
autoLayout
}
styles {
element "Software System" {
background #1168bd
color #ffffff
}
element "Person" {
shape person
background #08427b
color #ffffff
}
}
}
}
Nowadays structurizr allows creating groups of elements, but with some limitations:
It would be great if we remove these limitations, allowing creating views like this:
In case you think there is another recommended to get it, please let me know. Thanks!
The documentation describes that relations
Software System Instance
to Infrastructure Node, Software System Instance, Container Instance
Container Instance
to Infrastructure Node, Software System Instance, Container Instance
are allowed. However, when creating any relation between ContainerInstance or SoftwareSystemInstance to one of the other elemens listed as valid, I get an error message that the relation is not allowed.
At a first glance the problem seems to be burried in AbstractRelationshipParser.java which IMHO doesn't include if conditions to allow the relations listed above.
Example:
workspace "Getting Started" "This is a model of my software system." {
model {
ss1 = softwareSystem "Software System" "My software system." {
cont1 = container "Container" "Container"
}
ss2 = softwareSystem "Software System 2" ""
deploymentEnvironment "deploytest" {
deploymentNode wrapper "Wrapper" "Wrapper" {
ssinstance = softwareSystemInstance ss2
}
deploymentNode wrapper2 "Wrapper2" "Wrapper" {
continst = containerInstance cont1
continst -> ssinstance "connects" ""
}
}
}
views {
deployment * deploytest deploytest "test" {
include *
}
}
}
Error Message:
A relationship between "ContainerInstance://deploytest/wrapper2/Software System.Container[1]" and "SoftwareSystemInstance://deploytest/wrapper/Software System 2[1]" is not permitted at line 22: continst -> ssinstance "connects" ""
The following DSL does not output any relations for Deployment - production
:
workspace "Example" "bla bla" {
model {
enterprise "Ent" {
studio = softwaresystem "Studio" "bla" {
this_api = container "This API" "Pairing and heartbeat" "REST"
that_api = container "That API" "" "GraphQL"
}
player = softwareSystem "Player" "bla bla"
}
google = softwareSystem "GCP" {
firestore = container "Firestore" "" "" "Google Cloud Platform - Cloud Firestore"
}
cdn = softwareSystem "CDN" "Cloudflare"
aws = softwareSystem "AWS" {
redis = container "Cache" "Redis"
postgres = container "Database" "PostgreSQL" ""
}
deploymentEnvironment "production" {
deploymentNode "AWS" "" "" "Amazon Web Services - Cloud" {
deploymentNode "US-East-1" "" "" "Amazon Web Services - Region" {
deploymentNode "EC2" "" "" "Amazon Web Services - EC2" {
this_api_instance = containerInstance this_api
that_api_instance = containerInstance that_api
}
deploymentNode "RDS" "" "" "Amazon Web Services - RDS PostgreSQL instance" {
postgres_instance = containerInstance postgres
}
deploymentNode "Redis" "" "" "Amazon Web Services - ElastiCache For Redis" {
redis_instance = containerInstance redis
}
}
}
}
that_api -> postgres "Reads and writes"
player -> this_api "Reads and writes (pairing)"
player -> that_api "Reads and writes (content)"
}
views {
systemContext "studio" {
include *
autoLayout
}
container "studio" {
include *
autoLayout
}
container "google" {
include *
autoLayout
}
deployment studio "production" {
include *
autolayout lr
}
themes default https://static.structurizr.com/themes/amazon-web-services-2020.04.30/theme.json
}
}
Here is the generated IDL:
resources:
- id: "1"
name: "Studio"
subtitle: "[Software System]"
description: "bla"
backgroundColor: "#1168bd"
color: "#ffffff"
children:
- id: "2"
name: "This API"
subtitle: "[Container: REST]"
description: "Pairing and heartbeat"
backgroundColor: "#438dd5"
color: "#ffffff"
- id: "3"
name: "That API"
subtitle: "[Container: GraphQL]"
backgroundColor: "#438dd5"
color: "#ffffff"
- id: "4"
name: "Player"
subtitle: "[Software System]"
description: "bla bla"
backgroundColor: "#1168bd"
color: "#ffffff"
- id: "5"
name: "GCP"
subtitle: "[Software System]"
backgroundColor: "#1168bd"
color: "#ffffff"
children:
- id: "6"
name: "Firestore"
subtitle: "[Container]"
backgroundColor: "#438dd5"
color: "#ffffff"
- id: "7"
name: "CDN"
subtitle: "[Software System]"
description: "Cloudflare"
backgroundColor: "#1168bd"
color: "#ffffff"
- id: "8"
name: "AWS"
subtitle: "[Software System]"
backgroundColor: "#1168bd"
color: "#ffffff"
children:
- id: "10"
name: "Content database"
subtitle: "[Container]"
description: "PostgreSQL"
backgroundColor: "#438dd5"
color: "#ffffff"
- id: "9"
name: "Cache"
subtitle: "[Container]"
description: "Redis"
backgroundColor: "#438dd5"
color: "#ffffff"
- id: "11"
name: "AWS"
subtitle: "[Deployment Node]"
backgroundColor: "#ffffff"
color: "#232f3e"
children:
- id: "12"
name: "US-East-1"
subtitle: "[Deployment Node]"
backgroundColor: "#ffffff"
color: "#147eba"
children:
- id: "13"
name: "EC2"
subtitle: "[Deployment Node]"
backgroundColor: "#ffffff"
color: "#d86613"
children:
- id: "14"
name: "This API"
subtitle: "[Container: REST]"
description: "Pairing and heartbeat"
backgroundColor: "#438dd5"
color: "#ffffff"
- id: "15"
name: "That API"
subtitle: "[Container: GraphQL]"
backgroundColor: "#438dd5"
color: "#ffffff"
- id: "16"
name: "RDS"
subtitle: "[Deployment Node]"
backgroundColor: "#ffffff"
color: "#3b48cc"
children:
- id: "17"
name: "Content database"
subtitle: "[Container]"
description: "PostgreSQL"
backgroundColor: "#438dd5"
color: "#ffffff"
- id: "18"
name: "Redis"
subtitle: "[Deployment Node]"
backgroundColor: "#ffffff"
color: "#3b48cc"
children:
- id: "19"
name: "Cache"
subtitle: "[Container]"
description: "Redis"
backgroundColor: "#438dd5"
color: "#ffffff"
perspectives:
- name: Static Structure
relations:
- from: "1"
to: "8"
label: "Reads and writes"
- from: "4"
to: "1"
label: "Reads and writes (pairing)"
- from: "1"
to: "10"
label: "Reads and writes"
- from: "3"
to: "10"
label: "Reads and writes"
- from: "3"
to: "8"
label: "Reads and writes"
- from: "4"
to: "2"
label: "Reads and writes (pairing)"
- from: "4"
to: "3"
label: "Reads and writes (content)"
- name: Deployment - production
relations:
Hello,
I tried to generate a deployment diagram but I had to disable autoLayout to be able to get it as expected. I created a sample DSL code to help me on explaining the issue so you can also reproduce it.
I have a container diagram like this (see #All_Containers):
So, as a summary, a mobile app calls to multiple APIs through an API Gateway. The APIs have integration with database and 3rd party APIs.
For creating the deployment diagram, I added a the API Gateway as an infrastructure node, and enabled relationships between mobile app -> api gw -> apis. On the other hand, I represented a deployment of the APIs in multiple regions.
In the first try, I got the following diagram (See #All_Deployment_1):
That deployment diagram was confusing, as it included all relationships, when some of them are not valid from deployment point of view. e.g., API 1 deployed to US is not connected to the database in EU. On the other hand, once I introduce the API Gateway into the diagram, the direct relationship between mobile app and APIs must be hidden.
I've been able to implement the expected diagram using the feature that allows including/excluding especific relationships (See: #All_Deployment_2):
However, I had to disable autoLayout and manually distribute the elements in the diagram. If I enable autoLayout, I get the following diagram:
I would like to use the autolayout feature, as I do for other diagrams. I would appreciate if you can improve it to allow autolaout in that scenario.
Please let me know if I doing something wrong or I should I take a different approch to generate the deployment diagram as expected.
Thanks for your support.
Sample DSL:
workspace "Amazon Web Services Example" "An example AWS deployment architecture." {
model {
springPetClinic = softwaresystem "Spring PetClinic" "Allows employees to view and manage information regarding the veterinarians, the clients, and their pets." "Spring Boot Application" {
app = container "Mobile App" "Show information regarding the veterinarians, the clients, and their pets." "android" "Mobile App"
api1 = container "API 1" "API 2" "Java and Spring Boot"
api2 = container "API 2" "API 2" "Java and Spring Boot"
database = container "Database" "Stores information regarding the veterinarians, the clients, and their pets." "Relational database schema" "Database"
}
thirdPartyApi1 = softwaresystem "Third-Party API 1"
thirdPartyApi2 = softwaresystem "Third-Party API 2"
app -> api1 "manages data" "AWS API Gateway"
app -> api2 "manages data" "AWS API Gateway"
api1 -> database "Reads from and writes to" "JDBC/SSL"
api1 -> thirdPartyApi1 "Get 3rd pary data" "HTTP"
api2 -> thirdPartyApi2 "Get 3rd pary data" "HTTP"
deploymentEnvironment "Live" {
mobilePhone = deploymentNode "Customer's mobile device" "" "Android" {
appInstance = containerInstance app
}
deploymentNode "Amazon Web Services" "" "" "Amazon Web Services - Cloud" {
apiGw = deploymentNode "API Gateway" "" "" "Amazon Web Services - API Gateway" {
infrastructureNode "API Gateway" "" "" "Amazon Web Services - API Gateway Endpoint"
}
deploymentNode "US-East-1" "" "" "Amazon Web Services - Region" {
apiUsGroup = deploymentNode "Autoscaling group" "" "" "Amazon Web Services - Auto Scaling" {
api1UsDeploymentNode = deploymentNode "Amazon EC2 - API 1" "" "" "Amazon Web Services - EC2" {
containerInstance api1
}
api2UsDeploymentNode = deploymentNode "Amazon EC2 - API 2" "" "" "Amazon Web Services - EC2" {
containerInstance api2
}
}
rdsUs = deploymentNode "Amazon RDS" "" "" "Amazon Web Services - RDS" {
deploymentNode "MySQL" "" "" "Amazon Web Services - RDS_MySQL_instance" {
containerInstance database
}
}
}
deploymentNode "EU-West-1" "" "" "Amazon Web Services - Region" {
apiEuGroup = deploymentNode "Autoscaling group" "" "" "Amazon Web Services - Auto Scaling" {
api1EuDeploymentNode = deploymentNode "Amazon EC2 - API 1" "" "" "Amazon Web Services - EC2" {
containerInstance api1
}
api2EuDeploymentNode = deploymentNode "Amazon EC2 - API 2" "" "" "Amazon Web Services - EC2" {
containerInstance api2
}
}
rdsEu = deploymentNode "Amazon RDS" "" "" "Amazon Web Services - RDS" {
deploymentNode "MySQL" "" "" "Amazon Web Services - RDS_MySQL_instance" {
containerInstance database
}
}
}
}
thirdPartyInfra = deploymentNode "3rd party infrastructure" {
softwareSystemInstance thirdPartyApi1
softwareSystemInstance thirdPartyApi2
}
mobilePhone -> apiGw
apiGw -> apiUsGroup "Forwards requests to" "HTTPS"
apiGw -> apiEuGroup "Forwards requests to" "HTTPS"
api1UsDeploymentNode -> rdsUs
api1UsDeploymentNode -> thirdPartyInfra
api2UsDeploymentNode -> thirdPartyInfra
api1EuDeploymentNode -> rdsEu
api1EuDeploymentNode -> thirdPartyInfra
api2EuDeploymentNode -> thirdPartyInfra
}
}
views {
container springPetClinic "All_Containers" {
include *
autoLayout
}
deployment springPetClinic "Live" "All_Deployment_1" {
include *
autoLayout
}
deployment springPetClinic "Live" "All_Deployment_2" {
include *
exclude * -> *
include mobilePhone -> *
include apiGw -> *
include api1UsDeploymentNode -> *
include api2UsDeploymentNode -> *
include api1EuDeploymentNode -> *
include api2EuDeploymentNode -> *
//autoLayout
}
styles {
element "Element" {
shape roundedbox
background "#ffffff"
}
element "Database" {
shape cylinder
}
element "Mobile App" {
shape MobileDeviceLandscape
}
element "Infrastructure Node" {
shape roundedbox
}
}
themes https://static.structurizr.com/themes/amazon-web-services-2020.04.30/theme.json
}
}
External systems are styled the same way like internal systems.
Looking at the generated puml file the external systems are defined as regular "system" items although it should be "external_system".
I am using 1.8.1.
Hi there,
is it possible to include and exclude objects by tag? I just want to separate some elements of a context diagram into grouped items and create additional diagrams. Documentation says we can include/exclude only by name and it looks a bit tedious if we have 2-3 or more groups.
Is there a better way?
views {
systemContext System "SystemContext" "System Context diagram." {
include *
# exclude Grouped systems
exclude System1 System2 System3
# exclude Grouped relationships
exclude rel_System1 rel_System2 rel_System3
autoLayout
}
systemContext Grouped "Group1" "System Context diagram." {
# include Grouped systems
include System1 System2 System3
# exclude relationship to Group
exclude rel_to_Grouped
autoLayout
}
I am currently in the process of modeling a backend system using the structurizr dsl. One part includes defining our different deployment environment which also differ in regards of scaling the services. A lot of our services are not static but instead have autoscaling implemented. However, I haven't found a good way to model this in the dsl.
Example how I modeled one of our services in a deployment environment:
model {
deploymentEnvironment production {
deploymentNode "My scalable service" "This service scales based on load" "Kubernetes Deployment" "2" {
containerInstance myJavaApplication
containerInstance istio
}
}
}
Intuitively, I wanted to assign a value range, e.g. "2-10" to the last parameter of the deploymentNode
field. However, structurizr-cli
errors telling me that parameter only accepts numbers as a value.
Are there any suitable options to express the autoscaling of a service in the dsl? if not, would this be a viable feature to support?
Also [componenet]
There are missing dependencies, when building the project with gradle, like:
import com.structurizr.documentation.AdrToolsImporter;
^
symbol: class AdrToolsImporter
location: package com.structurizr.documentation
C:\development\projects\dsl\src\main\java\com\structurizr\dsl\AdrsParser.java:39: error: cannot find symbol
AdrToolsImporter adrToolsImporter = new AdrToolsImporter(workspace, path);
^
According to the documentation in Language reference, the element styles are defined using tags as identifiers (see element style). Although this is true, in my opinion documentation should specify that elements have predefined tags (e.g. Element and Person for persons).
I can create a pull request to add this information if you think it can improve the documentation.
Is it possible to autosize the diagrams to the size of the display?
Hello,
I've created a deployment diagram like this:
deployment myAppSystem "Live" "LiveDeployment" {
include deploymentNode1 deploymentNode2
exclude deploymentNode3
exclude relationship
autoLayout
}
So, I want the diagram to include some deployments nodes but hide others. Additionally, I want a relationship between some containers to be hidden.
As a result, I see the deployment nodes are shown as expected, but the relationship between containers is not excluded. Not sure if it also happens with relationship between systems.
It would be great if you can find a way to fix it.
Thank you,
Juan
I'm trying to give a tagged deployment node a specific color/icon. The definition of the deployment node is as follows:
hermesNode = deploymentNode "Hermes Instance" "Instance of Hermes" "Docker Container" "DOCKER" {
deploymentNode "OpenJDK 11" "" "OpenJDK 11" "JAVA" {
containerInstance hermes
}
}
The definition of the tag is as follows:
element "DOCKER" {
icon images/docker.png
background #007bff
}
When i look at the generated image for the deployment the tagged deployment node has no color while the icon is there.
Are there any plans/requests to add support for URLs to the !include
capabilities?
I'm modeling a rather large workspace and many of the grouped software systems themselves reside in separate repos with their own models defined as a .dsl
, rather than just allowing !include
to reference local relative paths, it would be nice to point them to a raw github link or something (assuming auth could be a problem here if they are not public)
there are ways we can do some of this via build scripts if needed, but it makes validating and testing the model a little more painful
I really like the default styling when exporting a dsl file to structurizr plantuml format. What I would like to do now is to easily add icons for certain element types (tags) but keep the rest. Using styles and the themes (did not try it yet) I can easily add icons and other style information.
But when styles is being used in a dsl then automatically all styling is gone/reset. My proposal would be that there should be a switch whether using styles in a dsl resets the complete styling or the given default styles should just override the specific style settings.
As a workaround getting the complete default styling to be added to the dsl and changing it where required would also be fine.
I created this theme
https://structurizr.com/help/theme?url=https://raw.githubusercontent.com/luizfbicalho/structurizr/master/theme/alpargatas.json
and when I display shows a broken image
At the moment the dynamic view always resolves to a single sequence of activities.
But some flows are more than just a sequence of steps but also includes parallel steps.
It would be very nice if parallel activities (two or three times a 1. or 3.) could be defined too.
Hello,
I tried to generate some filtered views based on tags for a more complex view. Even though the elements are filtered properly, the diagram generated with autoLayout doesn't look good: looks like it firstly generate the complex diagram with all elements with autolayout, and then show/hide the elements with the specified tags. As a result, the elements are not distributed properly. I would like to first filter elements and then apply the autolayout, so the diagram would look better.
I created a sample DSL code to help me on explaining the issue so you can also reproduce it.
I have a container diagram like this (see #All_Containers):
Then I create two filtered views, generating the following diagrams:
I would like them to be generated in this way:
#All_Containers_tag1_expectation:
#All_Containers_tag2_expectation:
If there is any way to achive my goal, let me know.
Thanks for your support.
Sample DSL:
workspace "Amazon Web Services Example" "An example AWS deployment architecture." {
model {
springPetClinic = softwaresystem "Spring PetClinic" "Allows employees to view and manage information regarding the veterinarians, the clients, and their pets." "Spring Boot Application"{
app = container "Mobile App" "Show information regarding the veterinarians, the clients, and their pets." "android" "Mobile App, tag1, tag2"
api1 = container "API 1" "API 2" "Java and Spring Boot" "tag1"
api2 = container "API 2" "API 2" "Java and Spring Boot" "tag2"
database = container "Database" "Stores information regarding the veterinarians, the clients, and their pets." "Relational database schema" "Database, tag1"
}
thirdPartyApi1 = softwaresystem "Third-Party API 1" "" "tag1"
thirdPartyApi2 = softwaresystem "Third-Party API 2" "" "tag2"
app -> api1 "manages data" "AWS API Gateway" "tag1"
app -> api2 "manages data" "AWS API Gateway" "tag2"
api1 -> database "Reads from and writes to" "JDBC/SSL" "tag1"
api1 -> thirdPartyApi1 "Get 3rd pary data" "HTTP" "tag1"
api2 -> thirdPartyApi2 "Get 3rd pary data" "HTTP" "tag2"
}
views {
container springPetClinic "All_Containers" {
include *
autoLayout
}
container springPetClinic "All_Containers_tag1_expectation" {
include app api1 database thirdPartyApi1
autoLayout
}
container springPetClinic "All_Containers_tag2_expectation" {
include app api2 thirdPartyApi2
autoLayout
}
filtered All_Containers include "tag1, tag2" "All_Containers_tag1_tag2"
filtered All_Containers include "tag1" "All_Containers_tag1"
filtered All_Containers include "tag2" "All_Containers_tag2"
styles {
element "Element" {
shape roundedbox
background "#ffffff"
}
element "Database" {
shape cylinder
}
element "Mobile App" {
shape MobileDeviceLandscape
}
element "Infrastructure Node" {
shape roundedbox
}
}
themes https://static.structurizr.com/themes/amazon-web-services-2020.04.30/theme.json
}
}
I'm having the error
Sorry, something went wrong.
in the url
https://structurizr.com/dsl
looks like is something wrong with the theme, but there is no explanation,
I open the theme correctly on the theme help
One problem found is the theme value is case sensitive
"routing" :"Direct" is OK but "routing" :"direct" gives the error
The language reference does not seem to specify it, and the examples at https://structurizr.com/dsl only have elements with 0..1 tags.
We have systems with very few but very big containers (Eclipse IDE client application). Such a container consists of a few high level components which itself contain (sub-)components on its own (sometimes even one more component layer) until finally the code layer is reached.
It would be very helpful if the dsl and finally then also the cli and structurizr server would support multiple layers of components.
That means when defining views in the dsl it would be very helpful if only the directly contained elements are shown, that means the component view only shows the top level components of the given container. For lower component layers it would be nice if the "parent" component could be given as the context for the view.
Hi,
This is a couple of suggestions for the DSL Language Reference (dsl/blob/docs/language-reference.md).
It seems like there are locations within the DSL structure where you aren't allowed to place relationships. For example. you can put a relationship within a DeploymentEnvironment, but not within a DeploymentNode.
Would it be possible to add that to the language reference, perhaps in the "relationship" section?
Also, is there a restriction on which two element types are allowed a relationship between them?
I managed to trigger the below error when making a relationship from a deploymentNode to a containerInstance:
(
).Perhaps you could document which elements are allowed to have relationships between each other?
Cheers!
Kirk
Hi there,
I just try to start working with structurize but noticed that I can only define relationships on model level. I expected to be able to create something like this:
container myContainer {
dummyView = component "View"
dummyViewModel = component "View Model"
dummyView-> dummyViewModel
}
If there are good modelling reasons for only allowing relationships on model-level, I appologize for asking this question. To me it seems strange that I have to define relationships within one component or a container outside of it.
Thanks in advance for your help and best regards, Jan
Relationships have semantics, the DSL doesn't have keywords for line ends (none, arrow, filled and unfilled circle, filled and unfilled triangle, filled and unfilled diamond) that are needed to show semantics like inheritance, aggregation, composition, etc.
(See https://www.visual-paradigm.com/guide/uml-unified-modeling-language/uml-class-diagram-tutorial/).
We recently converted from code to the DSL.
It seems there may be different behaviour when defining multiple relationships between the same elements.
For example for the DSL:
"a" -> "b" "text 1"
"a" -> "b" "text 2"
For the DSL this only draws a single line, with the first explanation, so text 1
.
In code multiple lines would be drawn. (We used the Java client.)
Not sure if this is a bug or a feature of the DSL but we used these definitions regularly.
We can work around it by combining all texts on a single relationship but first feel is it more arrows is more clear than more text on single relationship.
Please fix this
[<identifier> = ]softwareSystem = softwareSystem <name> [description] [tags] {
it should really read as
[<identifier> = ] softwareSystem <name> [description] [tags] {
I've noticed an inconsistency between the language reference and the Big Bank PLC example. The example has a relationship (primaryDatabaseServer -> secondaryDatabaseServer "Replicates data to"
) within a deploymentEnvironment
where this is not supported according to the language reference.
Could one or other be updated so they match please?
Add support for defining constants, to prevent values from being repeated (e.g. deployment environment names, tags, etc).
I am still working on a VS Code extension and completing a corresponding Xtext Grammar for the DSL.
The !include feature is not yet implemented, but I want to do that soon.
Are there any rules/conventions what kind of model elements/fragments can be outsourced into files, which then can be imported with the !include keyword?
I found the one example
user = person "User" "A user of my software system."
softwareSystem = softwareSystem "Software System" "My software system."
user -> softwareSystem "Uses"
Is that the complete list? Persons, Software Systems (and sub-elements) and Relationships ?
Thanks,
Torsten
I can't quite figure out how to use structurizr
Using the cloud version, there's a demo editor which I can use and render images. The weirdness about this editor is that it's not tied to my workspace, so I need copy-paste my DSL and save it into files locally. This works, but seems to be a terribly UX. It's only a matter of time before I end up losing information with poor copy-pasting.
Via my personal workspace, there seems to be no way to edit DSL. If there is, I can't figure out how to it. So it can render, but I can't type anywhere.
Using the CLI I can convert my DSL into various other formats, but not into an image file. It seems that you guys use graphviz to render the image, but the CLI cannot export to graphviz.
I can use the CLI to upload my DSL, but that's a dead end. I then have to log into the website, and navigate my way around onto the image. For each change I make, I need to re-do the whole round trip (and this is certainly something not scriptable). Each change I make, I need to:
So far, it seems that just using the demo editor and copy-pasting is the best way to use structurizr (which is weird, since it makes all the paid features entirely irrelevant). Am I missing something here?
Hello,
It would be a great productivity improvement, and may be a better adoption incentive of structurizr for the ones using Jetbrains IDEs such as IntelliJ to have an integration as for what has been done for VSCode.
What do you think about it ?
Thank you,
Any property containing "
ends up producing the error message com.structurizr.dsl.StructurizrDslParserException: Expected: <name> <value> at line 10: myproperty "This is an \"example\""
Example:
properties {
myproperty "This is an \"example\""
}
We need a way to escape double quotes. A backslash does obviously not work currently.
Background: We use properties to attach structured data (JSON format) to model elements. JSON requires to use doublequotes for fields.
I have a system with slightly different component based on the deployed configuration.
Depending on the configuration certain component may lose responsibilities that I want to illustrate with relationship.
Is it possible to exclude a relationship from a view?
workspace {
model {
mySystem = softwareSystem "My system" {
componentA = container "A"
componentB = container "B"
}
otherSystem = softwareSystem "The other system"
componentA -> componentB "Do it for me"
componentB -> otherSystem "Do it"
componentA -> otherSystem "No B i'll do it myself"
}
views {
container mySystem "ConfigurationA" {
include *
# Error The element/relationship "->" does not exist at line 20: exclude componentA -> otherSystem
# exclude componentA -> otherSystem
autoLayout
}
container mySystem "ConfigurationB" {
include *
exclude componentB
autoLayout
}
}
}
Within the DSL there is the option to define properties for a container/component/etc. How can these be used within the documentation and/or diagrams?
It would be really useful to have another level between SoftwareSystem and Container. For example, a set of Containers could work in concert to provide a service to the Software System. Within a SoftwareSystem, Groups almost work like this, but you can't seem to address them to, say, exclude them from a View.
Follow Up on #7
We're currently evaluating to use the DSL to hold our documentation as code. Furthermore we thought that we will get rid of this auto add relations to all views where the appropriate components are in feature. Unfortunately, this was a false positive.
After some readings in the implementation, we found out, that it might be easy to add an opt out for this feature into the DSL. The underlying java-client do already implement the necessary part for it in it's API. So, something like this should be possible:
workspace {
model {
user = person "User" "A user of my software system."
softwareSystem = softwareSystem "Software System" "My software system."
softwareSystem2 = softwareSystem "Software System2" "My software system."
softwareSystem3 = softwareSystem "Software System3" "My software system."
uss = user -> softwareSystem "Uses"
uss2 = user -> softwareSystem2 "Uses"
uss3 = user -> softwareSystem3 "Uses"
ss2ss3 = softwareSystem2 -> softwareSystem3 "Uses"
}
views {
systemContext softwareSystem {
# opt out
disableAutoAddRelations
include user softwareSystem2 uss uss2
autoLayout
}
}
}
Do you thing that this makes sense?
So, what is actually our need here. We want to document a big system, which does not really have a clean architecture where everything is somehow interconnected with all the other systems. A little bit overdrawing here, but basically we do have the need, to split things into dedicated views for a given context. In the and, we may have several views with same elements but just showing the relationships relevant for the given context.
Maybe this approach is wrong in first place?!
What's the best way to show relationships with resources which sit behind a load balancer in a deployment view?
The relationship defined between two software systems/containers when looking at the System Landscape normally looks correct but when creating a deployment view, the relationships will appear as if they'd call the api directly, when in reality it would be behind a load balancer.
Is there a way to override these relationships somehow or is the best way to use a tag to exclude them from the deployment view and create a new relationship there?
e.g.
model {
springPetClinic = softwaresystem "Spring PetClinic" "Allows employees to view and manage information regarding the veterinarians, the clients, and their pets." "Spring Boot Application" {
webApplication = container "Web Application" "Allows employees to view and manage information regarding the veterinarians, the clients, and their pets." "Java and Spring Boot"
database = container "Database" "Stores information regarding the veterinarians, the clients, and their pets." "Relational database schema" "Database"
}
springMobileApp = softwareSystem "Spring PetClinic Mobile App" "" "iOS" {
-> webApplication "Manage appointments"
}
client = person "client" {
-> springMobileApp "Makes appointments"
}
webApplication -> database "Reads from and writes to" "JDBC/SSL"
deploymentEnvironment "Live" {
deploymentNode "UserDevice" "" "" "iOS" {
softwareSystemInstance springMobileApp
}
deploymentNode "Amazon Web Services" "" "" "Amazon Web Services - Cloud" {
deploymentNode "US-East-1" "" "" "Amazon Web Services - Region" {
route53 = infrastructureNode "Route 53" "" "" "Amazon Web Services - Route 53"
elb = infrastructureNode "Elastic Load Balancer" "" "" "Amazon Web Services - Elastic Load Balancing"
deploymentNode "Autoscaling group" "" "" "Amazon Web Services - Auto Scaling" {
deploymentNode "Amazon EC2" "" "" "Amazon Web Services - EC2" {
webApplicationInstance = containerInstance webApplication
}
}
deploymentNode "Amazon RDS" "" "" "Amazon Web Services - RDS" {
deploymentNode "MySQL" "" "" "Amazon Web Services - RDS_MySQL_instance" {
containerInstance database
}
}
}
}
route53 -> elb "Forwards requests to" "HTTPS"
elb -> webApplicationInstance "Forwards requests to" "HTTPS"
}
}
views {
deployment springPetClinic "Live" "AmazonWebServicesDeployment" {
include *
autolayout lr
}
systemLandscape SystemLandscape {
include *
autoLayout
}
systemContext springPetClinic "Spring_Pet_Clinic_Context" {
include *
autoLayout
}
styles {
element "Element" {
shape roundedbox
background "#ffffff"
}
element "Database" {
shape cylinder
}
element "Infrastructure Node" {
shape roundedbox
}
element "iOS" {
shape MobileDevicePortrait
}
}
themes https://static.structurizr.com/themes/amazon-web-services-2020.04.30/theme.json
}
}```
I'm trying to create a dynamic view for a flow within my system. The definition of the software system is as follows:
BulkIngestion = softwareSystem "Bulk Ingestion" "Responsible for ingesting Products defined via xml" {
ftpServer = container "FtpServer" "FtpServer"
disk = container "Disk" "Storage on which Product is temporary stored" "SD" "STORAGE"
agent = container "Agent" "Triggers ingestion process when product received"
queue = container "Ingestion Queue" "Queue of pending Product ingestions" "Redis" "QUEUE"
worker = container "Worker" "Worker" ""Ingests uploaded Products" "Ruby"
user -> ftpServer "Uses"
ftpServer -> disk "Write Product"
disk -> agent "Read"
agent -> queue "Trigger Ingestion Product"
worker -> queue "Consume Trigger"
worker -> core "Create Product"
}
My dynamic view definition is as follows:
views {
systemLandscape "Landscape" "Landscape" {
include *
autolayout
}
...
dynamic * "IngestProduct" "Ingest Product via API" {
User -> ftpServer "Upload Binaries Product"
}
}
When i try to upload my workspace i get the following exception: Caused by: com.structurizr.dsl.StructurizrDslParserException: Only people and software systems can be added to this dynamic view at line 23: User -> ftpServer "Upload Binaries Product"
Would have expected that it would be possible since dsl language spec states:
dynamic <*|software system identifier|container identifier> [key] [description] {
...
}
As a new (excited) user I'd like to know what the reserved words are?
Hi Simon, I’m just now trying out the DSL for a real project, and so far I’m very impressed!
One question: I don’t see a way to specify element coordinates and/or relationship control points, when not using auto-layout. Am I missing something, or is this just not yet supported? If the latter, do you intend to add such support at some point?
Thanks!
Avi
Given the following:
apiApplication = container "API Application" "Desc" "Techno" {
component1 = component "Test component 1" "Desc" "Techno" "Microservice"
component2 = component "Test component 2" "Desc" "Techno" "Microservice"
component1 -> component2
}
I'd like to create a component view showing only component1
and its children, doing the following:
views {
component apiApplication "Component1" {
include component1 -> *
}
}
But that won't work and will throw the following error (using Structurizr CLI v1.8.1):
com.structurizr.dsl.StructurizrDslParserException: The element "component1" does not exist in the view at line 211: include component1 -> *
at com.structurizr.dsl.StructurizrDslParser.parse(StructurizrDslParser.java:561)
Given the following DSL:
workspace {
model {
A = softwareSystem A "" {
aa = container "aa"
}
B = softwareSystem B
// if we enable the following two lines the relationships are tagged correctly
// aa -> B "relation1" "" "tag1"
// aa -> B "relation2" "" "tag2"
}
views {
dynamic A "integration" "TAG-123 :: Project Description" {
aa -> B "relation1" "" "tag1"
aa -> B "relation2" "" "tag2"
autolayout
}
systemlandscape "SystemLandscape" {
include *
autoLayout
}
}
}
I am expecting to get two relationships where the first one is tagged with "tag1" and the second is tagged with "tag2".
Currently, it produces two relationships and both are tagged with "tag1".
Hello!
Lately I'm working with Structurizr and having a lot of fun, but I'm looking for specific view I can't get by now.
I want to see a connection from one component in container to other component in container, and actually see in one view two different components from two different containers.
For example, let's look in this DSL:
` model {
customer = person "Personal Banking Customer" "A customer of the bank, with personal bank accounts." "Customer"
enterprise "Big Bank plc" {
supportStaff = person "Customer Service Staff" "Customer service staff within the bank." "Bank Staff"
backoffice = person "Back Office Staff" "Administration and support staff within the bank." "Bank Staff"
mainframe = softwaresystem "Mainframe Banking System" "Stores all of the core banking information about customers, accounts, transactions, etc." "Existing System"
email = softwaresystem "E-mail System" "The internal Microsoft Exchange e-mail system." "Existing System"
atm = softwaresystem "ATM" "Allows customers to withdraw cash." "Existing System"
internetBankingSystem = softwaresystem "Internet Banking System" "Allows customers to view information about their bank accounts, and make payments." {
singlePageApplication = container "Single-Page Application" "Provides all of the Internet banking functionality to customers via their web browser." "JavaScript and Angular" "Web Browser"
mobileApp = container "Mobile App" "Provides a limited subset of the Internet banking functionality to customers via their mobile device." "Xamarin" "Mobile App" {
mobileAppComponent = component "Mobile App Component"
}
webApplication = container "Web Application" "Delivers the static content and the Internet banking single page application." "Java and Spring MVC"
apiApplication = container "API Application" "Provides Internet banking functionality via a JSON/HTTPS API." "Java and Spring MVC" {
signinController = component "Sign In Controller" "Allows users to sign in to the Internet Banking System." "Spring MVC Rest Controller"
accountsSummaryController = component "Accounts Summary Controller" "Provides customers with a summary of their bank accounts." "Spring MVC Rest Controller"
resetPasswordController = component "Reset Password Controller" "Allows users to reset their passwords with a single use URL." "Spring MVC Rest Controller"
securityComponent = component "Security Component" "Provides functionality related to signing in, changing passwords, etc." "Spring Bean"
mainframeBankingSystemFacade = component "Mainframe Banking System Facade" "A facade onto the mainframe banking system." "Spring Bean"
emailComponent = component "E-mail Component" "Sends e-mails to users." "Spring Bean"
}
database = container "Database" "Stores user registration information, hashed authentication credentials, access logs, etc." "Oracle Database Schema" "Database"
}
}
# relationships between people and software systems
customer -> internetBankingSystem "Views account balances, and makes payments using"
internetBankingSystem -> mainframe "Gets account information from, and makes payments using"
internetBankingSystem -> email "Sends e-mail using"
email -> customer "Sends e-mails to"
customer -> supportStaff "Asks questions to" "Telephone"
supportStaff -> mainframe "Uses"
customer -> atm "Withdraws cash using"
atm -> mainframe "Uses"
backoffice -> mainframe "Uses"
# relationships to/from containers
customer -> webApplication "Visits bigbank.com/ib using" "HTTPS"
customer -> singlePageApplication "Views account balances, and makes payments using"
customer -> mobileApp "Views account balances, and makes payments using"
webApplication -> singlePageApplication "Delivers to the customer's web browser"
# relationships to/from components
singlePageApplication -> signinController "Makes API calls to" "JSON/HTTPS"
singlePageApplication -> accountsSummaryController "Makes API calls to" "JSON/HTTPS"
singlePageApplication -> resetPasswordController "Makes API calls to" "JSON/HTTPS"
mobileAppComponent -> signinController "Makes API calls to" "JSON/HTTPS"
mobileApp -> accountsSummaryController "Makes API calls to" "JSON/HTTPS"
mobileApp -> resetPasswordController "Makes API calls to" "JSON/HTTPS"
signinController -> securityComponent "Uses"
accountsSummaryController -> mainframeBankingSystemFacade "Uses"
resetPasswordController -> securityComponent "Uses"
resetPasswordController -> emailComponent "Uses"
securityComponent -> database "Reads from and writes to" "JDBC"
mainframeBankingSystemFacade -> mainframe "Makes API calls to" "XML/HTTPS"
emailComponent -> email "Sends e-mail using"
views {
component apiApplication "Components" {
include *
animation {
singlePageApplication mobileApp database email mainframe
signinController securityComponent
accountsSummaryController mainframeBankingSystemFacade
resetPasswordController emailComponent
}
autoLayout
}
}
}
}
`
Taken from this example with few modification: https://structurizr.com/dsl?example=big-bank-plc, and I'm taking a look on the component view:
component apiApplication "Components" { include * animation { singlePageApplication mobileApp database email mainframe signinController securityComponent accountsSummaryController mainframeBankingSystemFacade resetPasswordController emailComponent } autoLayout }
The drawing we're having is:
Even though component inside the mobileApp container is communicating with one of the applications in the API Application container, the connection seems straight from the container itself.
I know that's the intention, but what I wanted to have is the possibility to see also the component inside the "mobileApp" container with dotted lines around the mobileApp container.
I guess it will require a different view, because such kind of view not falling on any of component / container / SystemLandscape view.
Such view (with inner components of several containers) can be quite loaded, so I guess using it with filtered view is the way to go (seeing only connection relevant to this drawing)
The benefit of this kind of view is seeing connection cross containers, and no only in the container level
In the project I'm working in, we're having few containers, each one of them including several processes (components).
My wish is to demonstrate connection between components, and that's where this request coming from
Thanks! Omri
Hi there, I got the DSL example to work in less than 5 mins, thanks for having documented it so well! How about "IDE" support for it, for instance Visual Studio Code? Apologies if I missed the instructions about it...
C4 does qualify as a mighty method in Michael Keeling terms :-)
Hi @simonbrowndotje ,
There doesn't appear to be any support for setting the URL on any of the objects that accept it in the UI. It this something that can be added?
By the way, I'm really liking the DSL. I much prefer it over the UI.
Cheers!
Kyle
Use Case: Using Structurizr to model an application landscape.
This goes against the recommendations for using Structurizr, but I have started to model a number (20ish) complex enterprise applications and how they integrate. We have tried this a number of times with UML and other techniques but have all failed, so I am trying it with C4 now :)
I have a models directory, and within that directories for:
I have a modified version of dsl which understands importing from directories.
Effectively I model systems in their own files, containing "within system" relationships in these files.
In the workspace I include the system in scope under "enterpise" and then import all systems next (this filters out the already loaded file in "enterprise"). Workspaces are generally containers for views.
Inter-thing relationships are seperate and included last so as to not require loading in a special order.
Is this something that is interesting? My current code breaks the file handling abstraction in the code a little, to dedeup file includes per workspace (I use Maven to generate all the models, and then also generate ascii doc extracts from the model to be included in other documents).
I can keep this as a private fork, or potenitally share for comment?
Thanks
Chris
=snip=
`
workspace "My System" "System which supports integration" {
model {
enterprise "My System" {
!include high-level-system/my-system.dsl
}
# Include related Systems here
!include high-level-system
# Include related People here
!include transpower-people
!include customer-people
!include relationships
}
views {
systemLandscape CriticalESBSystemLandscape "All Systems in the ESB System Context" {
autoLayout
`
I have a container for which I want to show multiple views, One would be a view that shows the use cases that are provided by the service/container and another would be the actual components that are implemented within the container. I can create the views by having the use cases tagged and include the tag within the view and exclude it in the other view. The views are correctly created but issue is when i want to zoom in on the container view. There seems to be no way that I can enforce/select to which view I want to go. Is that assumption correct, or is there a way to somehow force/select the proper zoom view
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.