Skip to content

Commit

Permalink
Merge pull request #38 from Cambio-Project/documentation
Browse files Browse the repository at this point in the history
Documentation + Minor Fixes
  • Loading branch information
franksn90 authored Jun 20, 2024
2 parents 72bce92 + 8e296da commit 8d835b0
Show file tree
Hide file tree
Showing 11 changed files with 785 additions and 52 deletions.
124 changes: 87 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,108 @@
# Dispel Dashboard
# DiSpel Cockpit

## Description
1. [Description](#description)
1. [Installation](#install)
1. [Usage](#use)

The Dispel Dashboard is an all-in-one, multi-functional application. It's designed to allow users to create and simulate scenarios, verify the results of simulations, and refine responses. The functionalities of the dashboard include:
- **Setup**: The dashboard provides an overview of all required services, indicating their availability.
- **Scenario Creation**: Users can create scenarios by providing an architecture and experiment files in JSON format. It also allows adding scenario metadata (name, description, category), creating stimuli, defining responses, and persistent custom events which are used by the TbVerifier.
- **Simulation**: Scenarios can be simulated and users are notified upon completion of the simulation.
- **Validation**: After simulation, the output can be verified. The response text color indicates whether the response passes validation.
- **Refinement**: Finally, users can refine the responses using the built-in TqPropRefiner interface.
## <a name="description" /> Description

The dashboard can be set up either using Docker Compose (recommended) or manually.
The Dispel Cockpit is an all-in-one, multi-functional application. It's designed to allow software architects to
specify (testable) scenarios, collect data from different sources (simulation, monitoring), verify the scenarios against
the results, and refine the response specifications. The functionalities of the Cockpit include:

- **Scenario Creation**: Users can create scenarios by providing specifications of the stimuli and responses using the
Property Specification Patterns. Additional information must be provided to allow for quantitative analyses, e.g.,
architecture and experiment files in JSON format.
- **Data Collection**: Scenarios can be simulated and monitoring data can be searched for existing scenario occurrences
based on the stimuli specifications.
- **Verification**: After data collection, the output can be verified. The response text color indicates whether the
response passes validation and statistics are computed.
- **Refinement**: Finally, users can refine the responses using the built-in TQPropRefiner interface by investigating
and adjusting parameters and timing specifications.
- **Configuration**: The Cockpit provides an overview of all required services, indicating their availability.

## How to install
There are two ways to use the dashboard.
The simplest is with the provided ``docker-compose.yml`` file which contains all required components.
The other is to build it locally, whereby you have to make sure that the respective connections of the components are correct.
The DiSpel Cockpit can be set up either using Docker Compose (recommended) or manually.

## <a name="install" /> How to install

There are two ways to use the Cockpit.
The simplest is with the provided ``docker-compose.yml`` file which contains all required components.
The other is to build it locally, whereby you have to make sure that the respective connections of the components are
correct.

### Docker

### Docker
**Requirements:** Docker

1. Copy the content (or the file itself) from the ``docker-compose.yml`` in an empty folder.
- Docker will need write access in that directory
2. start Docker with the command ```docker compose up -d```
2. Start Docker with the command ```docker compose up -d```
- The flag ```-d``` starts the containers in the background
3. After all Container are startet up, you can reach the Dashboard via your browser at ``http://localhost:8080``
3. After all Container are started up, you can reach the Cockpit via your browser at ``http://localhost:8080``

### Manual setup

_(Not recommended)_

**Requirements:** Node

1. Clone or download this Repository.
2. Adjust the URL and Ports in the ```.env``` file in this repository to match your service setup.
3. Now you cloud either run the Dashboard in dev mode or in build mode
3. Now you cloud either run the Cockpit in dev mode or in build mode
1. **Development Mode**
1. Make sure that you have all dependencies installed: ``npm install``
2. Start the Dashboard with the command: ``npm run dev``
1. Make sure that you have all dependencies installed: ``npm install``
2. Start the Cockpit with the command: ``npm run dev``
2. **Build Mode**
1. Run the command: ```npm run build```
2. Go to your build file and start the endpoint with your Node environment.

## How to use

1. **Startup:** On the Dashboard you will find an overview of all required services. A green light signals that the service is available. If the service is red something is wrong with your setup.
2. **Create a Scenario:** The next step is to go to the scenario overview where you can see and add scenarios. Click on add Scenario to start the process.
- **Create a Stimuli:** For the stimuli it is required to upload MiSim architecture and experiment file in ``.json`` format.
Its also required that all dependent additional files that MiSim need to run those configuration are added in this step.
Additionally, you can add a scenario name, description, and category.
- **Create a Response:** In the Response window you have access to all fields that are also available in the PspWizard. Define here the response you want to test.
- **Create Events:** You can create custom events that are persistent (in the installation of the dashboard).
Here you can deine measurement scores which are later used by the TbVerifier.
3. **Simulate Scenario:** After the create of a scenario you can find the scenario in the overview.
From there you can start the simulation with MiSim. You will be notified when the simulation finished.
4. **Validate Scenario:** When the simulation fished, you can verify the simulation with the verify simulation button. The color of the response text will indicate of the response validates or not.
5. **Refine Scenario:** Finally you can start the response refinement. With the click of the button you will be redirected to the interface of the TqPropRefiner.
Here you can use all the provided functionality and save the results in the dashboard.
1. Run the command: ```npm run build```
2. Go to your build file and start the endpoint with your Node environment.

Note: TQPropRefiner currently requires the Cockpit to run on port 8080, otherwise refinements can not be sent
back.

## <a name="use" /> How to use

### General Usage Workflow

1. **Startup:** You will find an overview of all required services on the 'Configuration' page, which is also the
starting page. A green
light signals that the
service is available. If the service is red something is wrong with your setup. A yellow light signals that some
services are not available. The status of dependencies is also visible in the menu bar on every page.
2. **Create a Scenario:** The next step is to go to the scenario overview where you can see and add scenarios. Click on
add Scenario to start the process.
- **Add Metadata:** You can add a scenario name, description, and category.
- **Add Environment:** For the data collection to work, it is required to upload MiSim architecture and experiment
file in ``.json``
format.
Its also required that all dependent additional load files that MiSim needs to run those configuration are added
in this
step.
For the search in monitoring data to work, the monitoring data has to be provided as ``.csv`` file and a search
window size (in time units) has to be defined. Found occurrences will be of this size.
- **Create Stimuli and Responses:** In the Stimuli and Response window you have access to all fields that are also
available in the
PSPWizard in order to select and specify a Property Specification Pattern.
- **Create Commands, Listeners, Events:** For stimuli, you can create commands (currently service killing and load
modification) and listeners (currently listening to a thrown event). For responses, you can create custom events
that are persistent.
Here you can define measurement sources which are basically metrics that have to be present in simulation data and
monitoring data.
3. **Collect Data:** After the creation of a scenario you can find the scenario in the overview.
From there you can start the simulation with MiSim or the search with MoSIM. You will be notified on this page when
the data generation finished.
4. **Verify Scenario:** When the data collection finished, you can verify the data with the verify simulation button
or the verify search button.
The color of the response text on the `Scenario Details' page will indicate whether the response is satisfied for a
specific run or not.
5. **Refine Scenario:** Finally you can start the response refinement on the 'Scenario Details' page. With the click of
the button you will be
redirected to the interface of the TQPropRefiner.
Here you can use all the provided functionality and save the refined specification in the Cockpit.

### Video Showcase & Example Scenario

The example scenario *Service Instance Failure + Load Peak*, including all specifications and files, is provided as part
of this project in ``examples / failureLoadPeak``. This example is used in the following tool demonstration vide.

[![](https://markdown-videos.vercel.app/youtube/gP6USBfOuxY)](https://youtu.be/gP6USBfOuxY)

10 changes: 0 additions & 10 deletions components/PSPWizard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ export default {
},
"pspSpecification.upperLimit": {
handler() {
this.checkTime()
this.handleInputChange()
},
deep: true
Expand All @@ -230,7 +229,6 @@ export default {
},
"pspSpecification.lowerLimit": {
handler() {
this.checkTime()
this.handleInputChange()
},
deep: true
Expand Down Expand Up @@ -1267,14 +1265,6 @@ export default {
}
}
,
checkTime() {
if (this.pspSpecification.upperLimit != null && this.pspSpecification.lowerLimit != null) {
if (this.pspSpecification.upperLimit < this.pspSpecification.lowerLimit) {
this.pspSpecification.lowerLimit = this.pspSpecification.upperLimit;
}
}
}
,
async sendTransformRequest(payload) {
if (payload.scope.type === null || payload.pattern.type === null || payload.pattern.p_event === undefined) {
return
Expand Down
6 changes: 3 additions & 3 deletions components/Scenario.vue
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,10 @@ export default {
<ul>
<li v-for="(response, index) in scenario.responses" :key="response" class="left">
<div class="container-row">
<div class="container-row-element-xs">
<div class="container-row-element-s">
<!-- Response Statistics -->
<div class="container-row">
<div class="container-row-element-s">
<div class="container-row-element-xs">
<span>{{ index + 1 }}.</span>
</div>
<div class="container-row-element">
Expand Down Expand Up @@ -450,7 +450,7 @@ export default {
<UDivider label="Executions" class="mt-2 mb-2"/>
<div v-for="(resultName,resultIndex) in result.simulationNames">
<div class="scenario-box mb-4"
:class="{ 'green-border' : this.result.searchResultsScenarioSuccesses[resultIndex], 'red-border' : !this.result.searchResultsScenarioSuccesses[resultIndex] }">
:class="{ 'green-border' : this.result.simulationResultsScenarioSuccesses[resultIndex], 'red-border' : !this.result.simulationResultsScenarioSuccesses[resultIndex] }">
<div class="container-row">
<div class="container-element-xs w-full">
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/Scenarios.vue
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ export default {
<ul>
<li v-for="(response, index) in scenario.responses" :key="response" class="mb-1">
<div class="container-row">
<div class="container-row-element-xs">
<div class="container-row-element-s">
<!-- Response Statistics -->
<div class="container-row">
<div class="container-row-element-s">
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: "dashboard-project"

services:
dashboard:
image: ghcr.io/cambio-project/dashboard-vue-23:1.2.0
image: ghcr.io/cambio-project/dashboard-vue-23:1.2.1
container_name: dashboard
ports:
- 8080:3000
Expand Down
135 changes: 135 additions & 0 deletions examples/failureLoadPeak/architecture_tltea_scenario1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
{
"microservices": [
{
"name": "gateway",
"instances": 1,
"capacity": 600,
"loadbalancer_strategy": "even",
"operations": [
{
"name": "EXTERNAL_DEP",
"demand": 1,
"dependencies": [
{
"service": "example-service",
"operation": "call_external_service"
}
]
},
{
"name": "INTERNAL_DEP",
"demand": 1,
"dependencies": [
{
"service": "example-service",
"operation": "call_example-service2"
}
]
},
{
"name": "UNAFFECTED_SERVICE",
"demand": 1,
"dependencies": [
{
"service": "example-service2",
"operation": "example-service2.get"
}
]
},
{
"name": "gateway.DB_WRITE",
"demand": 1,
"dependencies": [
{
"service": "example-service",
"operation": "example-service.DB_WRITE"
}
]
},
{
"name": "gateway.DB_READ",
"demand": 1,
"dependencies": [
{
"service": "example-service",
"operation": "example-service.DB_READ"
}
]
},
{
"name": "gateway.PING",
"demand": 1,
"dependencies": []
}
],
"patterns": [
{
"type": "retry",
"config": {
"maxTries": 5,
"baseBackoff": 0.2,
"maxBackoff": 2,
"base": 2,
"jittering": false
}
}
]
},
{
"name": "example-service",
"instances": 2,
"patterns": [],
"capacity": 300,
"operations": [
{
"name": "example-service.DB_WRITE",
"demand": 2,
"dependencies": []
},
{
"name": "example-service.DB_READ",
"demand": 1,
"dependencies": []
},
{
"name": "call_example-service2",
"demand": 1,
"dependencies": [
{
"service": "example-service2",
"operation": "example-service2.get"
}
]
},
{
"name": "call_external_service",
"demand": 1,
"dependencies": []
}
],
"s_patterns": [
{
"type": "autoscale"
}
]
},
{
"name": "example-service2",
"instances": 2,
"patterns": [],
"capacity": 300,
"operations": [
{
"name": "example-service2.get",
"demand": 1,
"dependencies": []
}
],
"s_patterns": [
{
"type": "autoscale"
}
]
}
]
}
40 changes: 40 additions & 0 deletions examples/failureLoadPeak/experiment_basic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"simulation_metadata": {
"experiment_name": "Example-Basic-Test",
"model_name": "Scenario Basic",
"duration": 200
},
"request_generators": [
{
"type": "interval",
"config": {
"interval": 0.01,
"microservice": "gateway",
"operation": "INTERNAL_DEP"
}
},
{
"type": "interval",
"config": {
"interval": 0.02,
"microservice": "gateway",
"operation": "DB_WRITE"
}
},
{
"type": "interval",
"config": {
"interval": 0.005,
"microservice": "gateway",
"operation": "DB_READ"
}
},
{
"type": "interval",
"config": {
"interval": 0.01,
"operation": "gateway.UNAFFECTED_SERVICE"
}
}
]
}
Loading

0 comments on commit 8d835b0

Please sign in to comment.