more fixes

This commit is contained in:
Jonathan Shook
2023-10-23 08:41:17 -05:00
parent 0a3b827372
commit 90519b9337
13 changed files with 276 additions and 153 deletions
@@ -16,31 +16,30 @@
package io.nosqlbench.engine.cli; package io.nosqlbench.engine.cli;
import com.codahale.metrics.Gauge;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import io.nosqlbench.adapters.api.activityconfig.rawyaml.RawOpsLoader;
import io.nosqlbench.api.annotations.Annotation; import io.nosqlbench.api.annotations.Annotation;
import io.nosqlbench.api.annotations.Layer; import io.nosqlbench.api.annotations.Layer;
import io.nosqlbench.api.labels.NBLabeledElement; import io.nosqlbench.api.apps.BundledApp;
import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.api.content.Content; import io.nosqlbench.api.content.Content;
import io.nosqlbench.api.content.NBIO; import io.nosqlbench.api.content.NBIO;
import io.nosqlbench.api.engine.metrics.ActivityMetrics; import io.nosqlbench.api.engine.metrics.ActivityMetrics;
import io.nosqlbench.api.engine.metrics.instruments.NBFunctionGauge; import io.nosqlbench.api.engine.metrics.instruments.NBFunctionGauge;
import io.nosqlbench.api.errors.BasicError; import io.nosqlbench.api.errors.BasicError;
import io.nosqlbench.api.labels.NBLabeledElement;
import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.api.logging.NBLogLevel; import io.nosqlbench.api.logging.NBLogLevel;
import io.nosqlbench.api.metadata.SessionNamer; import io.nosqlbench.api.metadata.SessionNamer;
import io.nosqlbench.api.metadata.SystemId; import io.nosqlbench.api.metadata.SystemId;
import io.nosqlbench.api.apps.BundledApp;
import io.nosqlbench.engine.api.activityapi.cyclelog.outputs.cyclelog.CycleLogDumperUtility; import io.nosqlbench.engine.api.activityapi.cyclelog.outputs.cyclelog.CycleLogDumperUtility;
import io.nosqlbench.engine.api.activityapi.cyclelog.outputs.cyclelog.CycleLogImporterUtility; import io.nosqlbench.engine.api.activityapi.cyclelog.outputs.cyclelog.CycleLogImporterUtility;
import io.nosqlbench.engine.api.activityapi.input.InputType; import io.nosqlbench.engine.api.activityapi.input.InputType;
import io.nosqlbench.engine.api.activityapi.output.OutputType; import io.nosqlbench.engine.api.activityapi.output.OutputType;
import io.nosqlbench.adapters.api.activityconfig.rawyaml.RawOpsLoader;
import io.nosqlbench.engine.cli.NBCLIOptions.LoggerConfigData; import io.nosqlbench.engine.cli.NBCLIOptions.LoggerConfigData;
import io.nosqlbench.engine.cli.NBCLIOptions.Mode; import io.nosqlbench.engine.cli.NBCLIOptions.Mode;
import io.nosqlbench.engine.core.annotation.Annotators; import io.nosqlbench.engine.core.annotation.Annotators;
import io.nosqlbench.engine.core.lifecycle.ExecutionResult;
import io.nosqlbench.engine.core.clientload.ClientSystemMetricChecker; import io.nosqlbench.engine.core.clientload.ClientSystemMetricChecker;
import io.nosqlbench.engine.core.clientload.DiskStatsReader; import io.nosqlbench.engine.core.clientload.DiskStatsReader;
import io.nosqlbench.engine.core.clientload.LoadAvgReader; import io.nosqlbench.engine.core.clientload.LoadAvgReader;
@@ -49,16 +48,12 @@ import io.nosqlbench.engine.core.clientload.NetDevReader;
import io.nosqlbench.engine.core.clientload.StatReader; import io.nosqlbench.engine.core.clientload.StatReader;
import io.nosqlbench.engine.core.lifecycle.process.NBCLIErrorHandler; import io.nosqlbench.engine.core.lifecycle.process.NBCLIErrorHandler;
import io.nosqlbench.engine.core.lifecycle.activity.ActivityTypeLoader; import io.nosqlbench.engine.core.lifecycle.activity.ActivityTypeLoader;
import io.nosqlbench.engine.core.lifecycle.process.ShutdownManager; import io.nosqlbench.engine.core.lifecycle.process.NBCLIErrorHandler;
import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosResults; import io.nosqlbench.engine.core.lifecycle.scenario.script.MetricsMapper;
import io.nosqlbench.engine.core.lifecycle.session.NBSession;
import io.nosqlbench.engine.core.logging.LoggerConfig; import io.nosqlbench.engine.core.logging.LoggerConfig;
import io.nosqlbench.engine.core.metadata.MarkdownFinder; import io.nosqlbench.engine.core.metadata.MarkdownFinder;
import io.nosqlbench.engine.core.metrics.MetricReporters; import io.nosqlbench.engine.core.metrics.MetricReporters;
import io.nosqlbench.engine.core.lifecycle.scenario.script.MetricsMapper;
import io.nosqlbench.engine.core.lifecycle.scenario.Scenario;
import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosExecutor;
import io.nosqlbench.engine.core.lifecycle.scenario.script.ScriptParams;
import io.nosqlbench.nb.annotations.Maturity;
import io.nosqlbench.nb.annotations.Service; import io.nosqlbench.nb.annotations.Service;
import io.nosqlbench.nb.annotations.ServiceSelector; import io.nosqlbench.nb.annotations.ServiceSelector;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@@ -175,17 +170,17 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
.and(globalOptions.getLabelMap()); .and(globalOptions.getLabelMap());
NBCLI.loggerConfig NBCLI.loggerConfig
.setSessionName(sessionName) .setSessionName(sessionName)
.setConsoleLevel(globalOptions.getConsoleLogLevel()) .setConsoleLevel(globalOptions.getConsoleLogLevel())
.setConsolePattern(globalOptions.getConsoleLoggingPattern()) .setConsolePattern(globalOptions.getConsoleLoggingPattern())
.setLogfileLevel(globalOptions.getScenarioLogLevel()) .setLogfileLevel(globalOptions.getScenarioLogLevel())
.setLogfilePattern(globalOptions.getLogfileLoggingPattern()) .setLogfilePattern(globalOptions.getLogfileLoggingPattern())
.setLoggerLevelOverrides(globalOptions.getLogLevelOverrides()) .setLoggerLevelOverrides(globalOptions.getLogLevelOverrides())
.setMaxLogs(globalOptions.getLogsMax()) .setMaxLogs(globalOptions.getLogsMax())
.setLogsDirectory(globalOptions.getLogsDirectory()) .setLogsDirectory(globalOptions.getLogsDirectory())
.setAnsiEnabled(globalOptions.isEnableAnsi()) .setAnsiEnabled(globalOptions.isEnableAnsi())
.setDedicatedVerificationLogger(globalOptions.isDedicatedVerificationLogger()) .setDedicatedVerificationLogger(globalOptions.isDedicatedVerificationLogger())
.activate(); .activate();
ConfigurationFactory.setConfigurationFactory(NBCLI.loggerConfig); ConfigurationFactory.setConfigurationFactory(NBCLI.loggerConfig);
NBCLI.logger = LogManager.getLogger("NBCLI"); NBCLI.logger = LogManager.getLogger("NBCLI");
@@ -282,7 +277,7 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
} }
if (options.getWantsListCommands()) { if (options.getWantsListCommands()) {
NBCLICommandParser.RESERVED_WORDS.forEach(System.out::println); SessionCommandParser.RESERVED_WORDS.forEach(System.out::println);
return NBCLI.EXIT_OK; return NBCLI.EXIT_OK;
} }
if (options.wantsActivityTypes()) { if (options.wantsActivityTypes()) {
@@ -310,19 +305,19 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
NBCLI.logger.debug(() -> "user requests to copy out " + resourceToCopy); NBCLI.logger.debug(() -> "user requests to copy out " + resourceToCopy);
Optional<Content<?>> tocopy = NBIO.classpath() Optional<Content<?>> tocopy = NBIO.classpath()
.searchPrefixes("activities") .searchPrefixes("activities")
.searchPrefixes(options.wantsIncludes()) .searchPrefixes(options.wantsIncludes())
.pathname(resourceToCopy).extensionSet(RawOpsLoader.YAML_EXTENSIONS).first(); .pathname(resourceToCopy).extensionSet(RawOpsLoader.YAML_EXTENSIONS).first();
if (tocopy.isEmpty()) tocopy = NBIO.classpath() if (tocopy.isEmpty()) tocopy = NBIO.classpath()
.searchPrefixes().searchPrefixes(options.wantsIncludes()) .searchPrefixes().searchPrefixes(options.wantsIncludes())
.searchPrefixes(options.wantsIncludes()) .searchPrefixes(options.wantsIncludes())
.pathname(resourceToCopy).first(); .pathname(resourceToCopy).first();
final Content<?> data = tocopy.orElseThrow( final Content<?> data = tocopy.orElseThrow(
() -> new BasicError( () -> new BasicError(
"Unable to find " + resourceToCopy + "Unable to find " + resourceToCopy +
" in classpath to copy out") " in classpath to copy out")
); );
final Path writeTo = Path.of(data.asPath().getFileName().toString()); final Path writeTo = Path.of(data.asPath().getFileName().toString());
@@ -360,7 +355,7 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
if (options.wantsTopicalHelp()) { if (options.wantsTopicalHelp()) {
final Optional<String> helpDoc = MarkdownFinder.forHelpTopic(options.wantsTopicalHelpFor()); final Optional<String> helpDoc = MarkdownFinder.forHelpTopic(options.wantsTopicalHelpFor());
System.out.println(helpDoc.orElseThrow( System.out.println(helpDoc.orElseThrow(
() -> new RuntimeException("No help could be found for " + options.wantsTopicalHelpFor()) () -> new RuntimeException("No help could be found for " + options.wantsTopicalHelpFor())
)); ));
return NBCLI.EXIT_OK; return NBCLI.EXIT_OK;
} }
@@ -376,23 +371,26 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
NBCLI.logger.debug("initializing annotators with config:'{}'", annotatorsConfig); NBCLI.logger.debug("initializing annotators with config:'{}'", annotatorsConfig);
Annotators.init(annotatorsConfig, options.getAnnotateLabelSpec()); Annotators.init(annotatorsConfig, options.getAnnotateLabelSpec());
Annotators.recordAnnotation( Annotators.recordAnnotation(
Annotation.newBuilder() Annotation.newBuilder()
.element(this) .element(this)
.now() .now()
.layer(Layer.Session) .layer(Layer.Session)
.addDetail("cli", String.join("\n", args)) .addDetail("cli", String.join("\n", args))
.build() .build()
); );
if ((null != reportPromPushTo) || (null != reportGraphiteTo) || (null != options.wantsReportCsvTo())) { if ((null != reportPromPushTo) || (null != reportGraphiteTo) || (null != options.wantsReportCsvTo())) {
final MetricReporters reporters = MetricReporters.getInstance(); final MetricReporters reporters = MetricReporters.getInstance();
reporters.addRegistry("workloads", ActivityMetrics.getMetricRegistry()); reporters.addRegistry("workloads", ActivityMetrics.getMetricRegistry());
if (null != reportPromPushTo) reporters.addPromPush(reportPromPushTo, options.wantsMetricsPrefix(), promPushConfig); if (null != reportPromPushTo)
reporters.addPromPush(reportPromPushTo, options.wantsMetricsPrefix(), promPushConfig);
if (null != reportGraphiteTo) reporters.addGraphite(reportGraphiteTo, options.wantsMetricsPrefix()); if (null != reportGraphiteTo) reporters.addGraphite(reportGraphiteTo, options.wantsMetricsPrefix());
if (null != options.wantsReportCsvTo()) if (null != options.wantsReportCsvTo())
reporters.addCSVReporter(options.wantsReportCsvTo(), options.wantsMetricsPrefix()); reporters.addCSVReporter(options.wantsReportCsvTo(), options.wantsMetricsPrefix());
if (options.wantsLoggedMetrics()) { reporters.addLogger(); } if (options.wantsLoggedMetrics()) {
reporters.addLogger();
}
reporters.start(10, options.getReportInterval()); reporters.start(10, options.getReportInterval());
} }
@@ -408,13 +406,13 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
} }
for ( for (
final LoggerConfigData histoLogger : options.getHistoLoggerConfigs()) final LoggerConfigData histoLogger : options.getHistoLoggerConfigs())
ActivityMetrics.addHistoLogger(sessionName, histoLogger.pattern, histoLogger.file, histoLogger.interval); ActivityMetrics.addHistoLogger(sessionName, histoLogger.pattern, histoLogger.file, histoLogger.interval);
for ( for (
final LoggerConfigData statsLogger : options.getStatsLoggerConfigs()) final LoggerConfigData statsLogger : options.getStatsLoggerConfigs())
ActivityMetrics.addStatsLogger(sessionName, statsLogger.pattern, statsLogger.file, statsLogger.interval); ActivityMetrics.addStatsLogger(sessionName, statsLogger.pattern, statsLogger.file, statsLogger.interval);
for ( for (
final LoggerConfigData classicConfigs : options.getClassicHistoConfigs()) final LoggerConfigData classicConfigs : options.getClassicHistoConfigs())
ActivityMetrics.addClassicHistos(sessionName, classicConfigs.pattern, classicConfigs.file, classicConfigs.interval); ActivityMetrics.addClassicHistos(sessionName, classicConfigs.pattern, classicConfigs.file, classicConfigs.interval);
// client machine metrics; TODO: modify pollInterval // client machine metrics; TODO: modify pollInterval
@@ -435,70 +433,29 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
NBCLI.logger.debug(() -> "enabling stack traces since log level is " + options.getConsoleLogLevel()); NBCLI.logger.debug(() -> "enabling stack traces since log level is " + options.getConsoleLogLevel());
} }
final Scenario scenario = new Scenario( // intentionally not shown for warn-only
sessionName, NBCLI.logger.info(() -> "console logging level is " + options.getConsoleLogLevel());
options.getScriptFile(),
options.getScriptingEngine(),
options.getProgressSpec(),
options.wantsStackTraces(),
options.wantsCompileScript(),
options.getReportSummaryTo(),
String.join("\n", args),
options.getLogsDirectory(),
Maturity.Unspecified,
this);
final ScriptBuffer buffer = new BasicScriptBuffer() /**
.add(options.getCommands() * At this point, the command stream from the CLI should be handed into the session, and the session should
.toArray(new Cmd[0])); * marshal and transform it for any scenario invocations directly.
final String scriptData = buffer.getParsedScript(); */
NBSession session = new NBSession(
if (options.wantsShowScript()) { this,
System.out.println("// Rendered Script"); sessionName,
System.out.println(scriptData); options.getProgressSpec(),
return NBCLI.EXIT_OK; options.getReportSummaryTo(),
} options.getLogsDirectory(),
options.getScriptFile(),
if (options.wantsEnableChart()) { options.wantsShowScript()
NBCLI.logger.info("Charting enabled"); );
scenario.enableCharting(); ExecutionResult sessionResult = session.apply(options.getCommands());
} else NBCLI.logger.info("Charting disabled"); sessionResult.printSummary(System.out);
return sessionResult.getStatus().code;
// Execute Scenario!
if (0 == options.getCommands().size()) {
NBCLI.logger.info("No commands provided. Exiting before scenario.");
return NBCLI.EXIT_OK;
}
scenario.addScriptText(scriptData);
final ScriptParams scriptParams = new ScriptParams();
scriptParams.putAll(buffer.getCombinedParams());
scenario.addScenarioScriptParams(scriptParams);
scenariosExecutor.execute(scenario);
final ScenariosResults scenariosResults = scenariosExecutor.awaitAllResults();
NBCLI.logger.debug(() -> "Total of " + scenariosResults.getSize() + " result object returned from ScenariosExecutor");
clientMetricChecker.shutdown();
ActivityMetrics.closeMetrics(options.wantsEnableChart());
scenariosResults.reportToLog();
ShutdownManager.shutdown();
NBCLI.logger.info(scenariosResults.getExecutionSummary());
if (scenariosResults.hasError()) {
final Exception exception = scenariosResults.getOne().getException();
NBCLI.logger.warn(scenariosResults.getExecutionSummary());
NBCLIErrorHandler.handle(exception, options.wantsStackTraces());
System.err.println(exception.getMessage()); // TODO: make this consistent with ConsoleLogging sequencing
return NBCLI.EXIT_ERROR;
}
NBCLI.logger.info(scenariosResults.getExecutionSummary());
return NBCLI.EXIT_OK;
} }
private String loadHelpFile(final String filename) { private String loadHelpFile(final String filename) {
final ClassLoader cl = this.getClass().getClassLoader(); final ClassLoader cl = this.getClass().getClassLoader();
final InputStream resourceAsStream = cl.getResourceAsStream(filename); final InputStream resourceAsStream = cl.getResourceAsStream(filename);
@@ -16,15 +16,14 @@
package io.nosqlbench.engine.cli; package io.nosqlbench.engine.cli;
import io.nosqlbench.api.labels.NBLabelSpec;
import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.api.engine.util.Unit; import io.nosqlbench.api.engine.util.Unit;
import io.nosqlbench.api.errors.BasicError; import io.nosqlbench.api.errors.BasicError;
import io.nosqlbench.api.labels.NBLabelSpec;
import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.api.logging.NBLogLevel; import io.nosqlbench.api.logging.NBLogLevel;
import io.nosqlbench.api.system.NBStatePath; import io.nosqlbench.api.system.NBStatePath;
import io.nosqlbench.engine.api.metrics.IndicatorMode; import io.nosqlbench.engine.api.metrics.IndicatorMode;
import io.nosqlbench.engine.cli.Cmd.CmdType; import io.nosqlbench.engine.cli.Cmd.CmdType;
import io.nosqlbench.engine.core.lifecycle.scenario.Scenario.Engine;
import io.nosqlbench.nb.annotations.Maturity; import io.nosqlbench.nb.annotations.Maturity;
import java.io.File; import java.io.File;
@@ -323,7 +322,7 @@ public class NBCLIOptions {
// Now that statdirs is settled, auto load argsfile if it is present // Now that statdirs is settled, auto load argsfile if it is present
final NBCLIArgsFile argsfile = new NBCLIArgsFile(); final NBCLIArgsFile argsfile = new NBCLIArgsFile();
argsfile.reserved(NBCLICommandParser.RESERVED_WORDS); argsfile.reserved(SessionCommandParser.RESERVED_WORDS);
argsfile.preload("--argsfile-optional", NBCLIOptions.ARGS_FILE_DEFAULT); argsfile.preload("--argsfile-optional", NBCLIOptions.ARGS_FILE_DEFAULT);
arglist = argsfile.process(arglist); arglist = argsfile.process(arglist);
@@ -645,7 +644,7 @@ public class NBCLIOptions {
} }
} }
arglist = nonincludes; arglist = nonincludes;
final Optional<List<Cmd>> commands = NBCLICommandParser.parse(arglist); final Optional<List<Cmd>> commands = SessionCommandParser.parse(arglist);
if (commands.isPresent()) cmdList.addAll(commands.get()); if (commands.isPresent()) cmdList.addAll(commands.get());
else { else {
final String arg = arglist.peekFirst(); final String arg = arglist.peekFirst();
@@ -131,9 +131,9 @@ public class BasicScriptBuffer implements ScriptBuffer {
return scriptParams; return scriptParams;
} }
public static String assemble(NBCLIOptions options) { public static String assemble(List<Cmd> cmds) {
ScriptBuffer script = new BasicScriptBuffer(); ScriptBuffer script = new BasicScriptBuffer();
for (Cmd command : options.getCommands()) { for (Cmd command : cmds) {
script.add(command); script.add(command);
} }
return script.getParsedScript(); return script.getParsedScript();
@@ -154,9 +154,9 @@ public class Cmd {
logger.debug(() -> "freeform parameter:" + nextarg); logger.debug(() -> "freeform parameter:" + nextarg);
} else if (nextarg.contains("=")) { } else if (nextarg.contains("=")) {
throw new InvalidParameterException( throw new InvalidParameterException(
"command '" + cmdName + "' requires a value for " + arg.name + "" + "command '" + cmdName + "' requires a value for " + arg.name +
", but a named parameter was found instead: " + nextarg); ", but a named parameter was found instead: " + nextarg);
} else if (NBCLICommandParser.RESERVED_WORDS.contains(nextarg)) { } else if (SessionCommandParser.RESERVED_WORDS.contains(nextarg)) {
throw new InvalidParameterException( throw new InvalidParameterException(
"command '" + cmdName + "' requires a value for " + arg.name "command '" + cmdName + "' requires a value for " + arg.name
+ ", but a reserved word was found instead: " + nextarg); + ", but a reserved word was found instead: " + nextarg);
@@ -167,7 +167,7 @@ public class Cmd {
} }
while (arglist.size() > 0 && while (arglist.size() > 0 &&
!NBCLICommandParser.RESERVED_WORDS.contains(arglist.peekFirst()) !SessionCommandParser.RESERVED_WORDS.contains(arglist.peekFirst())
&& arglist.peekFirst().contains("=")) { && arglist.peekFirst().contains("=")) {
String arg = arglist.removeFirst(); String arg = arglist.removeFirst();
String[] assigned = arg.split("=", 2); String[] assigned = arg.split("=", 2);
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022 nosqlbench * Copyright (c) 2022-2023 nosqlbench
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ import java.util.*;
* If the optional is empty, then it means some part of the command structure * If the optional is empty, then it means some part of the command structure
* was not recognized. * was not recognized.
*/ */
public class NBCLICommandParser { public class SessionCommandParser {
private static final String FRAGMENT = "fragment"; private static final String FRAGMENT = "fragment";
private static final String SCRIPT = "script"; private static final String SCRIPT = "script";
@@ -19,6 +19,8 @@ package io.nosqlbench.engine.core.lifecycle;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.io.PrintStream;
/** /**
* Provide a result type back to a caller, including the start and end times, * Provide a result type back to a caller, including the start and end times,
* any exception that occurred, and any content written to stdout or stderr equivalent * any exception that occurred, and any content written to stdout or stderr equivalent
@@ -27,6 +29,22 @@ import org.apache.logging.log4j.Logger;
*/ */
public class ExecutionResult { public class ExecutionResult {
protected final static Logger logger = LogManager.getLogger(ExecutionResult.class); protected final static Logger logger = LogManager.getLogger(ExecutionResult.class);
protected final Status status;
public void printSummary(PrintStream out) {
out.println(this);
}
public enum Status {
OK(0),
WARNING(1),
ERROR(2);
public final int code;
Status(int code) {
this.code = code;
}
}
protected final long startedAt; protected final long startedAt;
protected final long endedAt; protected final long endedAt;
protected final Exception exception; protected final Exception exception;
@@ -37,7 +55,9 @@ public class ExecutionResult {
this.endedAt = endedAt; this.endedAt = endedAt;
this.exception = error; this.exception = error;
this.iolog = ((iolog != null) ? iolog + "\n\n" : "") + exception; this.iolog = ((iolog != null) ? iolog + "\n\n" : "") + exception;
logger.debug("populating "+(error==null ? "NORMAL" : "ERROR")+" scenario result"); this.status = (error==null) ? Status.OK : Status.ERROR;
logger.debug("populating "+status+" scenario result");
// if (logger.isTraceEnabled()) { // if (logger.isTraceEnabled()) {
// StackTraceElement[] st = Thread.currentThread().getStackTrace(); // StackTraceElement[] st = Thread.currentThread().getStackTrace();
// for (int i = 0; i < st.length; i++) { // for (int i = 0; i < st.length; i++) {
@@ -63,4 +83,10 @@ public class ExecutionResult {
public Exception getException() { public Exception getException() {
return exception; return exception;
} }
public Status getStatus() {
return this.status;
}
} }
@@ -21,22 +21,18 @@ import io.nosqlbench.api.annotations.Annotation;
import io.nosqlbench.api.annotations.Layer; import io.nosqlbench.api.annotations.Layer;
import io.nosqlbench.api.labels.NBLabeledElement; import io.nosqlbench.api.labels.NBLabeledElement;
import io.nosqlbench.api.labels.NBLabels; import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.api.engine.metrics.ActivityMetrics;
import io.nosqlbench.api.metadata.ScenarioMetadata; import io.nosqlbench.api.metadata.ScenarioMetadata;
import io.nosqlbench.api.metadata.ScenarioMetadataAware; import io.nosqlbench.api.metadata.ScenarioMetadataAware;
import io.nosqlbench.api.metadata.SystemId; import io.nosqlbench.api.metadata.SystemId;
import io.nosqlbench.api.extensions.ScriptingExtensionPluginInfo;
import io.nosqlbench.engine.api.scripting.ScriptEnvBuffer; import io.nosqlbench.engine.api.scripting.ScriptEnvBuffer;
import io.nosqlbench.engine.core.annotation.Annotators; import io.nosqlbench.engine.core.annotation.Annotators;
import io.nosqlbench.engine.core.lifecycle.ExecutionMetricsResult; import io.nosqlbench.engine.core.lifecycle.ExecutionMetricsResult;
import io.nosqlbench.engine.core.lifecycle.activity.ActivityProgressIndicator; import io.nosqlbench.engine.core.lifecycle.activity.ActivityProgressIndicator;
import io.nosqlbench.api.extensions.SandboxExtensionFinder;
import io.nosqlbench.engine.core.lifecycle.scenario.script.ScenarioContext; import io.nosqlbench.engine.core.lifecycle.scenario.script.ScenarioContext;
import io.nosqlbench.engine.core.lifecycle.scenario.script.ScriptParams; import io.nosqlbench.engine.core.lifecycle.scenario.script.ScriptParams;
import io.nosqlbench.engine.core.lifecycle.scenario.script.bindings.ActivityBindings; import io.nosqlbench.engine.core.lifecycle.scenario.script.bindings.ActivityBindings;
import io.nosqlbench.engine.core.lifecycle.scenario.script.bindings.PolyglotMetricRegistryBindings; import io.nosqlbench.engine.core.lifecycle.scenario.script.bindings.PolyglotMetricRegistryBindings;
import io.nosqlbench.engine.core.lifecycle.scenario.script.bindings.PolyglotScenarioController; import io.nosqlbench.engine.core.lifecycle.scenario.script.bindings.PolyglotScenarioController;
import io.nosqlbench.nb.annotations.Maturity;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.graalvm.polyglot.Context; import org.graalvm.polyglot.Context;
@@ -58,14 +54,13 @@ import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.*; import java.util.*;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.stream.Collectors;
public class Scenario implements Callable<ExecutionMetricsResult>, NBLabeledElement { public class Scenario implements Callable<ExecutionMetricsResult>, NBLabeledElement {
private final String commandLine;
private final String reportSummaryTo; private final String reportSummaryTo;
private final Path logsPath; private final Path logsPath;
private final Maturity minMaturity; private final Invocation invocation;
private final String scriptfile;
private Logger logger = LogManager.getLogger("SCENARIO"); private Logger logger = LogManager.getLogger("SCENARIO");
private State state = State.Scheduled; private State state = State.Scheduled;
@@ -80,6 +75,11 @@ public class Scenario implements Callable<ExecutionMetricsResult>, NBLabeledElem
return Optional.ofNullable(result); return Optional.ofNullable(result);
} }
public enum Invocation {
RENDER_SCRIPT,
EXECUTE_SCRIPT
}
@Override @Override
public NBLabels getLabels() { public NBLabels getLabels() {
return this.parentComponent.getLabels().and("scenario", this.scenarioName); return this.parentComponent.getLabels().and("scenario", this.scenarioName);
@@ -92,6 +92,7 @@ public class Scenario implements Callable<ExecutionMetricsResult>, NBLabeledElem
Interrupted, Interrupted,
Finished Finished
} }
private final List<String> scripts = new ArrayList<>(); private final List<String> scripts = new ArrayList<>();
private ScriptEngine scriptEngine; private ScriptEngine scriptEngine;
private ScenarioController scenarioController; private ScenarioController scenarioController;
@@ -100,10 +101,7 @@ public class Scenario implements Callable<ExecutionMetricsResult>, NBLabeledElem
private ScenarioContext scriptEnv; private ScenarioContext scriptEnv;
private final String scenarioName; private final String scenarioName;
private ScriptParams scenarioScriptParams; private ScriptParams scenarioScriptParams;
private final String scriptfile; private final Engine engine = Engine.Graalvm;
private Engine engine = Engine.Graalvm;
private final boolean wantsStackTraces;
private final boolean wantsCompiledScript;
private long startedAtMillis = -1L; private long startedAtMillis = -1L;
private long endedAtMillis = -1L; private long endedAtMillis = -1L;
@@ -113,32 +111,34 @@ public class Scenario implements Callable<ExecutionMetricsResult>, NBLabeledElem
public Scenario( public Scenario(
final String scenarioName, final String scenarioName,
final String scriptfile,
final Engine engine,
final String progressInterval, final String progressInterval,
final boolean wantsStackTraces,
final boolean wantsCompiledScript,
final String reportSummaryTo, final String reportSummaryTo,
final String commandLine,
final Path logsPath, final Path logsPath,
final Maturity minMaturity, String scriptfile,
NBLabeledElement parentComponent) { NBComponent parentComponent,
Invocation invocation
) {
super(parentComponent, NBLabels.forKV("scenario", scenarioName));
this.scenarioName = scenarioName; this.scenarioName = scenarioName;
this.scriptfile = scriptfile;
this.engine = engine;
this.progressInterval = progressInterval; this.progressInterval = progressInterval;
this.wantsStackTraces = wantsStackTraces;
this.wantsCompiledScript = wantsCompiledScript;
this.reportSummaryTo = reportSummaryTo; this.reportSummaryTo = reportSummaryTo;
this.commandLine = commandLine;
this.logsPath = logsPath; this.logsPath = logsPath;
this.minMaturity = minMaturity; this.scriptfile = scriptfile;
this.parentComponent = parentComponent; this.parentComponent = parentComponent;
this.invocation = invocation;
} }
public static Scenario forTesting(final String name, final Engine engine, final String reportSummaryTo, final Maturity minMaturity) { public static Scenario forTesting(final String name, final String reportSummaryTo, NBComponent parent) {
return new Scenario(name, null, engine, "console:10s", true, true, reportSummaryTo, "", Path.of("logs"), minMaturity, NBLabeledElement.forKV("test_name", "name"));
return new Scenario(
name,
"console:10s",
reportSummaryTo,
Path.of("logs"),
"",
new NBBaseComponent(parent,NBLabels.forKV("test","testrun")),
Invocation.EXECUTE_SCRIPT
);
} }
public Scenario setLogger(final Logger logger) { public Scenario setLogger(final Logger logger) {
@@ -351,7 +351,7 @@ public class Scenario implements Callable<ExecutionMetricsResult>, NBLabeledElem
.element(this) .element(this)
.interval(startedAtMillis, this.endedAtMillis) .interval(startedAtMillis, this.endedAtMillis)
.layer(Layer.Scenario) .layer(Layer.Scenario)
.addDetail("event","stop-scenario") .addDetail("event", "stop-scenario")
.build(); .build();
Annotators.recordAnnotation(annotation); Annotators.recordAnnotation(annotation);
@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022 nosqlbench * Copyright (c) 2022-2023 nosqlbench
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -17,11 +17,14 @@
package io.nosqlbench.engine.core.lifecycle.scenario; package io.nosqlbench.engine.core.lifecycle.scenario;
import io.nosqlbench.engine.core.lifecycle.ExecutionMetricsResult; import io.nosqlbench.engine.core.lifecycle.ExecutionMetricsResult;
import org.apache.logging.log4j.Logger; import io.nosqlbench.engine.core.lifecycle.ExecutionResult;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional;
public class ScenariosResults { public class ScenariosResults {
@@ -75,6 +78,11 @@ public class ScenariosResults {
.anyMatch(r -> r.getException()!=null); .anyMatch(r -> r.getException()!=null);
} }
public Optional<Exception> getAnyError() {
return this.scenarioResultMap.values().stream()
.map(ExecutionResult::getException).filter(Objects::nonNull).findFirst();
}
public int getSize() { public int getSize() {
return this.scenarioResultMap.size(); return this.scenarioResultMap.size();
} }
@@ -0,0 +1,133 @@
/*
* Copyright (c) 2023 nosqlbench
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.nosqlbench.engine.core.lifecycle.session;
import io.nosqlbench.api.config.NBComponent;
import io.nosqlbench.api.config.standard.NBBaseComponent;
import io.nosqlbench.api.engine.metrics.ActivityMetrics;
import io.nosqlbench.api.labels.NBLabels;
import io.nosqlbench.engine.cli.BasicScriptBuffer;
import io.nosqlbench.engine.cli.Cmd;
import io.nosqlbench.engine.cli.ScriptBuffer;
import io.nosqlbench.engine.core.lifecycle.ExecutionResult;
import io.nosqlbench.engine.core.lifecycle.process.NBCLIErrorHandler;
import io.nosqlbench.engine.core.lifecycle.process.ShutdownManager;
import io.nosqlbench.engine.core.lifecycle.scenario.Scenario;
import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosExecutor;
import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosResults;
import io.nosqlbench.engine.core.lifecycle.scenario.script.ScriptParams;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Function;
/**
* A session represents a single execution of NoSQLBench, whether episodic or persistent under some service layer.
* An NBSession takes care of system level concerns like logging, annotations, error reporting, metrics flows, and so
* on.
* All NBScenarios are run within an NBSession.
*/
public class NBSession extends NBBaseComponent implements Function<List<Cmd>, ExecutionResult> {
private final static Logger logger = LogManager.getLogger(NBSession.class);
private final String sessionName;
private final String progressSpec;
private final String reportSummaryTo;
private final Path logspath;
private final boolean wantsShowScript;
private final String scriptfile;
public enum STATUS {
OK,
WARNING,
ERROR
}
public NBSession(
NBComponent parent,
String sessionName,
String progressSpec,
String reportSummaryTo,
Path logspath,
String scriptfile,
boolean wantsShowScript
) {
super(parent, NBLabels.forKV("session", sessionName));
this.sessionName = sessionName;
this.progressSpec = progressSpec;
this.reportSummaryTo = reportSummaryTo;
this.logspath = logspath;
this.scriptfile = scriptfile;
this.wantsShowScript = wantsShowScript;
}
public ExecutionResult apply(List<Cmd> cmds) {
ResultCollector collector = new ResultCollector();
try (ResultContext results = new ResultContext(collector)) {
final ScenariosExecutor scenariosExecutor = new ScenariosExecutor("executor-" + sessionName, 1);
Scenario.Invocation invocation = wantsShowScript ? Scenario.Invocation.RENDER_SCRIPT : Scenario.Invocation.EXECUTE_SCRIPT;
final Scenario scenario = new Scenario(
sessionName,
progressSpec,
reportSummaryTo,
logspath,
scriptfile,
this,
invocation
);
final ScriptBuffer buffer = new BasicScriptBuffer().add(cmds.toArray(new Cmd[0]));
final String scriptData = buffer.getParsedScript();
// Execute Scenario!
if (cmds.isEmpty()) {
logger.info("No commands provided.");
}
scenario.addScriptText(scriptData);
final ScriptParams scriptParams = new ScriptParams();
scriptParams.putAll(buffer.getCombinedParams());
scenario.addScenarioScriptParams(scriptParams);
scenariosExecutor.execute(scenario);
final ScenariosResults scenariosResults = scenariosExecutor.awaitAllResults();
logger.debug(() -> "Total of " + scenariosResults.getSize() + " result object returned from ScenariosExecutor");
ActivityMetrics.closeMetrics();
scenariosResults.reportToLog();
ShutdownManager.shutdown();
logger.info(scenariosResults.getExecutionSummary());
if (scenariosResults.hasError()) {
results.error(scenariosResults.getAnyError().orElseThrow());
final Exception exception = scenariosResults.getOne().getException();
logger.warn(scenariosResults.getExecutionSummary());
NBCLIErrorHandler.handle(exception, true);
System.err.println(exception.getMessage()); // TODO: make this consistent with ConsoleLogging sequencing
}
results.output(scenariosResults.getExecutionSummary());
}
return collector.toExecutionResult();
}
}
@@ -16,9 +16,9 @@
package io.nosqlbench.engine.core; package io.nosqlbench.engine.core;
import io.nosqlbench.api.config.standard.TestComponent;
import io.nosqlbench.engine.api.scripting.ScriptEnvBuffer; import io.nosqlbench.engine.api.scripting.ScriptEnvBuffer;
import io.nosqlbench.engine.core.lifecycle.scenario.Scenario; import io.nosqlbench.engine.core.lifecycle.scenario.Scenario;
import io.nosqlbench.nb.annotations.Maturity;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -31,7 +31,7 @@ public class ScenarioTest {
@Test @Test
public void shouldLoadScriptText() { public void shouldLoadScriptText() {
ScriptEnvBuffer buffer = new ScriptEnvBuffer(); ScriptEnvBuffer buffer = new ScriptEnvBuffer();
Scenario scenario = Scenario.forTesting("testing", Scenario.Engine.Graalvm, "stdout:300", Maturity.Any); Scenario scenario = Scenario.forTesting("testing", "stdout:300", new TestComponent());
scenario.addScriptText("print('loaded script environment...');\n"); scenario.addScriptText("print('loaded script environment...');\n");
try { try {
var result=scenario.call(); var result=scenario.call();
@@ -16,11 +16,11 @@
package io.nosqlbench.nbr.examples; package io.nosqlbench.nbr.examples;
import io.nosqlbench.api.config.standard.TestComponent;
import io.nosqlbench.engine.core.lifecycle.ExecutionMetricsResult; import io.nosqlbench.engine.core.lifecycle.ExecutionMetricsResult;
import io.nosqlbench.engine.core.lifecycle.scenario.Scenario; import io.nosqlbench.engine.core.lifecycle.scenario.Scenario;
import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosExecutor; import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosExecutor;
import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosResults; import io.nosqlbench.engine.core.lifecycle.scenario.ScenariosResults;
import io.nosqlbench.nb.annotations.Maturity;
import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.compress.utils.IOUtils;
import org.assertj.core.data.Offset; import org.assertj.core.data.Offset;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
@@ -56,7 +56,7 @@ public class ScriptExampleTests {
String scenarioName = "scenario " + scriptname; String scenarioName = "scenario " + scriptname;
System.out.println("=".repeat(29) + " Running integration test for example scenario: " + scenarioName); System.out.println("=".repeat(29) + " Running integration test for example scenario: " + scenarioName);
ScenariosExecutor executor = new ScenariosExecutor(ScriptExampleTests.class.getSimpleName() + ":" + scriptname, 1); ScenariosExecutor executor = new ScenariosExecutor(ScriptExampleTests.class.getSimpleName() + ":" + scriptname, 1);
Scenario s = Scenario.forTesting(scenarioName, Scenario.Engine.Graalvm,"stdout:300", Maturity.Any); Scenario s = Scenario.forTesting(scenarioName,"stdout:300", new TestComponent());
s.addScenarioScriptParams(paramsMap); s.addScenarioScriptParams(paramsMap);