mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
add instant and interval annotations
This commit is contained in:
parent
5315b8a98a
commit
0d422b5a5f
@ -18,6 +18,9 @@ import io.nosqlbench.engine.api.activityapi.core.*;
|
|||||||
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
||||||
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
||||||
import io.nosqlbench.engine.api.activityimpl.input.ProgressCapable;
|
import io.nosqlbench.engine.api.activityimpl.input.ProgressCapable;
|
||||||
|
import io.nosqlbench.engine.core.annotation.Annotators;
|
||||||
|
import io.nosqlbench.nb.api.Layer;
|
||||||
|
import io.nosqlbench.nb.api.annotations.Annotation;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
@ -56,6 +59,10 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
private RuntimeException stoppingException;
|
private RuntimeException stoppingException;
|
||||||
|
|
||||||
private final static int waitTime = 10000;
|
private final static int waitTime = 10000;
|
||||||
|
private String sessionId = "";
|
||||||
|
private long startedAt = 0L;
|
||||||
|
private long stoppedAt = 0L;
|
||||||
|
private String[] annotatedCommand;
|
||||||
|
|
||||||
// private RunState intendedState = RunState.Uninitialized;
|
// private RunState intendedState = RunState.Uninitialized;
|
||||||
|
|
||||||
@ -72,6 +79,10 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
activity.setActivityController(this);
|
activity.setActivityController(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSessionId(String sessionId) {
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: Doc how uninitialized activities do not propagate parameter map changes and how
|
// TODO: Doc how uninitialized activities do not propagate parameter map changes and how
|
||||||
// TODO: this is different from preventing modification to uninitialized activities
|
// TODO: this is different from preventing modification to uninitialized activities
|
||||||
@ -86,9 +97,22 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
*/
|
*/
|
||||||
public synchronized void startActivity() {
|
public synchronized void startActivity() {
|
||||||
logger.info("starting activity " + activity.getAlias() + " for cycles " + activity.getCycleSummary());
|
logger.info("starting activity " + activity.getAlias() + " for cycles " + activity.getCycleSummary());
|
||||||
|
this.annotatedCommand = annotatedCommand;
|
||||||
|
Annotators.recordAnnotation(Annotation.newBuilder()
|
||||||
|
.session(sessionId)
|
||||||
|
.now()
|
||||||
|
.layer(Layer.Activity)
|
||||||
|
.label("alias", getActivityDef().getAlias())
|
||||||
|
.label("driver", getActivityDef().getActivityType())
|
||||||
|
.label("workload", getActivityDef().getParams().getOptionalString("workload").orElse("none"))
|
||||||
|
.detail("params", getActivityDef().toString())
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
activitylogger.debug("START/before alias=(" + activity.getAlias() + ")");
|
activitylogger.debug("START/before alias=(" + activity.getAlias() + ")");
|
||||||
try {
|
try {
|
||||||
activity.setRunState(RunState.Starting);
|
activity.setRunState(RunState.Starting);
|
||||||
|
this.startedAt = System.currentTimeMillis();
|
||||||
activity.initActivity();
|
activity.initActivity();
|
||||||
//activity.onActivityDefUpdate(activityDef);
|
//activity.onActivityDefUpdate(activityDef);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -117,6 +141,17 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
activity.setRunState(RunState.Stopped);
|
activity.setRunState(RunState.Stopped);
|
||||||
logger.info("stopped: " + this.getActivityDef().getAlias() + " with " + motors.size() + " slots");
|
logger.info("stopped: " + this.getActivityDef().getAlias() + " with " + motors.size() + " slots");
|
||||||
activitylogger.debug("STOP/after alias=(" + activity.getAlias() + ")");
|
activitylogger.debug("STOP/after alias=(" + activity.getAlias() + ")");
|
||||||
|
Annotators.recordAnnotation(Annotation.newBuilder()
|
||||||
|
.session(sessionId)
|
||||||
|
.interval(this.startedAt, this.stoppedAt)
|
||||||
|
.layer(Layer.Activity)
|
||||||
|
.label("alias", getActivityDef().getAlias())
|
||||||
|
.label("driver", getActivityDef().getActivityType())
|
||||||
|
.label("workload", getActivityDef().getParams().getOptionalString("workload").orElse("none"))
|
||||||
|
.detail("params", getActivityDef().toString())
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,11 +214,10 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean requestStopExecutor(int secondsToWait) {
|
public boolean finishAndShutdownExecutor(int secondsToWait) {
|
||||||
activitylogger.debug("REQUEST STOP/before alias=(" + activity.getAlias() + ")");
|
activitylogger.debug("REQUEST STOP/before alias=(" + activity.getAlias() + ")");
|
||||||
|
|
||||||
|
logger.debug("Stopping executor for " + activity.getAlias() + " when work completes.");
|
||||||
logger.info("Stopping executor for " + activity.getAlias() + " when work completes.");
|
|
||||||
|
|
||||||
executorService.shutdown();
|
executorService.shutdown();
|
||||||
boolean wasStopped = false;
|
boolean wasStopped = false;
|
||||||
@ -202,6 +236,7 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
activity.closeAutoCloseables();
|
activity.closeAutoCloseables();
|
||||||
activity.setRunState(RunState.Stopped);
|
activity.setRunState(RunState.Stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stoppingException != null) {
|
if (stoppingException != null) {
|
||||||
logger.trace("an exception caused the activity to stop:" + stoppingException.getMessage());
|
logger.trace("an exception caused the activity to stop:" + stoppingException.getMessage());
|
||||||
throw stoppingException;
|
throw stoppingException;
|
||||||
@ -242,8 +277,27 @@ public class ActivityExecutor implements ActivityController, ParameterMap.Listen
|
|||||||
return activityDef;
|
return activityDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the canonical way to wait for an activity to finish. It ties together
|
||||||
|
* any way that an activity can finish under one blocking call.
|
||||||
|
* This should be awaited asynchronously from the control layer in separate threads.
|
||||||
|
*
|
||||||
|
* TODO: move activity finisher threaad to this class and remove separate implementation
|
||||||
|
*/
|
||||||
public boolean awaitCompletion(int waitTime) {
|
public boolean awaitCompletion(int waitTime) {
|
||||||
return requestStopExecutor(waitTime);
|
boolean finished = finishAndShutdownExecutor(waitTime);
|
||||||
|
Annotators.recordAnnotation(Annotation.newBuilder()
|
||||||
|
.session(sessionId)
|
||||||
|
.interval(startedAt, this.stoppedAt)
|
||||||
|
.layer(Layer.Activity)
|
||||||
|
.label("alias", getActivityDef().getAlias())
|
||||||
|
.label("driver", getActivityDef().getActivityType())
|
||||||
|
.label("workload", getActivityDef().getParams().getOptionalString("workload").orElse("none"))
|
||||||
|
.detail("params", getActivityDef().toString())
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
|
||||||
|
return finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean awaitFinish(int timeout) {
|
public boolean awaitFinish(int timeout) {
|
||||||
|
@ -20,6 +20,9 @@ import io.nosqlbench.engine.api.activityimpl.ActivityDef;
|
|||||||
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
import io.nosqlbench.engine.api.activityimpl.ParameterMap;
|
||||||
import io.nosqlbench.engine.api.activityimpl.ProgressAndStateMeter;
|
import io.nosqlbench.engine.api.activityimpl.ProgressAndStateMeter;
|
||||||
import io.nosqlbench.engine.api.metrics.ActivityMetrics;
|
import io.nosqlbench.engine.api.metrics.ActivityMetrics;
|
||||||
|
import io.nosqlbench.engine.core.annotation.Annotators;
|
||||||
|
import io.nosqlbench.nb.api.Layer;
|
||||||
|
import io.nosqlbench.nb.api.annotations.Annotation;
|
||||||
import io.nosqlbench.nb.api.errors.BasicError;
|
import io.nosqlbench.nb.api.errors.BasicError;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@ -38,6 +41,11 @@ public class ScenarioController {
|
|||||||
private static final Logger scenariologger = LogManager.getLogger("SCENARIO");
|
private static final Logger scenariologger = LogManager.getLogger("SCENARIO");
|
||||||
|
|
||||||
private final Map<String, ActivityExecutor> activityExecutors = new ConcurrentHashMap<>();
|
private final Map<String, ActivityExecutor> activityExecutors = new ConcurrentHashMap<>();
|
||||||
|
private final String sessionId;
|
||||||
|
|
||||||
|
public ScenarioController(String sessionId) {
|
||||||
|
this.sessionId = sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an activity, given the activity definition for it. The activity will be known in the scenario
|
* Start an activity, given the activity definition for it. The activity will be known in the scenario
|
||||||
@ -46,9 +54,20 @@ public class ScenarioController {
|
|||||||
* @param activityDef string in alias=value1;driver=value2;... format
|
* @param activityDef string in alias=value1;driver=value2;... format
|
||||||
*/
|
*/
|
||||||
public synchronized void start(ActivityDef activityDef) {
|
public synchronized void start(ActivityDef activityDef) {
|
||||||
|
Annotators.recordAnnotation(Annotation.newBuilder()
|
||||||
|
.session(sessionId)
|
||||||
|
.now()
|
||||||
|
.layer(Layer.Activity)
|
||||||
|
.label("alias", activityDef.getAlias())
|
||||||
|
.detail("command", "start")
|
||||||
|
.detail("params", activityDef.toString())
|
||||||
|
.build());
|
||||||
|
|
||||||
|
|
||||||
ActivityExecutor activityExecutor = getActivityExecutor(activityDef, true);
|
ActivityExecutor activityExecutor = getActivityExecutor(activityDef, true);
|
||||||
scenariologger.debug("START " + activityDef.getAlias());
|
scenariologger.debug("START " + activityDef.getAlias());
|
||||||
activityExecutor.startActivity();
|
activityExecutor.startActivity();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,6 +103,15 @@ public class ScenarioController {
|
|||||||
* @param activityDef A definition for an activity to run
|
* @param activityDef A definition for an activity to run
|
||||||
*/
|
*/
|
||||||
public synchronized void run(int timeout, ActivityDef activityDef) {
|
public synchronized void run(int timeout, ActivityDef activityDef) {
|
||||||
|
Annotators.recordAnnotation(Annotation.newBuilder()
|
||||||
|
.session(sessionId)
|
||||||
|
.now()
|
||||||
|
.layer(Layer.Activity)
|
||||||
|
.label("alias", activityDef.getAlias())
|
||||||
|
.detail("command", "run")
|
||||||
|
.detail("params", activityDef.toString())
|
||||||
|
.build());
|
||||||
|
|
||||||
ActivityExecutor activityExecutor = getActivityExecutor(activityDef, true);
|
ActivityExecutor activityExecutor = getActivityExecutor(activityDef, true);
|
||||||
scenariologger.debug("RUN alias=" + activityDef.getAlias());
|
scenariologger.debug("RUN alias=" + activityDef.getAlias());
|
||||||
scenariologger.debug(" (RUN/START) alias=" + activityDef.getAlias());
|
scenariologger.debug(" (RUN/START) alias=" + activityDef.getAlias());
|
||||||
@ -135,6 +163,15 @@ public class ScenarioController {
|
|||||||
* @param activityDef An activity def, including at least the alias parameter.
|
* @param activityDef An activity def, including at least the alias parameter.
|
||||||
*/
|
*/
|
||||||
public synchronized void stop(ActivityDef activityDef) {
|
public synchronized void stop(ActivityDef activityDef) {
|
||||||
|
Annotators.recordAnnotation(Annotation.newBuilder()
|
||||||
|
.session(sessionId)
|
||||||
|
.now()
|
||||||
|
.layer(Layer.Activity)
|
||||||
|
.label("alias", activityDef.getAlias())
|
||||||
|
.detail("command", "stop")
|
||||||
|
.detail("params", activityDef.toString())
|
||||||
|
.build());
|
||||||
|
|
||||||
ActivityExecutor activityExecutor = getActivityExecutor(activityDef, false);
|
ActivityExecutor activityExecutor = getActivityExecutor(activityDef, false);
|
||||||
if (activityExecutor == null) {
|
if (activityExecutor == null) {
|
||||||
throw new RuntimeException("could not stop missing activity:" + activityDef);
|
throw new RuntimeException("could not stop missing activity:" + activityDef);
|
||||||
@ -345,15 +382,33 @@ public class ScenarioController {
|
|||||||
* @return true, if all activities completed before the timer expired, false otherwise
|
* @return true, if all activities completed before the timer expired, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean awaitCompletion(int waitTimeMillis) {
|
public boolean awaitCompletion(int waitTimeMillis) {
|
||||||
boolean completed = false;
|
boolean completed = true;
|
||||||
for (ActivityExecutor executor : activityExecutors.values()) {
|
long waitstart = System.currentTimeMillis();
|
||||||
if (!executor.awaitCompletion(waitTimeMillis)) {
|
long remaining = waitTimeMillis;
|
||||||
logger.debug("awaiting completion signaled FALSE");
|
|
||||||
return false;
|
List<ActivityFinisher> finishers = new ArrayList<>();
|
||||||
|
for (ActivityExecutor ae : activityExecutors.values()) {
|
||||||
|
ActivityFinisher finisher = new ActivityFinisher(ae, (int) remaining);
|
||||||
|
finishers.add(finisher);
|
||||||
|
finisher.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ActivityFinisher finisher : finishers) {
|
||||||
|
try {
|
||||||
|
finisher.join(waitTimeMillis);
|
||||||
|
} catch (InterruptedException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug("All activities awaiting completion signaled TRUE");
|
|
||||||
return true;
|
for (ActivityFinisher finisher : finishers) {
|
||||||
|
if (!finisher.getResult()) {
|
||||||
|
logger.debug("finisher for " + finisher.getName() + " did not signal TRUE");
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return completed;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActivityDef aliasToDef(String alias) {
|
private ActivityDef aliasToDef(String alias) {
|
||||||
@ -367,6 +422,7 @@ public class ScenarioController {
|
|||||||
public boolean await(Map<String, String> activityDefMap) {
|
public boolean await(Map<String, String> activityDefMap) {
|
||||||
return this.awaitActivity(activityDefMap);
|
return this.awaitActivity(activityDefMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean awaitActivity(Map<String, String> activityDefMap) {
|
public boolean awaitActivity(Map<String, String> activityDefMap) {
|
||||||
ActivityDef ad = new ActivityDef(new ParameterMap(activityDefMap));
|
ActivityDef ad = new ActivityDef(new ParameterMap(activityDefMap));
|
||||||
return awaitActivity(ad);
|
return awaitActivity(ad);
|
||||||
@ -375,6 +431,7 @@ public class ScenarioController {
|
|||||||
public boolean await(String alias) {
|
public boolean await(String alias) {
|
||||||
return this.awaitActivity(alias);
|
return this.awaitActivity(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean awaitActivity(String alias) {
|
public boolean awaitActivity(String alias) {
|
||||||
ActivityDef toAwait = aliasToDef(alias);
|
ActivityDef toAwait = aliasToDef(alias);
|
||||||
return awaitActivity(toAwait);
|
return awaitActivity(toAwait);
|
||||||
@ -383,6 +440,7 @@ public class ScenarioController {
|
|||||||
public boolean await(ActivityDef activityDef) {
|
public boolean await(ActivityDef activityDef) {
|
||||||
return this.awaitActivity(activityDef);
|
return this.awaitActivity(activityDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean awaitActivity(ActivityDef activityDef) {
|
public boolean awaitActivity(ActivityDef activityDef) {
|
||||||
ActivityExecutor activityExecutor = getActivityExecutor(activityDef, false);
|
ActivityExecutor activityExecutor = getActivityExecutor(activityDef, false);
|
||||||
if (activityExecutor == null) {
|
if (activityExecutor == null) {
|
||||||
|
@ -56,14 +56,19 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
public class Scenario implements Callable<ScenarioResult> {
|
public class Scenario implements Callable<ScenarioResult> {
|
||||||
|
|
||||||
|
private final String commandLine;
|
||||||
private Logger logger = LogManager.getLogger("SCENARIO");
|
private Logger logger = LogManager.getLogger("SCENARIO");
|
||||||
|
|
||||||
private State state = State.Scheduled;
|
private State state = State.Scheduled;
|
||||||
|
private volatile ScenarioShutdownHook scenarioShutdownHook;
|
||||||
|
private Exception error;
|
||||||
|
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
Scheduled,
|
Scheduled,
|
||||||
Running,
|
Running,
|
||||||
Errored,
|
Errored,
|
||||||
|
Interrupted,
|
||||||
Finished
|
Finished
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +101,8 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
String progressInterval,
|
String progressInterval,
|
||||||
boolean wantsGraaljsCompatMode,
|
boolean wantsGraaljsCompatMode,
|
||||||
boolean wantsStackTraces,
|
boolean wantsStackTraces,
|
||||||
boolean wantsCompiledScript) {
|
boolean wantsCompiledScript,
|
||||||
|
String commandLine) {
|
||||||
this.scenarioName = scenarioName;
|
this.scenarioName = scenarioName;
|
||||||
this.scriptfile = scriptfile;
|
this.scriptfile = scriptfile;
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
@ -104,6 +110,7 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
this.wantsGraaljsCompatMode = wantsGraaljsCompatMode;
|
this.wantsGraaljsCompatMode = wantsGraaljsCompatMode;
|
||||||
this.wantsStackTraces = wantsStackTraces;
|
this.wantsStackTraces = wantsStackTraces;
|
||||||
this.wantsCompiledScript = wantsCompiledScript;
|
this.wantsCompiledScript = wantsCompiledScript;
|
||||||
|
this.commandLine = commandLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Scenario setLogger(Logger logger) {
|
public Scenario setLogger(Logger logger) {
|
||||||
@ -118,6 +125,7 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
public Scenario(String name, Engine engine) {
|
public Scenario(String name, Engine engine) {
|
||||||
this.scenarioName = name;
|
this.scenarioName = name;
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
|
this.commandLine = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public Scenario addScriptText(String scriptText) {
|
public Scenario addScriptText(String scriptText) {
|
||||||
@ -180,7 +188,7 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
scenarioController = new ScenarioController();
|
scenarioController = new ScenarioController(this.scenarioName);
|
||||||
if (!progressInterval.equals("disabled")) {
|
if (!progressInterval.equals("disabled")) {
|
||||||
activityProgressIndicator = new ActivityProgressIndicator(scenarioController, progressInterval);
|
activityProgressIndicator = new ActivityProgressIndicator(scenarioController, progressInterval);
|
||||||
}
|
}
|
||||||
@ -229,6 +237,9 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
|
scenarioShutdownHook = new ScenarioShutdownHook(this);
|
||||||
|
Runtime.getRuntime().addShutdownHook(scenarioShutdownHook);
|
||||||
|
|
||||||
state = State.Running;
|
state = State.Running;
|
||||||
|
|
||||||
startedAtMillis = System.currentTimeMillis();
|
startedAtMillis = System.currentTimeMillis();
|
||||||
@ -237,7 +248,6 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
.session(this.scenarioName)
|
.session(this.scenarioName)
|
||||||
.now()
|
.now()
|
||||||
.layer(Layer.Scenario)
|
.layer(Layer.Scenario)
|
||||||
.label("scenario", getScenarioName())
|
|
||||||
.detail("engine", this.engine.toString())
|
.detail("engine", this.engine.toString())
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
@ -285,11 +295,9 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
this.state = State.Errored;
|
this.state = State.Errored;
|
||||||
logger.warn("Error in scenario, shutting down.");
|
logger.warn("Error in scenario, shutting down.");
|
||||||
this.scenarioController.forceStopScenario(5000, false);
|
this.scenarioController.forceStopScenario(5000, false);
|
||||||
|
this.error = e;
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} finally {
|
} finally {
|
||||||
if (this.state==State.Running) {
|
|
||||||
this.state = State.Finished;
|
|
||||||
}
|
|
||||||
System.out.flush();
|
System.out.flush();
|
||||||
System.err.flush();
|
System.err.flush();
|
||||||
endedAtMillis = System.currentTimeMillis();
|
endedAtMillis = System.currentTimeMillis();
|
||||||
@ -300,8 +308,38 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
scenarioController.awaitCompletion(awaitCompletionTime);
|
scenarioController.awaitCompletion(awaitCompletionTime);
|
||||||
//TODO: Ensure control flow covers controller shutdown in event of internal error.
|
//TODO: Ensure control flow covers controller shutdown in event of internal error.
|
||||||
|
|
||||||
logger.debug("scenario completed without errors");
|
Runtime.getRuntime().removeShutdownHook(scenarioShutdownHook);
|
||||||
|
scenarioShutdownHook = null;
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish() {
|
||||||
|
logger.debug("finishing scenario");
|
||||||
endedAtMillis = System.currentTimeMillis(); //TODO: Make only one endedAtMillis assignment
|
endedAtMillis = System.currentTimeMillis(); //TODO: Make only one endedAtMillis assignment
|
||||||
|
if (this.state == State.Running) {
|
||||||
|
this.state = State.Finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scenarioShutdownHook != null) {
|
||||||
|
// If this method was called while the shutdown hook is defined, then it means
|
||||||
|
// that the scenario was ended before the hook was uninstalled normally.
|
||||||
|
this.state = State.Interrupted;
|
||||||
|
logger.warn("Scenario was interrupted by process exit, shutting down");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("scenario state: " + this.state);
|
||||||
|
|
||||||
|
// We report the scenario state via annotation even for short runs
|
||||||
|
Annotation annotation = Annotation.newBuilder()
|
||||||
|
.session(this.scenarioName)
|
||||||
|
.interval(this.startedAtMillis, endedAtMillis)
|
||||||
|
.layer(Layer.Scenario)
|
||||||
|
.label("state", this.state.toString())
|
||||||
|
.detail("command_line", this.commandLine)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Annotators.recordAnnotation(annotation);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getStartedAtMillis() {
|
public long getStartedAtMillis() {
|
||||||
@ -315,7 +353,7 @@ public class Scenario implements Callable<ScenarioResult> {
|
|||||||
public ScenarioResult call() {
|
public ScenarioResult call() {
|
||||||
run();
|
run();
|
||||||
String iolog = scriptEnv.getTimedLog();
|
String iolog = scriptEnv.getTimedLog();
|
||||||
return new ScenarioResult(iolog);
|
return new ScenarioResult(iolog, this.startedAtMillis, this.endedAtMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -149,7 +149,8 @@ public class ScenariosExecutor {
|
|||||||
try {
|
try {
|
||||||
oResult = Optional.of(resultFuture.get());
|
oResult = Optional.of(resultFuture.get());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
oResult = Optional.of(new ScenarioResult(e));
|
long now = System.currentTimeMillis();
|
||||||
|
oResult = Optional.of(new ScenarioResult(e, now, now));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,14 +183,15 @@ public class ScenariosExecutor {
|
|||||||
if (resultFuture1 == null) {
|
if (resultFuture1 == null) {
|
||||||
throw new BasicError("Unknown scenario name:" + scenarioName);
|
throw new BasicError("Unknown scenario name:" + scenarioName);
|
||||||
}
|
}
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
if (resultFuture1.isDone()) {
|
if (resultFuture1.isDone()) {
|
||||||
try {
|
try {
|
||||||
return Optional.ofNullable(resultFuture1.get());
|
return Optional.ofNullable(resultFuture1.get());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return Optional.of(new ScenarioResult(e));
|
return Optional.of(new ScenarioResult(e, now, now));
|
||||||
}
|
}
|
||||||
} else if (resultFuture1.isCancelled()) {
|
} else if (resultFuture1.isCancelled()) {
|
||||||
return Optional.of(new ScenarioResult(new Exception("result was cancelled.")));
|
return Optional.of(new ScenarioResult(new Exception("result was cancelled."), now, now));
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
@ -108,8 +108,8 @@ public class ScenarioExecutorEndpoint implements WebServiceObject {
|
|||||||
"disabled",
|
"disabled",
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
false
|
false,
|
||||||
);
|
cmdList.toString());
|
||||||
|
|
||||||
scenario.addScriptText(buffer.getParsedScript());
|
scenario.addScriptText(buffer.getParsedScript());
|
||||||
|
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package io.nosqlbench.nb.api.annotations;
|
||||||
|
|
||||||
|
public enum Span {
|
||||||
|
/**
|
||||||
|
* A span of time of size zero.
|
||||||
|
*/
|
||||||
|
instant,
|
||||||
|
/**
|
||||||
|
* A span in time for which the start and end are different.
|
||||||
|
*/
|
||||||
|
interval
|
||||||
|
}
|
@ -26,6 +26,7 @@ public class AnnotationBuilderTest {
|
|||||||
String represented = an1.toString();
|
String represented = an1.toString();
|
||||||
assertThat(represented).isEqualTo("session: test-session\n" +
|
assertThat(represented).isEqualTo("session: test-session\n" +
|
||||||
"[2020-09-13T12:26:40Z[GMT]]\n" +
|
"[2020-09-13T12:26:40Z[GMT]]\n" +
|
||||||
|
"span:instant\n" +
|
||||||
"details:\n" +
|
"details:\n" +
|
||||||
" detailk1: detailv1\n" +
|
" detailk1: detailv1\n" +
|
||||||
" detailk2: \n" +
|
" detailk2: \n" +
|
||||||
@ -38,7 +39,10 @@ public class AnnotationBuilderTest {
|
|||||||
"labels:\n" +
|
"labels:\n" +
|
||||||
" layer: Scenario\n" +
|
" layer: Scenario\n" +
|
||||||
" labelka: labelvb\n" +
|
" labelka: labelvb\n" +
|
||||||
" labelkc: labelvd\n");
|
" labelkc: labelvd\n" +
|
||||||
|
" session: test-session\n" +
|
||||||
|
" span: instant\n" +
|
||||||
|
" appname: nosqlbench\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user