Skip to content

Commit

Permalink
Report Framework Step 1 (#65)
Browse files Browse the repository at this point in the history
Creates the new asynchronous background writers for continuous output.
  • Loading branch information
LitschiW committed Jul 15, 2023
1 parent 13e4bea commit 37cf9d3
Show file tree
Hide file tree
Showing 71 changed files with 2,255 additions and 1,331 deletions.
1 change: 1 addition & 0 deletions Examples/example_experiment_chaosmonkey.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"simulation_metadata": {
"experiment_name": "Example-ChaosMonkey-Test",
"model_name": "Scenario ChaosMonkey",
"seed": "12345",
"duration": 200
},
"request_generators": [
Expand Down
712 changes: 356 additions & 356 deletions checkstyle.xml → checkstyle/checkstyle.xml

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions checkstyle/suppressions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<suppress files="AsyncMultiColumnReportWriter.java"
checks="MissingJavadocMethod"/>
</suppressions>
19 changes: 7 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cambio.simulator</groupId>
Expand Down Expand Up @@ -160,16 +161,16 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.2.0</version>
<version>3.3.0</version>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
<version>9.3</version>
<version>9.3</version> <!-- TODO: update to >10 when moving to java >8 -->
</dependency>
</dependencies>
<configuration>
<configLocation>${project.basedir}/checkstyle.xml</configLocation>
<configLocation>${project.basedir}/checkstyle/checkstyle.xml</configLocation>
<inputEncoding>UTF-8</inputEncoding>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
Expand Down Expand Up @@ -198,10 +199,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<encoding>UTF-8</encoding>
<doclint>all,-accessibility</doclint>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
Expand All @@ -213,9 +210,6 @@
<goals>
<goal>jar</goal>
</goals>
<configuration>
<doclint>none</doclint>
</configuration>
</execution>
</executions>
</plugin>
Expand All @@ -237,7 +231,8 @@
<version>3.3.0</version>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>cambio.simulator.Main</mainClass>
</transformer>
</transformers>
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/cambio/simulator/CLI.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import org.jetbrains.annotations.NotNull;

/**
* Static class that holds the command line options of the simulator and is able to parse these into a {@link
* CommandLine} object for retrieval.
* Static class that holds the command line options of the simulator and is able to parse these into a
* {@link CommandLine} object for retrieval.
*
* @author Lion Wagner
*/
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/cambio/simulator/ExperimentCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.nio.file.Path;
import java.time.LocalDateTime;

import cambio.simulator.export.ExportUtils;
import cambio.simulator.misc.FileUtilities;
Expand All @@ -13,8 +14,8 @@
import org.jetbrains.annotations.NotNull;

/**
* Class that contains code for creating a new {@link desmoj.core.simulator.Experiment} based on a {@link
* ExperimentStartupConfig}.
* Class that contains code for creating a new {@link desmoj.core.simulator.Experiment} based on a
* {@link ExperimentStartupConfig}.
*
* @author Lion Wagner
*/
Expand Down Expand Up @@ -62,8 +63,12 @@ protected File tryGetDescription(String expDescLocation, String descriptionName)
@NotNull
protected Experiment setupExperiment(ExperimentStartupConfig config, MiSimModel model) {
ExperimentMetaData metaData = model.getExperimentMetaData();
metaData.setStartDate(LocalDateTime.now());
Path reportLocation = ExportUtils.prepareReportDirectory(config, model);
Experiment exp = new Experiment(metaData.getExperimentName(), reportLocation.toString());
Experiment exp = config.traceEnabled()
? new Experiment(metaData.getExperimentName(), reportLocation.toString())
: new Experiment(metaData.getExperimentName(), reportLocation.toString(), "desmoj.core.report.NullOutput",
"desmoj.core.report.NullOutput", "desmoj.core.report.NullOutput", "desmoj.core.report.NullOutput");
model.connectToExperiment(exp);

exp.setSeedGenerator(metaData.getSeed());
Expand Down
37 changes: 27 additions & 10 deletions src/main/java/cambio/simulator/ExperimentStartupConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,18 @@ public class ExperimentStartupConfig {
longOpt = "out",
description = "Report Location Directory. Creates a new directory with "
+ "experiment name and start timestamp for each experiment run.",
hasArg = true)
hasArg = true,
optionGroup = "output")
private final String reportLocation;

@CLIOption(
opt = "O",
longOpt = "overwrite_out",
description = "Report Location Directory. It Is cleared before the experiment.",
hasArg = true,
optionGroup = "output")
private final String reportOverwriteLocation;

@CLIOption(
opt = "p",
longOpt = "progress_bar",
Expand Down Expand Up @@ -71,21 +80,25 @@ public class ExperimentStartupConfig {
* An expDescLoc or scenario have to be given. If an expDescLoc is given the scenario will be ignored. Boolean
* default values are always {@code false}.
*
* @param archDescLoc mandatory path to an architecture description
* @param expDescLoc path to an experiment description
* @param scenario path to a scenario description
* @param reportLocation directory path ot
* @param showProgressBar when this option is set to true, a progressbar window is shown during the simulation
* (setting this option disables headless mode and requires a display output)
* @param debug enables debug output
* @param archDescLoc mandatory path to an architecture description
* @param expDescLoc path to an experiment description
* @param scenario path to a scenario description
* @param reportLocation directory path where the report should be saved
* @param reportOverwriteLocation directory path where the report should be overwritten
* @param showProgressBar when this option is set to true, a progressbar window is shown during the
* simulation (setting this option disables headless mode and requires a display
* output)
* @param debug enables debug output
*/
public ExperimentStartupConfig(@NotNull String archDescLoc, String expDescLoc, String scenario,
String reportLocation,
boolean showProgressBar, boolean debug, boolean traces) {
String reportOverwriteLocation, boolean showProgressBar, boolean debug,
boolean traces) {
this.archDescLoc = archDescLoc;
this.expDescLoc = expDescLoc;
this.scenario = scenario;
this.reportLocation = reportLocation;
this.reportOverwriteLocation = reportOverwriteLocation;
this.showProgressBar = showProgressBar;
this.debug = debug;
this.noTraces = !traces;
Expand All @@ -110,7 +123,11 @@ public String getScenario() {
}

public String getReportLocation() {
return reportLocation;
return reportLocation != null ? reportLocation : reportOverwriteLocation;
}

public boolean isOverwriteReportPath() {
return reportOverwriteLocation != null;
}

public boolean showProgressBarOn() {
Expand Down
35 changes: 25 additions & 10 deletions src/main/java/cambio/simulator/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import java.util.Arrays;

import cambio.simulator.export.ReportCollector;
import cambio.simulator.misc.RNGStorage;
import cambio.simulator.misc.Util;
import cambio.simulator.models.ExperimentMetaData;
import cambio.simulator.models.MiSimModel;
import cambio.simulator.parsing.ParsingException;
import com.google.gson.JsonParseException;
Expand All @@ -23,13 +24,14 @@ public final class Main {
*
* <p>
* This method will <b>always</b> call {@link System#exit(int)}! Be aware of that if you call it from other code. If
* you want to avoid this behavior, consider calling {@link #runExperiment(String[])} or {@link
* #runExperiment(ExperimentStartupConfig)} instead.
* you want to avoid this behavior, consider calling {@link #runExperiment(String[])} or
* {@link #runExperiment(ExperimentStartupConfig)} instead.
*
* <p>
* Exit code meanings are as follows:
*
* <table>
* <caption>Exit codes.</caption>
* <tr>
* <th>Exit Code</th>
* <th>Description</th>
Expand Down Expand Up @@ -78,6 +80,7 @@ public static void main(final String[] args) {
System.exit(16);
} else {
System.out.println("[INFO] Simulation finished successfully.");
writeCommandLineReport((MiSimModel) experiment.getModel());
System.exit(0);
}
} catch (ParsingException | JsonParseException e) {
Expand All @@ -91,6 +94,7 @@ public static void main(final String[] args) {
//In tests, System.exit throws an exception with a private type from the
//"com.github.stefanbirkner.systemlambda" package. This exception is supposed to be
//thrown up to top level to be detected by a test and therefore is not handled here.
//TODO: this should (and will have to be with later java versions) be removed
if (e.getClass().getPackage().getName().equals("com.github.stefanbirkner.systemlambda")) {
throw e;
}
Expand All @@ -109,14 +113,13 @@ public static void main(final String[] args) {
*
* <p>
* This method will <b>always</b> call {@link System#exit(int)}! Be aware of that if you call it from other code. If
* you want to avoid this behavior, consider calling {@link #runExperiment(String[])} or {@link
* #runExperiment(ExperimentStartupConfig)} instead.
* you want to avoid this behavior, consider calling {@link #runExperiment(String[])} or
* {@link #runExperiment(ExperimentStartupConfig)} instead.
*
* <p>
* For exit code meanings, see {@link #main(String[])}.
*
* @param args program options, see {@link ExperimentStartupConfig#ExperimentStartupConfig(String, String, String,
* String, boolean, boolean, boolean)}
* @param args program options, see {@link ExperimentStartupConfig}
* @see #main(String[])
* @see #runExperiment(String)
* @see #runExperiment(ExperimentStartupConfig)
Expand Down Expand Up @@ -145,8 +148,6 @@ public static void mainVarargs(final String... args) {

Experiment experiment = runExperiment(startupConfig);

ReportCollector.getInstance().printReport((MiSimModel) experiment.getModel());

return experiment;

}
Expand Down Expand Up @@ -183,4 +184,18 @@ public static void mainVarargs(final String... args) {

return experiment;
}
}

private static void writeCommandLineReport(MiSimModel model) {
ExperimentMetaData metaData = model.getExperimentMetaData();
System.out.println("\n*** MiSim Report ***");
System.out.println("Simulation of Architecture: "
+ metaData.getArchitectureDescriptionLocation().getAbsolutePath());
System.out.println("Executed Experiment: "
+ metaData.getExperimentDescriptionLocation().getAbsolutePath());
System.out.println("Report Location: "
+ metaData.getReportLocation().toAbsolutePath());
System.out.println("Setup took: " + Util.timeFormat(metaData.getSetupExecutionDuration()));
System.out.println("Experiment took: " + Util.timeFormat(metaData.getExperimentExecutionDuration()));
System.out.println("Execution took: " + Util.timeFormat(metaData.getExecutionDuration()));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package cambio.simulator.entities.generator;

import static cambio.simulator.export.ReportCollector.GENERATOR_REPORTER;
import static cambio.simulator.export.MiSimReporters.GENERATOR_REPORTER;

import cambio.simulator.entities.NamedSimProcess;
import cambio.simulator.entities.microservice.NoInstanceAvailableException;
Expand Down Expand Up @@ -61,7 +61,7 @@ public LoadGeneratorDescriptionExecutor(Model model, @NotNull LoadGeneratorDescr
String reportName = String
.format("G[%s]_[%s(%s)]_", this.getClass().getSimpleName(), targetOperation.getOwnerMS().getPlainName(),
targetOperation.getPlainName());
accReporter = new AccumulativeDataPointReporter(reportName);
accReporter = new AccumulativeDataPointReporter(reportName, model);


addUpdateListener(this);
Expand All @@ -75,11 +75,10 @@ public void doInitialSelfSchedule() {
}

private void sendNewUserRequest() {
UserRequest request = new UserRequest(model, String.format("UserRequest@[%s]",
targetOperation.getFullyQualifiedPlainName()), true, targetOperation);
UserRequest request = new UserRequest(model,
"UserRequest@[" + targetOperation.getFullyQualifiedPlainName() + "]", model.traceIsOn(), targetOperation);
try {
sendRequest(String.format("SendingUserRequest(%s)", request.getPlainName()), request,
targetOperation.getOwnerMS());
sendRequest("SendingUserRequest(" + request.getPlainName() + ")", request, targetOperation.getOwnerMS());
} catch (NoInstanceAvailableException e) {
onRequestFailed(request, presentTime(), RequestFailedReason.NO_INSTANCE_AVAILABLE);
}
Expand All @@ -91,7 +90,7 @@ private void sendNewUserRequest() {
*/
@Override
public boolean onRequestFailed(Request request, TimeInstant when, RequestFailedReason reason) {
sendTraceNote(String.format("Arrival of Request %s failed at %s.", request, when));
sendTraceNote("Arrival of Request " + request + " failed at " + when + ".");
TimeInstant currentTime = new TimeInstant(Math.ceil(presentTime().getTimeAsDouble()));

accReporter.addDatapoint("FailedRequests", currentTime, 1);
Expand All @@ -110,7 +109,7 @@ public boolean onRequestFailed(Request request, TimeInstant when, RequestFailedR
*/
@Override
public boolean onRequestResultArrivedAtRequester(Request request, TimeInstant when) {
sendTraceNote(String.format("Successfully completed Request %s at %s.", request, when));
sendTraceNote("Successfully completed Request " + request + " at " + when + ".");
TimeInstant currentTime = new TimeInstant(Math.ceil(presentTime().getTimeAsDouble()));

accReporter.addDatapoint("SuccessfulRequests", currentTime, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import cambio.simulator.entities.NamedEntity;
import cambio.simulator.entities.networking.InternalRequest;
import cambio.simulator.entities.patterns.*;
import cambio.simulator.export.AccumulativeDataPointReporter;
import cambio.simulator.export.ListCollectingReporter;
import cambio.simulator.export.MultiDataPointReporter;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
Expand Down Expand Up @@ -42,7 +42,7 @@ public class Microservice extends NamedEntity {
protected final transient Set<MicroserviceInstance> instancesSet =
new TreeSet<>(Comparator.comparingInt(MicroserviceInstance::getInstanceID));
protected final transient MultiDataPointReporter reporter;
private final transient AccumulativeDataPointReporter accReporter;
protected final transient ListCollectingReporter accReporter;

@Expose
@SerializedName(value = "loadbalancer_strategy", alternate = {"load_balancer", "loadbalancer"})
Expand Down Expand Up @@ -82,8 +82,8 @@ public Microservice(Model model, String name, boolean showInTrace) {
super(model, name, showInTrace);
//default load balancer
loadBalancer = new LoadBalancer(model, "Loadbalancer", traceIsOn(), null);
reporter = new MultiDataPointReporter(String.format("S[%s]_", name));
accReporter = new AccumulativeDataPointReporter(String.format("S[%s]_", name));
reporter = new MultiDataPointReporter(String.format("S[%s]_", name), model);
accReporter = new ListCollectingReporter(String.format("S[%s]_", name), model);
}

/**
Expand Down Expand Up @@ -165,14 +165,13 @@ public synchronized void scaleToInstancesCount(final int targetInstanceCount) {
changedInstance =
instancesSet.stream().min(Comparator.comparingDouble(MicroserviceInstance::getUsage)).get();
changeEvent = new InstanceShutdownStartEvent(getModel(),
String.format("Instance %s Shutdown Start", changedInstance.getQuotedName()), traceIsOn());
"Instance " + changedInstance.getQuotedName() + " Shutdown Start", traceIsOn());
instancesSet.remove(changedInstance);
}
changeEvent.schedule(changedInstance, presentTime());
}

reporter.addDatapoint("InstanceCount", presentTime(), instancesSet.size());

}


Expand Down Expand Up @@ -239,9 +238,7 @@ public Operation getOperationByName(String name) {
*/
public MicroserviceInstance getNextAvailableInstance() throws NoInstanceAvailableException {
MicroserviceInstance nextInstance = loadBalancer.getNextInstance(instancesSet);
List<String> data = new ArrayList<>();
data.add(nextInstance.getPlainName());
accReporter.addDatapoint("Load_Distribution", presentTime(), data);
accReporter.addDatapoint("Load_Distribution", presentTime(), nextInstance.getPlainName());
return nextInstance;
}

Expand All @@ -250,10 +247,10 @@ public MicroserviceInstance getNextAvailableInstance() throws NoInstanceAvailabl
* Applies the given delay distribution to the given operations.
*
* @param dist {@link NumericalDist} of the delay.
* @param operationSrc {@link Operation} of this {@link Microservice} that should be affected, can be set to {@code
* null} to affect all {@link Operation}s
* @param operationTrg target {@link Operation} of the operationSrc that should be affected, can be set to {@code
* null} to affect all outgoing {@link InternalRequest}s
* @param operationSrc {@link Operation} of this {@link Microservice} that should be affected, can be set to
* {@code null} to affect all {@link Operation}s
* @param operationTrg target {@link Operation} of the operationSrc that should be affected, can be set to
* {@code null} to affect all outgoing {@link InternalRequest}s
*/
public void applyDelay(NumericalDist<Double> dist, Operation operationSrc, Operation operationTrg) {
if (operationTrg == null) {
Expand Down
Loading

0 comments on commit 37cf9d3

Please sign in to comment.