mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2025-02-25 18:55:28 -06:00
Add NBAdvisor Framework (#2070)
* Add NBAdvisor Framework * Revert "Add NBAdvisor Framework" This reverts commitf2f448ffc3
. * Reapply "Add NBAdvisor Framework" This reverts commit8048402b88
. * 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:
parent
041dafa5c6
commit
7a9b2237de
@ -20,6 +20,7 @@ import com.amazonaws.util.StringInputStream;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.nosqlbench.nb.api.nbio.Content;
|
||||
import io.nosqlbench.nb.api.nbio.NBIO;
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorException;
|
||||
import io.nosqlbench.nb.api.errors.BasicError;
|
||||
import io.nosqlbench.adapters.api.activityconfig.rawyaml.RawOpsDocList;
|
||||
import io.nosqlbench.adapters.api.activityconfig.rawyaml.RawOpsLoader;
|
||||
@ -129,10 +130,10 @@ public class OpsLoader {
|
||||
System.err.println(stderrOutput);
|
||||
if (resultStatus==0 && stderrOutput.isEmpty()) {
|
||||
logger.info("no errors detected during jsonnet evaluation.");
|
||||
System.exit(0);
|
||||
throw new NBAdvisorException("dryrun=jsonnet: No errors detected.", 0);
|
||||
} else {
|
||||
logger.error("ERRORS detected during jsonnet evaluation:\n" + stderrOutput);
|
||||
System.exit(2);
|
||||
throw new NBAdvisorException("dryrun=jsonnet: Errors detected.", 2);
|
||||
}
|
||||
}
|
||||
if (!stderrOutput.isEmpty()) {
|
||||
|
@ -182,6 +182,7 @@ public abstract class BaseDriverAdapter<RESULT
|
||||
.add(Param.defaultTo("dryrun", "none").setRegex("(op|jsonnet|emit|none)"))
|
||||
.add(Param.optional("maxtries", Integer.class))
|
||||
.asReadOnly();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -162,7 +162,6 @@
|
||||
<version>3.46.0.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -0,0 +1,48 @@
|
||||
package io.nosqlbench.nb.api.advisor;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
import io.nosqlbench.nb.api.components.core.NBComponent;
|
||||
|
||||
public abstract class BaseAdvisorBuilder<ELEMENT, T, SelfT extends BaseAdvisorBuilder<ELEMENT, T, SelfT>>
|
||||
extends NBAdvisorPointOrBuilder<ELEMENT> {
|
||||
|
||||
protected NBComponent component;
|
||||
protected String name;
|
||||
protected String description;
|
||||
|
||||
protected abstract SelfT self();
|
||||
|
||||
public SelfT component(NBComponent component) {
|
||||
this.component = component;
|
||||
return self();
|
||||
}
|
||||
|
||||
public SelfT name(String name) {
|
||||
this.name = name;
|
||||
return self();
|
||||
}
|
||||
|
||||
public SelfT desc(String description) {
|
||||
this.description = description;
|
||||
return self();
|
||||
}
|
||||
|
||||
public abstract <PTYPE> NBAdvisorPoint<PTYPE> build();
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package io.nosqlbench.nb.api.advisor;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
public class NBAdvisorBuilder<PTYPE>
|
||||
extends BaseAdvisorBuilder<PTYPE, NBAdvisorPoint<PTYPE>, NBAdvisorBuilder<PTYPE>> {
|
||||
|
||||
@Override
|
||||
protected NBAdvisorBuilder<PTYPE> self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBAdvisorPoint<PTYPE> build() {
|
||||
return (NBAdvisorPoint<PTYPE>) new NBAdvisorPoint<PTYPE>(name, description == null ? name : description);
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package io.nosqlbench.nb.api.advisor;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
import io.nosqlbench.nb.api.components.core.NBNamedElement;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
public interface NBAdvisorCondition<T> extends Function<T, NBAdvisorPoint.Result<T>>, Predicate<T> {
|
||||
|
||||
Function<T, String> okMsg();
|
||||
|
||||
Function<T, String> errMsg();
|
||||
|
||||
Level level();
|
||||
|
||||
@Override
|
||||
default NBAdvisorPoint.Result<T> apply(T element) {
|
||||
boolean hasError = test(element);
|
||||
return new NBAdvisorPoint.Result<>(
|
||||
this,
|
||||
element,
|
||||
hasError ? NBAdvisorPoint.Status.ERROR : NBAdvisorPoint.Status.OK
|
||||
);
|
||||
}
|
||||
|
||||
String getName();
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 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.nb.api.advisor;
|
||||
|
||||
public class NBAdvisorException extends RuntimeException {
|
||||
private final String message;
|
||||
private final int exitCode;
|
||||
|
||||
public NBAdvisorException(String message, int exitCode) {
|
||||
this.message = message;
|
||||
this.exitCode = exitCode;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public int getExitCode() {
|
||||
return this.exitCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 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.nb.api.advisor;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* This is related to {@link io.nosqlbench.nb.api.advisor.conditions.Conditions}, and the terms
|
||||
* should be aligned. When possible, the the Conditions class should be used to capture
|
||||
* re-usable conditions, so that there is only one instance of each distinct type in the runtime,
|
||||
* regardless of how many components use it in their advisor points.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public enum NBAdvisorLevel {
|
||||
/**
|
||||
* Do not analyze arguments, scenarios, activities, and workloads
|
||||
*/
|
||||
none,
|
||||
/**
|
||||
* Provide advice about invalid, incorrect, and unused ops
|
||||
*/
|
||||
validate,
|
||||
/**
|
||||
* Only allow correct operations
|
||||
*/
|
||||
enforce;
|
||||
|
||||
// Static field to store the last used setting
|
||||
private static NBAdvisorLevel level = none;
|
||||
|
||||
public static NBAdvisorLevel fromString(String advisorStr) {
|
||||
try {
|
||||
level = NBAdvisorLevel.valueOf(advisorStr.toLowerCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("--advisor=" + advisorStr + " is invalid. Using 'none'");
|
||||
level = NBAdvisorLevel.none;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
public static NBAdvisorLevel get() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public static boolean isAdvisorActive() {
|
||||
return level != NBAdvisorLevel.none;
|
||||
}
|
||||
|
||||
public static boolean isEnforcerActive() {
|
||||
return level == NBAdvisorLevel.enforce;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package io.nosqlbench.nb.api.advisor;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class NBAdvisorPoint<T> extends NBAdvisorPointOrBuilder<T> {
|
||||
|
||||
private final static Logger logger = LogManager.getLogger("ADVISOR");
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private NBAdvisorLevel advisorLevel = NBAdvisorLevel.none;
|
||||
private NBAdvisorCondition<T>[] conditions = new NBAdvisorCondition[0];
|
||||
private List<Result<?>> resultLog = new ArrayList<Result<?>>();
|
||||
|
||||
public NBAdvisorPoint(String name) {
|
||||
this(name, null);
|
||||
}
|
||||
|
||||
public NBAdvisorPoint(String name, String description) {
|
||||
this.name = name;
|
||||
this.description = description == null ? name : description;
|
||||
this.advisorLevel = NBAdvisorLevel.get();
|
||||
}
|
||||
|
||||
public Result<T>[] validateAll(Collection<T> elements) {
|
||||
List<Result<T>> buffer = new ArrayList<>();
|
||||
for (T element : elements) {
|
||||
Result<T>[] oneElementValidation = validate(element);
|
||||
for (Result<T> r : oneElementValidation) {
|
||||
buffer.add(r);
|
||||
}
|
||||
}
|
||||
return buffer.toArray(new Result[0]);
|
||||
}
|
||||
|
||||
public synchronized Result<T>[] validate(T element) {
|
||||
Result<T>[] results = new Result[conditions.length];
|
||||
for (int i = 0; i < conditions.length; i++) {
|
||||
results[i] = conditions[i].apply(element);
|
||||
resultLog.add(results[i]);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<Result<?>> getResultLog() {
|
||||
return this.resultLog;
|
||||
}
|
||||
|
||||
public NBAdvisorPoint<T> add(NBAdvisorCondition<T> condition) {
|
||||
_addArrayCondition(condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String[] errorMessages(T element) {
|
||||
Result<T>[] results = this.validate(element);
|
||||
return Arrays.stream(results).filter(Result::isError).map(Result::rendered).toArray(String[]::new);
|
||||
}
|
||||
|
||||
|
||||
private void _addArrayCondition(NBAdvisorCondition<T> condition) {
|
||||
NBAdvisorCondition<T>[] newConditions = new NBAdvisorCondition[conditions.length + 1];
|
||||
System.arraycopy(conditions, 0, newConditions, 0, conditions.length);
|
||||
newConditions[newConditions.length - 1] = condition;
|
||||
conditions = newConditions;
|
||||
}
|
||||
|
||||
public static enum Status {
|
||||
OK,
|
||||
ERROR
|
||||
}
|
||||
|
||||
public static record Result<T>(
|
||||
NBAdvisorCondition<T> condition,
|
||||
T element,
|
||||
Status status
|
||||
) {
|
||||
public boolean isError() {
|
||||
return status == Status.ERROR;
|
||||
}
|
||||
|
||||
public Level conditionLevel() {
|
||||
return condition.level();
|
||||
}
|
||||
|
||||
public String rendered() {
|
||||
return switch (status) {
|
||||
case OK -> "OK: " + condition.okMsg().apply(element);
|
||||
case ERROR -> conditionLevel() + ": " + condition.errMsg().apply(element);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package io.nosqlbench.nb.api.advisor;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
public class NBAdvisorPointOrBuilder<T> {
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package io.nosqlbench.nb.api.advisor;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class NBAdvisorResults {
|
||||
private final static Logger logger = LogManager.getLogger("ADVISOR");
|
||||
private final List<NBAdvisorPoint<?>> points = new ArrayList<>();
|
||||
|
||||
public NBAdvisorResults(List<NBAdvisorPoint<?>> points) {
|
||||
this.points.addAll(points);
|
||||
}
|
||||
|
||||
public List<NBAdvisorPoint.Result<?>> getAdvisorResults() {
|
||||
return points.stream().flatMap(a -> a.getResultLog().stream()).toList();
|
||||
}
|
||||
|
||||
public void render(Level level,String message) {
|
||||
if (level == Level.INFO) {
|
||||
logger.info(message);
|
||||
} else if (level == Level.WARN) {
|
||||
logger.warn(message);
|
||||
} else if (level == Level.ERROR) {
|
||||
logger.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
public int evaluate() {
|
||||
List<NBAdvisorPoint.Result<?>> results = getAdvisorResults();
|
||||
Iterator<NBAdvisorPoint.Result<?>> iterator = results.iterator();
|
||||
int count = 0;
|
||||
boolean terminate = false;
|
||||
Level level = Level.INFO;
|
||||
while (iterator.hasNext()) {
|
||||
NBAdvisorPoint.Result<?> result = iterator.next();
|
||||
level = result.isError() ? result.conditionLevel() : level.INFO;
|
||||
switch (NBAdvisorLevel.get()) {
|
||||
case NBAdvisorLevel.none:
|
||||
if ( level == Level.ERROR ) {
|
||||
render(level, result.rendered());
|
||||
count++;
|
||||
terminate = true;
|
||||
}
|
||||
break;
|
||||
case NBAdvisorLevel.validate:
|
||||
if ( level == Level.ERROR ) {
|
||||
render(level, result.rendered());
|
||||
count++;
|
||||
terminate = true;
|
||||
} else {
|
||||
render(Level.INFO, result.rendered());
|
||||
}
|
||||
break;
|
||||
case NBAdvisorLevel.enforce:
|
||||
if ( level == Level.ERROR || level == Level.WARN ) {
|
||||
render(level, result.rendered());
|
||||
count++;
|
||||
terminate = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( terminate ) {
|
||||
String message = String.format("Advisor found %d actionable %s.",
|
||||
count,
|
||||
(count < 2 ? "error" : "errors"));
|
||||
render(Level.ERROR, message);
|
||||
throw new NBAdvisorException(message, 2);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package io.nosqlbench.nb.api.advisor.conditions;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorCondition;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
/**
|
||||
* <P>The mappings between logging levels for conditions and the advisory
|
||||
* levels should be consistent, so they will be described here to start.</P>
|
||||
*
|
||||
* <P>These are the levels which conditions should use:</P>
|
||||
* <OL>
|
||||
* <LI>Level.ERROR (internal to conditions, cause immediate exceptions)</LI>
|
||||
* <LI>Level.WARN (conditions which should inform the user about a likely issue)</LI>
|
||||
* <LI>Level.INFO (conditions which may inform the user about a possible issue)</LI>
|
||||
* </OL>
|
||||
*
|
||||
* <P>This means that the following three behaviors are possible:
|
||||
* <OL>
|
||||
* <LI>{@link io.nosqlbench.nb.api.advisor.NBAdvisorLevel#none} - Only ERROR level results throw exceptions, no
|
||||
* results are presented.</LI>
|
||||
* <LI>{@link io.nosqlbench.nb.api.advisor.NBAdvisorLevel#validate} - Only ERROR level results throw exceptions,
|
||||
* all results are presented. </LI>
|
||||
* <LI>{@link io.nosqlbench.nb.api.advisor.NBAdvisorLevel#enforce} - ERROR and WARN levels throw exceptions.</LI>
|
||||
* </P>
|
||||
*
|
||||
*/
|
||||
public class Conditions {
|
||||
|
||||
public static NoHyphens NoHyphensError = new NoHyphens(Level.ERROR);
|
||||
public static NoHyphens NoHyphensWarning = new NoHyphens(Level.WARN);
|
||||
public static NoSpaces NoSpacesError = new NoSpaces(Level.ERROR);
|
||||
public static NoSpaces NoSpacesWarning = new NoSpaces(Level.WARN);
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package io.nosqlbench.nb.api.advisor.conditions;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorCondition;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NoHyphens implements NBAdvisorCondition<String> {
|
||||
|
||||
private final Level level;
|
||||
|
||||
public NoHyphens(Level level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(String string) {
|
||||
return string.contains("-");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, String> okMsg() {
|
||||
return s -> "String '" + s + "' does not contain hyphens";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, String> errMsg() {
|
||||
return s -> "String '" + s + "' should not contain hyphens";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Level level() {
|
||||
return this.level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "no-hyphens";
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package io.nosqlbench.nb.api.advisor.conditions;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorCondition;
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NoSpaces implements NBAdvisorCondition<String> {
|
||||
|
||||
private final Level level;
|
||||
|
||||
public NoSpaces(Level level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, String> okMsg() {
|
||||
return string -> "String '" + string + "' does not contain spaces";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, String> errMsg() {
|
||||
return string -> "String '" +string + "' should not contain spaces";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Level level() {
|
||||
return level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "no spaces";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(String s) {
|
||||
return s.contains(" ");
|
||||
}
|
||||
}
|
@ -16,6 +16,8 @@
|
||||
|
||||
package io.nosqlbench.nb.api.components.core;
|
||||
|
||||
import io.nosqlbench.nb.api.advisor.*;
|
||||
import io.nosqlbench.nb.api.advisor.conditions.Conditions;
|
||||
import io.nosqlbench.nb.api.components.decorators.NBTokenWords;
|
||||
import io.nosqlbench.nb.api.components.events.ComponentOutOfScope;
|
||||
import io.nosqlbench.nb.api.components.events.DownEvent;
|
||||
@ -24,6 +26,7 @@ import io.nosqlbench.nb.api.components.events.UpEvent;
|
||||
import io.nosqlbench.nb.api.engine.metrics.MetricsCloseable;
|
||||
import io.nosqlbench.nb.api.engine.metrics.instruments.NBMetric;
|
||||
import io.nosqlbench.nb.api.labels.NBLabels;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
@ -32,15 +35,17 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class NBBaseComponent extends NBBaseComponentMetrics implements NBComponent, NBTokenWords, NBComponentTimeline {
|
||||
private final static Logger logger = LogManager.getLogger("RUNTIME");
|
||||
protected final NBComponent parent;
|
||||
protected final NBLabels labels;
|
||||
private final List<NBComponent> children = new ArrayList<>();
|
||||
private final List<NBAdvisorPoint<?>> advisors = new ArrayList<>();
|
||||
protected NBMetricsBuffer metricsBuffer = new NBMetricsBuffer();
|
||||
protected boolean bufferOrphanedMetrics = false;
|
||||
private ConcurrentHashMap<String,String> props = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, String> props = new ConcurrentHashMap<>();
|
||||
protected Exception error;
|
||||
protected long started_ns, teardown_ns, closed_ns, errored_ns, started_epoch_ms;
|
||||
protected NBInvokableState state = NBInvokableState.STARTING;
|
||||
@ -51,6 +56,19 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
}
|
||||
|
||||
public NBBaseComponent(NBComponent parentComponent, NBLabels componentSpecificLabelsOnly) {
|
||||
NBAdvisorPoint<String> labelsAdvisor = create().advisor(b -> b.name("Check labels"));
|
||||
// ^ Explicitly name the generic type here
|
||||
// ^ retain the advisor instance for customization, even though it is already attached to
|
||||
// the current component
|
||||
labelsAdvisor.add(Conditions.NoHyphensError);
|
||||
labelsAdvisor.add(Conditions.NoSpacesWarning);
|
||||
|
||||
labelsAdvisor.validateAll(componentSpecificLabelsOnly.asMap().keySet());
|
||||
labelsAdvisor.validateAll(componentSpecificLabelsOnly.asMap().values());
|
||||
|
||||
NBAdvisorResults advisorResults = getAdvisorResults();
|
||||
advisorResults.evaluate();
|
||||
|
||||
this.started_ns = System.nanoTime();
|
||||
this.started_epoch_ms = System.currentTimeMillis();
|
||||
this.labels = componentSpecificLabelsOnly;
|
||||
@ -60,11 +78,11 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
} else {
|
||||
parent = null;
|
||||
}
|
||||
state = (state==NBInvokableState.ERRORED) ? state : NBInvokableState.RUNNING;
|
||||
state = (state == NBInvokableState.ERRORED) ? state : NBInvokableState.RUNNING;
|
||||
}
|
||||
|
||||
public NBBaseComponent(NBComponent parentComponent, NBLabels componentSpecificLabelsOnly, Map<String, String> props) {
|
||||
this(parentComponent,componentSpecificLabelsOnly);
|
||||
this(parentComponent, componentSpecificLabelsOnly);
|
||||
props.forEach(this::setComponentProp);
|
||||
}
|
||||
|
||||
@ -82,10 +100,8 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
NBLabels eachLabels = extant.getComponentOnlyLabels();
|
||||
NBLabels newLabels = child.getComponentOnlyLabels();
|
||||
|
||||
if (eachLabels!=null && newLabels!=null && !eachLabels.isEmpty() && !newLabels.isEmpty() && child.getComponentOnlyLabels().equals(extant.getComponentOnlyLabels())) {
|
||||
throw new RuntimeException("Adding second child under already-defined labels is not allowed:\n" +
|
||||
" extant: (" + extant.getClass().getSimpleName() + ") " + extant.description() + "\n" +
|
||||
" adding: (" + child.getClass().getSimpleName() + ") " + child.description());
|
||||
if (eachLabels != null && newLabels != null && !eachLabels.isEmpty() && !newLabels.isEmpty() && child.getComponentOnlyLabels().equals(extant.getComponentOnlyLabels())) {
|
||||
throw new RuntimeException("Adding second child under already-defined labels is not allowed:\n" + " extant: (" + extant.getClass().getSimpleName() + ") " + extant.description() + "\n" + " adding: (" + child.getClass().getSimpleName() + ") " + child.description());
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +145,7 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
|
||||
@Override
|
||||
public final void close() throws RuntimeException {
|
||||
state = (state==NBInvokableState.ERRORED) ? state : NBInvokableState.CLOSING;
|
||||
state = (state == NBInvokableState.ERRORED) ? state : NBInvokableState.CLOSING;
|
||||
closed_ns = System.nanoTime();
|
||||
|
||||
try {
|
||||
@ -156,8 +172,9 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
RuntimeException wrapped = new RuntimeException("While in state " + this.state + ", an error occured: " + e, e);
|
||||
logger.error(wrapped);
|
||||
this.error = wrapped;
|
||||
state=NBInvokableState.ERRORED;
|
||||
state = NBInvokableState.ERRORED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method in your component implementations when you need to do something
|
||||
* to close out your component.
|
||||
@ -165,7 +182,7 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
protected void teardown() {
|
||||
logger.debug("tearing down " + description());
|
||||
this.teardown_ns = System.nanoTime();
|
||||
this.state=(state==NBInvokableState.ERRORED) ? state : NBInvokableState.STOPPED;
|
||||
this.state = (state == NBInvokableState.ERRORED) ? state : NBInvokableState.STOPPED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -240,7 +257,8 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
* This method is called by the engine to report a component going out of scope. The metrics for that component
|
||||
* will bubble up through the component layers and can be buffered for reporting at multiple levels.
|
||||
*
|
||||
* @param m The metric to report
|
||||
* @param m
|
||||
* The metric to report
|
||||
*/
|
||||
@Override
|
||||
public void reportExecutionMetric(NBMetric m) {
|
||||
@ -254,8 +272,8 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
|
||||
@Override
|
||||
public long getNanosSinceStart() {
|
||||
if (teardown_ns ==0) {
|
||||
return System.nanoTime()- started_ns;
|
||||
if (teardown_ns == 0) {
|
||||
return System.nanoTime() - started_ns;
|
||||
} else {
|
||||
return teardown_ns - started_ns;
|
||||
}
|
||||
@ -263,10 +281,10 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
|
||||
@Override
|
||||
public Optional<String> getComponentProp(String name) {
|
||||
if (this.props!=null && this.props.containsKey(name)) {
|
||||
if (this.props != null && this.props.containsKey(name)) {
|
||||
return Optional.ofNullable(this.props.get(name));
|
||||
} else if (this.getParent()!=null) {
|
||||
return this.getParent().getComponentProp(name);
|
||||
} else if (this.getParent() != null) {
|
||||
return this.getParent().getComponentProp(name);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
@ -274,7 +292,7 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
|
||||
@Override
|
||||
public NBComponentProps setComponentProp(String name, String value) {
|
||||
if (this.props==null) {
|
||||
if (this.props == null) {
|
||||
this.props = new ConcurrentHashMap<>();
|
||||
}
|
||||
props.put(name, value);
|
||||
@ -315,4 +333,13 @@ public class NBBaseComponent extends NBBaseComponentMetrics implements NBCompone
|
||||
metricsCloseables.add(metric);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdvisor(NBAdvisorPoint advisor) {
|
||||
this.advisors.add(advisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NBAdvisorPoint<?>> getAdvisors() {
|
||||
return advisors;
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,8 @@ public interface NBComponent extends
|
||||
NBComponentServices,
|
||||
NBComponentEvents,
|
||||
NBProviderSearch,
|
||||
NBComponentProps {
|
||||
NBComponentProps,
|
||||
NBComponentAdvisors {
|
||||
|
||||
NBComponent EMPTY_COMPONENT = new NBBaseComponent(null);
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
package io.nosqlbench.nb.api.components.core;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorPoint;
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorResults;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public interface NBComponentAdvisors {
|
||||
|
||||
void addAdvisor(NBAdvisorPoint<?> advisor);
|
||||
|
||||
List<NBAdvisorPoint<?>> getAdvisors();
|
||||
|
||||
default NBAdvisorResults getAdvisorResults() {
|
||||
return new NBAdvisorResults(getAdvisors());
|
||||
}
|
||||
}
|
@ -16,6 +16,9 @@
|
||||
|
||||
package io.nosqlbench.nb.api.components.core;
|
||||
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorBuilder;
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorPoint;
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorPointOrBuilder;
|
||||
import io.nosqlbench.nb.api.csvoutput.CsvOutputPluginWriter;
|
||||
import com.codahale.metrics.Meter;
|
||||
import io.nosqlbench.nb.api.engine.metrics.*;
|
||||
@ -42,6 +45,7 @@ import java.util.*;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -56,7 +60,7 @@ public class NBCreators {
|
||||
}
|
||||
|
||||
public NBMetricTimer timer(String metricFamilyName, MetricCategory category, String description) {
|
||||
return timer(metricFamilyName,3, category,description);
|
||||
return timer(metricFamilyName, 3, category, description);
|
||||
}
|
||||
|
||||
public NBMetricTimer timer(String metricFamilyName, int hdrdigits, MetricCategory category, String description) {
|
||||
@ -72,7 +76,7 @@ public class NBCreators {
|
||||
|
||||
public Meter meter(String metricFamilyName, MetricCategory category, String description) {
|
||||
NBLabels labels = base.getLabels().and("name", metricFamilyName);
|
||||
NBMetricMeter meter = new NBMetricMeter(labels,description, category);
|
||||
NBMetricMeter meter = new NBMetricMeter(labels, description, category);
|
||||
base.addComponentMetric(meter, category, description);
|
||||
return meter;
|
||||
}
|
||||
@ -113,7 +117,7 @@ public class NBCreators {
|
||||
for (WindowSummaryGauge.Stat stat : stats) {
|
||||
anyGauge = new WindowSummaryGauge(
|
||||
window,
|
||||
base.getLabels().and(NBLabels.forKV("name", name+"_w"+window, "stat", stat)),
|
||||
base.getLabels().and(NBLabels.forKV("name", name + "_w" + window, "stat", stat)),
|
||||
stat,
|
||||
description,
|
||||
category
|
||||
@ -136,7 +140,7 @@ public class NBCreators {
|
||||
}
|
||||
|
||||
public NBMetricHistogram histogram(String metricFamilyName, MetricCategory category, String description) {
|
||||
return histogram(metricFamilyName,4, category, description);
|
||||
return histogram(metricFamilyName, 4, category, description);
|
||||
}
|
||||
|
||||
public NBMetricHistogram histogram(String metricFamilyName, int hdrdigits, MetricCategory category, String description) {
|
||||
@ -486,4 +490,18 @@ public class NBCreators {
|
||||
() -> new RuntimeException("unable to load extension with name '" + name + "' and type '" + type.getSimpleName() + "'")
|
||||
);
|
||||
}
|
||||
|
||||
public <PTYPE> NBAdvisorPoint<PTYPE> advisor(Function<NBAdvisorBuilder<PTYPE>, NBAdvisorPointOrBuilder<PTYPE>> builderOrPointF) {
|
||||
NBAdvisorBuilder<PTYPE> newBuilder = new NBAdvisorBuilder<PTYPE>();
|
||||
NBAdvisorPointOrBuilder<PTYPE> builderOrPoint = builderOrPointF.apply(newBuilder);
|
||||
NBAdvisorPoint<PTYPE> point = switch (builderOrPoint) {
|
||||
case NBAdvisorPoint p -> p;
|
||||
case NBAdvisorBuilder builder -> builder.build();
|
||||
default -> throw new RuntimeException(
|
||||
"unknown type for mapping builder: " + builderOrPoint.getClass().getCanonicalName()
|
||||
);
|
||||
};
|
||||
base.addAdvisor(point);
|
||||
return point;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,13 @@ package io.nosqlbench.nb.api.components.decorators;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <P>This is a canonical way to get the words which are acceptable and valid
|
||||
* for token transformations in strings, particularly in identifiers for
|
||||
* external reporting or logging. No other methods should be used to determine
|
||||
* which tokens are valid across NB components. All tokens which are deemed
|
||||
* useful or necessary should be included here. (This derives from built-in labels)</P>
|
||||
*/
|
||||
public interface NBTokenWords {
|
||||
Map<String,String> getTokens();
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class PromPushReporterComponent extends PeriodicTaskComponent {
|
||||
private String bearerToken;
|
||||
|
||||
public PromPushReporterComponent(NBComponent parent, String endpoint,long intervalMs, NBLabels nbLabels, String prompushApikeyfile) {
|
||||
super(parent, nbLabels.and("_type", "prom-push"), intervalMs, "REPORT-PROMPUSH",FirstReport.OnInterval, LastReport.OnInterrupt);
|
||||
super(parent, nbLabels.and("_type", "prom_push"), intervalMs, "REPORT-PROMPUSH",FirstReport.OnInterval, LastReport.OnInterrupt);
|
||||
String jobname = getLabels().valueOfOptional("jobname").orElse("default");
|
||||
String instance = getLabels().valueOfOptional("instance").orElse("default");
|
||||
if (jobname.equals("default") || instance.equals("default")) {
|
||||
|
@ -0,0 +1,54 @@
|
||||
package io.nosqlbench.nb.api.components.core;
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
|
||||
import io.nosqlbench.nb.api.advisor.NBAdvisorPoint;
|
||||
import io.nosqlbench.nb.api.advisor.conditions.Conditions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class NBAdvisorPointTest {
|
||||
|
||||
@Test
|
||||
public void testAdvisorPointBasics() {
|
||||
NBAdvisorPoint<String> nap = new NBAdvisorPoint<>("labels should have no hyphens");
|
||||
nap.add(Conditions.NoHyphensError);
|
||||
nap.add(Conditions.NoSpacesWarning);
|
||||
|
||||
String[] spaceErrors = nap.errorMessages("one two three");
|
||||
assertThat(spaceErrors)
|
||||
.containsExactly(new String[]{"WARN: String 'one two three' should not contain spaces"});
|
||||
|
||||
String[] hyphenErrors = nap.errorMessages("one-two");
|
||||
assertThat(hyphenErrors)
|
||||
.containsExactly(new String[]{"ERROR: String 'one-two' should not contain hyphens"});
|
||||
|
||||
String[] bothErrors = nap.errorMessages("one-two three");
|
||||
assertThat(bothErrors)
|
||||
.containsExactly(new String[]{
|
||||
"ERROR: String 'one-two three' should not contain hyphens",
|
||||
"WARN: String 'one-two three' should not contain spaces"
|
||||
});
|
||||
|
||||
//int count = nap.evaluate();
|
||||
//assertThat(count).isEqualTo(4);
|
||||
}
|
||||
|
||||
}
|
@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ -64,7 +65,6 @@ class NBComponentServicesTest {
|
||||
metricsInTree.forEach(m -> {
|
||||
System.out.println("metric: " + m.toString());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import java.util.Iterator;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class NBComponentTraversalTest {
|
||||
public class NBComponentTraversalTest {
|
||||
|
||||
/**
|
||||
* <pre>{@code
|
||||
|
@ -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 (
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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<>();
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user