Add NBAdvisor Framework (#2070)

* Add NBAdvisor Framework

* Revert "Add NBAdvisor Framework"

This reverts commit f2f448ffc3.

* Reapply "Add NBAdvisor Framework"

This reverts commit 8048402b88.

* Update pom.xml

* Adjust

* Fix tabs

* Revert change including test

* Simplify toString

* Advisor is now a global option

* Added error checking

* NB Advisor runtime scaffold prototype

* fix double dispatch error

* Make NBAdvisorLevel sticky and evaluate error count

* Working towards better encapsulation

* advisor refinements

* document alignment of log levels and advisor levels

* doc updates

* Evaluation refactor and fix integration tests

* Cleanup tabs

* Rename Exception

* Use a logger for output

* Small cleanup

* Remove extraneous dependency

* OF - bug fix

* Add Advisor Exception Test

---------

Co-authored-by: Jonathan Shook <jshook@gmail.com>
This commit is contained in:
Dave Fisher
2024-11-11 10:08:08 -08:00
committed by GitHub
parent 041dafa5c6
commit 7a9b2237de
30 changed files with 869 additions and 46 deletions

View File

@@ -136,12 +136,12 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
break;
}
final String error = NBCLIErrorHandler.handle(e, showStackTraces, NBCLI.version);
final int result = NBCLIErrorHandler.handle(e, showStackTraces, NBCLI.version);
// Commented for now, as the above handler should do everything needed.
if (null != error) System.err.println("Scenario stopped due to error. See logs for details.");
if (result != 0) System.err.println("Scenario stopped due to error. See logs for details.");
System.err.flush();
System.out.flush();
return NBCLI.EXIT_ERROR;
return result;
}
}
@@ -412,7 +412,8 @@ public class NBCLI implements Function<String[], Integer>, NBLabeledElement {
"logsdir", options.getLogsDirectory().toString(),
"progress", options.getProgressSpec(),
"prompush_cache", "prompush_cache.txt",
"heartbeat", String.valueOf(options.wantsHeartbeatIntervalMs())
"heartbeat", String.valueOf(options.wantsHeartbeatIntervalMs()),
"advisor", String.valueOf(options.getAdvisor())
);
try (

View File

@@ -21,6 +21,7 @@ import io.nosqlbench.engine.cli.atfiles.NBAtFile;
import io.nosqlbench.engine.cmdstream.Cmd;
import io.nosqlbench.engine.cmdstream.PathCanonicalizer;
import io.nosqlbench.engine.core.lifecycle.session.CmdParser;
import io.nosqlbench.nb.api.advisor.NBAdvisorLevel;
import io.nosqlbench.nb.api.engine.util.Unit;
import io.nosqlbench.nb.api.errors.BasicError;
import io.nosqlbench.nb.api.labels.NBLabelSpec;
@@ -96,6 +97,8 @@ public class NBCLIOptions {
private static final String ADD_LABELS = "--add-labels";
private static final String ADD_LABEL = "--add-label";
private static final String ADVISOR = "--advisor";
// Execution
private static final String EXPORT_CYCLE_LOG = "--export-cycle-log";
private static final String IMPORT_CYCLE_LOG = "--import-cycle-log";
@@ -103,7 +106,6 @@ public class NBCLIOptions {
// Execution Options
private static final String SESSION_NAME = "--session-name";
private static final String LOGS_DIR = "--logs-dir";
private static final String WORKSPACES_DIR = "--workspaces-dir";
@@ -207,6 +209,7 @@ public class NBCLIOptions {
private String reportSummaryTo = NBCLIOptions.REPORT_SUMMARY_TO_DEFAULT;
private boolean enableAnsi = (null != System.getenv("TERM")) && !System.getenv("TERM").isEmpty();
private Maturity minMaturity = Maturity.Unspecified;
private NBAdvisorLevel advisor = NBAdvisorLevel.none;
private String graphitelogLevel = "info";
private boolean wantsListCommands;
private boolean wantsListApps;
@@ -504,6 +507,12 @@ public class NBCLIOptions {
String addLabeldata = arglist.removeFirst();
addLabels(addLabeldata);
break;
case ADVISOR:
arglist.removeFirst();
final String advisorStr = this.readWordOrThrow(arglist, "advisor level for checking");
advisor = NBAdvisorLevel.fromString(advisorStr); // includes error checking. invalid values
// provide a warning.
break;
case NBCLIOptions.ENABLE_LOGGED_METRICS:
arglist.removeFirst();
this.wantsConsoleMetrics = true;
@@ -733,7 +742,7 @@ public class NBCLIOptions {
.replaceAll("ARG", cmdParam)
.replaceAll("PROG", "nb5")
.replaceAll("INCLUDES", String.join(",", wantsIncludes()))
+ (arglist.size()>0 && arglist.peekFirst().startsWith("nb") ?
+ (arglist.size() > 0 && arglist.peekFirst().startsWith("nb") ?
"""
(HINT:) It looks like you are starting your command with ARGV0
" which looks like the nb5 command itself. Maybe remove this?
@@ -800,6 +809,10 @@ public class NBCLIOptions {
return this.minMaturity;
}
public NBAdvisorLevel getAdvisor() {
return this.advisor;
}
public List<Cmd> getCommands() {
return this.cmdList;
}

View File

@@ -20,7 +20,7 @@ package io.nosqlbench.engine.api.activityimpl;
public enum Dryrun {
/**
* Ops are executed normally, no change to the dispenser behavior
* Ops are executed normally, no change to the dispenser behavior.
*/
none,
/**
@@ -32,5 +32,12 @@ public enum Dryrun {
* Ops will print the toString version of their result to stdout.
* This is done by wrapping the synthesized op in a post-emit facade.
*/
emit
emit,
/**
* Jsonnet evaluation is a one time dry-run and then exit.
* With this value the run should exit after the first evaluation of jsonnet
* and Ops are not executed, but should processing fall through then processing
* will proceed as for none.
*/
jsonnet
}

View File

@@ -43,6 +43,7 @@ public class OpWrappers {
case none -> dispenser;
case op -> new DryCycleOpDispenserWrapper(adapter, pop, dispenser);
case emit -> new EmitterCycleOpDispenserWrapper(adapter, pop, dispenser);
case jsonnet -> dispenser;
};
}
}

View File

@@ -34,7 +34,7 @@ public class ClientSystemMetricChecker extends NBBaseComponent {
private List<ClientMetric> clientMetrics;
public ClientSystemMetricChecker(NBComponent parent, NBLabels additionalLabels, int pollIntervalSeconds) {
super(parent,additionalLabels.and("_type","client-metrics"));
super(parent,additionalLabels.and("_type","client_metrics"));
this.pollIntervalSeconds = pollIntervalSeconds;
this.scheduler = Executors.newScheduledThreadPool(1);
this.clientMetrics = new ArrayList<>();

View File

@@ -17,6 +17,7 @@
package io.nosqlbench.engine.core.lifecycle.process;
import io.nosqlbench.nb.api.errors.BasicError;
import io.nosqlbench.nb.api.advisor.NBAdvisorException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.graalvm.polyglot.PolyglotException;
@@ -43,7 +44,7 @@ public class NBCLIErrorHandler {
private final static Logger logger = LogManager.getLogger("ERRORHANDLER");
public static String handle(Throwable t, boolean wantsStackTraces, String version) {
public static int handle(Throwable t, boolean wantsStackTraces, String version) {
if (wantsStackTraces) {
StackTraceElement[] st = Thread.currentThread().getStackTrace();
@@ -63,6 +64,9 @@ public class NBCLIErrorHandler {
} else if (t instanceof BasicError) {
logger.trace("Handling basic error: " + t);
return handleBasicError((BasicError) t, wantsStackTraces, version);
} else if (t instanceof NBAdvisorException) {
logger.trace("Handle processing early exit: " + t);
return handleNBAdvisorException((NBAdvisorException) t, wantsStackTraces, version);
} else if (t instanceof Exception) {
logger.trace("Handling general exception: " + t);
return handleInternalError((Exception) t, wantsStackTraces, version);
@@ -72,7 +76,7 @@ public class NBCLIErrorHandler {
}
}
private static String handleInternalError(Exception e, boolean wantsStackTraces, String version) {
private static int handleInternalError(Exception e, boolean wantsStackTraces, String version) {
String prefix = "internal error(" + version + "):";
if (e.getCause() != null && !e.getCause().getClass().getCanonicalName().contains("io.nosqlbench")) {
prefix = "Error from driver or included library(" + version + "):";
@@ -87,10 +91,10 @@ public class NBCLIErrorHandler {
logger.error(e.getMessage());
logger.error("for the full stack trace, run with --show-stacktraces");
}
return e.getMessage();
return 2;
}
private static String handleScriptException(ScriptException e, boolean wantsStackTraces, String version) {
private static int handleScriptException(ScriptException e, boolean wantsStackTraces, String version) {
Throwable cause = e.getCause();
if (cause instanceof PolyglotException) {
Throwable hostException = ((PolyglotException) cause).asHostException();
@@ -107,17 +111,22 @@ public class NBCLIErrorHandler {
logger.error("for the full stack trace, run with --show-stacktraces");
}
}
return e.getMessage();
return 2;
}
private static String handleBasicError(BasicError e, boolean wantsStackTraces, String version) {
private static int handleBasicError(BasicError e, boolean wantsStackTraces, String version) {
if (wantsStackTraces) {
logger.error(e.getMessage(), e);
} else {
logger.error(e.getMessage());
logger.error("for the full stack trace, run with --show-stacktraces");
}
return e.getMessage();
return 2;
}
private static int handleNBAdvisorException(NBAdvisorException e, boolean wantsStackTraces, String version) {
logger.info(e.toString());
return e.getExitCode();
}
}

View File

@@ -18,6 +18,7 @@ package io.nosqlbench.engine.core;
import io.nosqlbench.nb.api.config.standard.TestComponent;
import io.nosqlbench.nb.api.engine.activityimpl.ActivityDef;
import io.nosqlbench.nb.api.advisor.NBAdvisorException;
import io.nosqlbench.engine.api.activityapi.core.*;
import io.nosqlbench.engine.api.activityapi.input.Input;
import io.nosqlbench.engine.api.activityapi.input.InputDispenser;
@@ -81,10 +82,24 @@ class ActivityExecutorTest {
//
// }
@Test
synchronized void testAdvisorError() {
try {
ActivityDef activityDef = ActivityDef.parseActivityDef("driver=diag;alias=test-delayed-start;cycles=1000;initdelay=2000;");
new ActivityTypeLoader().load(activityDef, TestComponent.INSTANCE);
Activity activity = new DelayedInitActivity(activityDef);
fail("Expected an Advisor exception");
} catch (NBAdvisorException e) {
assertThat(e.toString().contains("error"));
assertThat(e.getExitCode() == 2);
}
}
@Test
synchronized void testDelayedStartSanity() {
ActivityDef activityDef = ActivityDef.parseActivityDef("driver=diag;alias=test-delayed-start;cycles=1000;initdelay=2000;");
ActivityDef activityDef = ActivityDef.parseActivityDef("driver=diag;alias=test_delayed_start;cycles=1000;initdelay=2000;");
new ActivityTypeLoader().load(activityDef, TestComponent.INSTANCE);
Activity activity = new DelayedInitActivity(activityDef);
@@ -118,7 +133,7 @@ class ActivityExecutorTest {
@Test
synchronized void testNewActivityExecutor() {
final ActivityDef activityDef = ActivityDef.parseActivityDef("driver=diag;alias=test-dynamic-params;cycles=1000;initdelay=5000;");
final ActivityDef activityDef = ActivityDef.parseActivityDef("driver=diag;alias=test_dynamic_params;cycles=1000;initdelay=5000;");
new ActivityTypeLoader().load(activityDef,TestComponent.INSTANCE);
Activity simpleActivity = new SimpleActivity(TestComponent.INSTANCE,activityDef);