mirror of
https://github.com/nosqlbench/nosqlbench.git
synced 2024-12-24 08:00:00 -06:00
Notify user when using error=count vs. counter.
This commit is contained in:
parent
b1d5411afd
commit
9bc3a2fd14
@ -72,8 +72,8 @@ This is the error handler stack:
|
||||
these histos is how long the operation was pending before the related
|
||||
error occurred.
|
||||
- **count** - keep a count in metrics for the exception, under the name
|
||||
errorcounts.classname, using the simple class name.
|
||||
- **counter** - same as **count**, added for compatibility with the newer
|
||||
errorcounts.classname, using the simple class name. Starting with v4.17 onward, use **counter**.
|
||||
- **counter** - same as **count**, starting with v4.17 onward, added for compatibility with the newer
|
||||
universal error handler. This one is the preferred name.
|
||||
- **ignore** - do nothing, do not even retry or count
|
||||
|
||||
|
@ -16,8 +16,12 @@
|
||||
|
||||
package io.nosqlbench.engine.api.activityapi.errorhandling.modular.handlers;
|
||||
|
||||
import io.nosqlbench.engine.api.activityapi.errorhandling.modular.ErrorDetail;
|
||||
import io.nosqlbench.engine.api.activityapi.errorhandling.modular.ErrorHandler;
|
||||
import io.nosqlbench.nb.annotations.Service;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* This is here to allow the classic name 'count' to work although the
|
||||
@ -25,4 +29,12 @@ import io.nosqlbench.nb.annotations.Service;
|
||||
*/
|
||||
@Service(value = ErrorHandler.class, selector = "count")
|
||||
public class CountErrorHandler extends CounterErrorHandler {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(CountErrorHandler.class);
|
||||
|
||||
@Override
|
||||
public ErrorDetail handleError(String name, Throwable t, long cycle, long durationInNanos, ErrorDetail detail) {
|
||||
logger.warn("Starting with v4.17 onward, use 'counter'. See cql-errors.md for usage.");
|
||||
return super.handleError(name, t, cycle, durationInNanos, detail);
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,14 @@ import com.codahale.metrics.Counter;
|
||||
import com.codahale.metrics.Histogram;
|
||||
import com.codahale.metrics.Meter;
|
||||
import com.codahale.metrics.Timer;
|
||||
import io.nosqlbench.engine.api.activityapi.errorhandling.ErrorMetrics;
|
||||
import io.nosqlbench.api.engine.activityimpl.ActivityDef;
|
||||
import io.nosqlbench.engine.api.activityapi.errorhandling.ErrorMetrics;
|
||||
import io.nosqlbench.engine.api.activityapi.errorhandling.modular.handlers.CountErrorHandler;
|
||||
import io.nosqlbench.engine.api.activityapi.errorhandling.modular.handlers.CounterErrorHandler;
|
||||
import io.nosqlbench.util.NBMock;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
@ -29,20 +35,22 @@ import java.util.List;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
public class NBErrorHandlerTest {
|
||||
class NBErrorHandlerTest {
|
||||
|
||||
private static final String ERROR_HANDLER_APPENDER_NAME = "ErrorHandler";
|
||||
private final RuntimeException runtimeException = new RuntimeException("test exception");
|
||||
|
||||
|
||||
@Test
|
||||
public void testNullConfig() {
|
||||
void testNullConfig() {
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_stop"));
|
||||
NBErrorHandler errhandler = new NBErrorHandler(() -> "stop", () -> errorMetrics);
|
||||
assertThatExceptionOfType(RuntimeException.class)
|
||||
.isThrownBy(() -> errhandler.handleError(runtimeException, 1, 2));
|
||||
.isThrownBy(() -> errhandler.handleError(runtimeException, 1, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleWithRetry() {
|
||||
void testMultipleWithRetry() {
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_wr"));
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "warn,retry", () -> errorMetrics);
|
||||
ErrorDetail detail = eh.handleError(runtimeException, 1, 2);
|
||||
@ -50,11 +58,24 @@ public class NBErrorHandlerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistogramErrorHandler() {
|
||||
void testWarnErrorHandler() {
|
||||
Logger logger = (Logger) LogManager.getLogger("ERRORS");
|
||||
NBMock.LogAppender appender = NBMock.registerTestLogger(ERROR_HANDLER_APPENDER_NAME, logger, Level.WARN);
|
||||
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_warn"));
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "warn", () -> errorMetrics);
|
||||
ErrorDetail detail = eh.handleError(runtimeException, 1, 2);
|
||||
|
||||
assertThat(detail.isRetryable()).isFalse();
|
||||
assertThat(appender.getFirstEntry()).contains("error with cycle");
|
||||
appender.cleanup(logger);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testHistogramErrorHandler() {
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_histos"));
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "histogram", () -> {
|
||||
return errorMetrics;
|
||||
});
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "histogram", () -> errorMetrics);
|
||||
ErrorDetail detail = eh.handleError(runtimeException, 1, 2);
|
||||
assertThat(detail.isRetryable()).isFalse();
|
||||
List<Histogram> histograms = errorMetrics.getExceptionHistoMetrics().getHistograms();
|
||||
@ -62,11 +83,9 @@ public class NBErrorHandlerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimerErrorHandler() {
|
||||
void testTimerErrorHandler() {
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_timers"));
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "timer", () -> {
|
||||
return errorMetrics;
|
||||
});
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "timer", () -> errorMetrics);
|
||||
ErrorDetail detail = eh.handleError(runtimeException, 1, 2);
|
||||
assertThat(detail.isRetryable()).isFalse();
|
||||
List<Timer> histograms = errorMetrics.getExceptionTimerMetrics().getTimers();
|
||||
@ -74,23 +93,42 @@ public class NBErrorHandlerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCounterErrorHandler() {
|
||||
void testCounterErrorHandler() {
|
||||
Logger logger = (Logger) LogManager.getLogger(CounterErrorHandler.class);
|
||||
NBMock.LogAppender appender = NBMock.registerTestLogger(ERROR_HANDLER_APPENDER_NAME, logger, Level.INFO);
|
||||
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_counters"));
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "counter", () -> {
|
||||
return errorMetrics;
|
||||
});
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "counter", () -> errorMetrics);
|
||||
ErrorDetail detail = eh.handleError(runtimeException, 1, 2);
|
||||
assertThat(detail.isRetryable()).isFalse();
|
||||
List<Counter> histograms = errorMetrics.getExceptionCountMetrics().getCounters();
|
||||
assertThat(histograms).hasSize(1);
|
||||
|
||||
assertThat(appender.getFirstEntry()).isNull();
|
||||
appender.cleanup(logger);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeterErrorHandler() {
|
||||
void testCountErrorHandler() {
|
||||
Logger logger = (Logger) LogManager.getLogger(CountErrorHandler.class);
|
||||
NBMock.LogAppender appender = NBMock.registerTestLogger(ERROR_HANDLER_APPENDER_NAME, logger, Level.WARN);
|
||||
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_count"));
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "count", () -> errorMetrics);
|
||||
ErrorDetail detail = eh.handleError(runtimeException, 1, 2);
|
||||
assertThat(detail.isRetryable()).isFalse();
|
||||
List<Counter> histograms = errorMetrics.getExceptionCountMetrics().getCounters();
|
||||
assertThat(histograms).hasSize(1);
|
||||
|
||||
assertThat(appender.getFirstEntry()).contains("Starting with v4.17 onward, use 'counter'");
|
||||
appender.cleanup(logger);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testMeterErrorHandler() {
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_meters"));
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "meter", () -> {
|
||||
return errorMetrics;
|
||||
});
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "meter", () -> errorMetrics);
|
||||
ErrorDetail detail = eh.handleError(runtimeException, 1, 2);
|
||||
assertThat(detail.isRetryable()).isFalse();
|
||||
List<Meter> histograms = errorMetrics.getExceptionMeterMetrics().getMeters();
|
||||
@ -98,13 +136,29 @@ public class NBErrorHandlerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCodeShorthand() {
|
||||
void testCodeShorthand() {
|
||||
ErrorMetrics errorMetrics = new ErrorMetrics(ActivityDef.parseActivityDef("alias=testalias_meters"));
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "handler=code code=42", () -> {
|
||||
return errorMetrics;
|
||||
});
|
||||
NBErrorHandler eh = new NBErrorHandler(() -> "handler=code code=42", () -> errorMetrics);
|
||||
ErrorDetail detail = eh.handleError(runtimeException, 1, 2);
|
||||
assertThat(detail.isRetryable()).isFalse();
|
||||
assertThat(detail.resultCode).isEqualTo(42);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testErrorLogAppender() {
|
||||
|
||||
Logger logger = (Logger) LogManager.getLogger(ErrorHandler.class);
|
||||
NBMock.LogAppender appender = NBMock.registerTestLogger(ERROR_HANDLER_APPENDER_NAME, logger, Level.DEBUG);
|
||||
|
||||
logger.debug("NBErrorHandler is cool.");
|
||||
logger.debug("I second that.");
|
||||
|
||||
List<String> entries = appender.getEntries();
|
||||
assertThat(entries).hasSize(2);
|
||||
assertThat(appender.getFirstEntry()).isEqualTo("NBErrorHandler is cool.");
|
||||
assertThat(entries.get(1)).isEqualTo("I second that.");
|
||||
appender.cleanup(logger);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
75
engine-api/src/test/java/io/nosqlbench/util/NBMock.java
Normal file
75
engine-api/src/test/java/io/nosqlbench/util/NBMock.java
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.util;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.apache.logging.log4j.core.Logger;
|
||||
import org.apache.logging.log4j.core.appender.AbstractAppender;
|
||||
import org.apache.logging.log4j.core.config.Property;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used as collection of test mocks.
|
||||
*/
|
||||
public class NBMock {
|
||||
|
||||
// Registration of test logger provided with appender added for test inspection of logging.
|
||||
public static LogAppender registerTestLogger(String appenderName, Logger logger, Level level) {
|
||||
LogAppender mockedAppender = new NBMock.LogAppender(appenderName);
|
||||
mockedAppender.start();
|
||||
logger.addAppender(mockedAppender);
|
||||
logger.setLevel(level);
|
||||
return (LogAppender) logger.getAppenders().get(appenderName);
|
||||
}
|
||||
|
||||
// Appender implementation associated to a specific logger; used to obtain log specific entries in tests.
|
||||
public static class LogAppender extends AbstractAppender {
|
||||
private final List<String> entries = new ArrayList<>(1);
|
||||
|
||||
public LogAppender(String name) {
|
||||
super(name, null, null, false, new Property[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append(LogEvent event) {
|
||||
entries.add(event.getMessage().getFormattedMessage());
|
||||
}
|
||||
|
||||
public String getFirstEntry() {
|
||||
if (entries.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return entries.get(0);
|
||||
}
|
||||
|
||||
public List<String> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
public void cleanup(Logger logger) {
|
||||
this.stop();
|
||||
entries.clear();
|
||||
|
||||
if (logger != null) {
|
||||
logger.removeAppender(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -80,7 +80,7 @@ handler list which has the default wildcard error matcher.
|
||||
A handler definition is thus comprised of the error matching patterns and
|
||||
the error handling verbs which should be applied when an error matches the
|
||||
patterns. If the error matching patterns are not provided, then the
|
||||
default wildcard pattern and delimtiter `.*:`is automatically prepended.
|
||||
default wildcard pattern and delimiter `.*:`is automatically prepended.
|
||||
|
||||
### Error Pattern Formats
|
||||
|
||||
@ -98,15 +98,15 @@ commas. Alternately, handler verbs may be blocks of JSON or other standard
|
||||
NoSQLBench encoding formats, as long as they are protected by quotes:
|
||||
|
||||
# basic verb -only form
|
||||
count,warn
|
||||
counter,warn
|
||||
|
||||
# using JSON
|
||||
"{\"handler\"=\"count\"},{\"handler\"=\"warn\"}"
|
||||
"{\"handler\"=\"counter\"},{\"handler\"=\"warn\"}"
|
||||
|
||||
# using simplified params form
|
||||
"handler=count,handler=warn,handler=code code=42"
|
||||
"handler=counter,handler=warn,handler=code code=42"
|
||||
|
||||
This shows that handler verbs are really just short-hand for more
|
||||
This shows that handler verbs are really just shorthand for more
|
||||
canonical object definitions which have their own properties. The handler
|
||||
property is the one that select which handler implementation to use. Each
|
||||
handler implementation may have its own options. Those will be documented
|
||||
|
Loading…
Reference in New Issue
Block a user