Added @TestLogging annotation to set a specific level per test method
It supports multiple logger:level comma separated key value pairs Use the _root keyword to set the root logger level e.g. @Logging("_root:DEBUG,org.elasticsearch.cluster.metadata:TRACE") or just @TestLogging("_root:DEBUG,cluster.metadata:TRACE") since we start the test with -Des.logger.prefix=
This commit is contained in:
parent
453e7c1510
commit
9e72683ba4
|
@ -28,8 +28,22 @@ public interface ESLogger {
|
||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to set the logger level
|
||||||
|
* If the new level is null, the logger will inherit its level
|
||||||
|
* from its nearest ancestor with a specific (non-null) level value.
|
||||||
|
* @param level the new level
|
||||||
|
*/
|
||||||
void setLevel(String level);
|
void setLevel(String level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current logger level
|
||||||
|
* If the level is null, it means that the logger inherits its level
|
||||||
|
* from its nearest ancestor with a specific (non-null) level value.
|
||||||
|
* @return the logger level
|
||||||
|
*/
|
||||||
|
String getLevel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if a TRACE level message is logged.
|
* Returns {@code true} if a TRACE level message is logged.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -41,7 +41,9 @@ public class JdkESLogger extends AbstractESLogger {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setLevel(String level) {
|
public void setLevel(String level) {
|
||||||
if ("error".equalsIgnoreCase(level)) {
|
if (level == null) {
|
||||||
|
logger.setLevel(null);
|
||||||
|
} else if ("error".equalsIgnoreCase(level)) {
|
||||||
logger.setLevel(Level.SEVERE);
|
logger.setLevel(Level.SEVERE);
|
||||||
} else if ("warn".equalsIgnoreCase(level)) {
|
} else if ("warn".equalsIgnoreCase(level)) {
|
||||||
logger.setLevel(Level.WARNING);
|
logger.setLevel(Level.WARNING);
|
||||||
|
@ -54,6 +56,14 @@ public class JdkESLogger extends AbstractESLogger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLevel() {
|
||||||
|
if (logger.getLevel() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return logger.getLevel().toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return logger.getName();
|
return logger.getName();
|
||||||
|
|
|
@ -36,7 +36,9 @@ public class Log4jESLogger extends AbstractESLogger {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLevel(String level) {
|
public void setLevel(String level) {
|
||||||
if ("error".equalsIgnoreCase(level)) {
|
if (level == null) {
|
||||||
|
logger.setLevel(null);
|
||||||
|
} else if ("error".equalsIgnoreCase(level)) {
|
||||||
logger.setLevel(Level.ERROR);
|
logger.setLevel(Level.ERROR);
|
||||||
} else if ("warn".equalsIgnoreCase(level)) {
|
} else if ("warn".equalsIgnoreCase(level)) {
|
||||||
logger.setLevel(Level.WARN);
|
logger.setLevel(Level.WARN);
|
||||||
|
@ -49,6 +51,14 @@ public class Log4jESLogger extends AbstractESLogger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLevel() {
|
||||||
|
if (logger.getLevel() == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return logger.getLevel().toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return logger.getName();
|
return logger.getName();
|
||||||
|
|
|
@ -39,6 +39,12 @@ public class Slf4jESLogger extends AbstractESLogger {
|
||||||
// can't set it in slf4j...
|
// can't set it in slf4j...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLevel() {
|
||||||
|
// can't get it in slf4j...
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return logger.getName();
|
return logger.getName();
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Licensed to ElasticSearch and Shay Banon under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. ElasticSearch licenses this
|
||||||
|
* file to you 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 org.elasticsearch.junit.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation used to set a custom log level for a specific test method.
|
||||||
|
*
|
||||||
|
* It supports multiple logger:level comma separated key value pairs
|
||||||
|
* Use the _root keyword to set the root logger level
|
||||||
|
* e.g. @TestLogging("_root:DEBUG,org.elasticsearch.cluster.metadata:TRACE")
|
||||||
|
* or just @TestLogging("_root:DEBUG,cluster.metadata:TRACE") since we start the test with -Des.logger.prefix=
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface TestLogging {
|
||||||
|
String value();
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Licensed to ElasticSearch and Shay Banon under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. ElasticSearch licenses this
|
||||||
|
* file to you 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 org.elasticsearch.junit.listerners;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.logging.ESLogger;
|
||||||
|
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||||
|
import org.elasticsearch.junit.annotations.TestLogging;
|
||||||
|
import org.junit.runner.Description;
|
||||||
|
import org.junit.runner.notification.RunListener;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link RunListener} that allows to change the log level for a specific test method.
|
||||||
|
* When a test method is annotated with the {@link org.elasticsearch.junit.annotations.TestLogging} annotation, the level for the specified loggers
|
||||||
|
* will be internally saved before the test method execution and overridden with the specified ones.
|
||||||
|
* At the end of the test method execution the original loggers levels will be restored.
|
||||||
|
*
|
||||||
|
* Note: This class is not thread-safe. Given the static nature of the logging api, it assumes that tests
|
||||||
|
* are never run concurrently in the same jvm. For the very same reason no synchronization has been implemented
|
||||||
|
* regarding the save/restore process of the original loggers levels.
|
||||||
|
*/
|
||||||
|
public class LoggingListener extends RunListener {
|
||||||
|
|
||||||
|
private Map<String, String> previousLoggingMap;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testStarted(Description description) throws Exception {
|
||||||
|
TestLogging testLogging = description.getAnnotation(TestLogging.class);
|
||||||
|
if (testLogging != null) {
|
||||||
|
this.previousLoggingMap = new HashMap<String, String>();
|
||||||
|
String[] loggersAndLevels = testLogging.value().split(",");
|
||||||
|
for (String loggerAndLevel : loggersAndLevels) {
|
||||||
|
String[] loggerAndLevelArray = loggerAndLevel.split(":");
|
||||||
|
if (loggerAndLevelArray.length >=2) {
|
||||||
|
String loggerName = loggerAndLevelArray[0];
|
||||||
|
String level = loggerAndLevelArray[1];
|
||||||
|
ESLogger esLogger = resolveLogger(loggerName);
|
||||||
|
this.previousLoggingMap.put(loggerName, esLogger.getLevel());
|
||||||
|
esLogger.setLevel(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testFinished(Description description) throws Exception {
|
||||||
|
if (this.previousLoggingMap != null) {
|
||||||
|
for (Map.Entry<String, String> previousLogger : previousLoggingMap.entrySet()) {
|
||||||
|
ESLogger esLogger = resolveLogger(previousLogger.getKey());
|
||||||
|
esLogger.setLevel(previousLogger.getValue());
|
||||||
|
}
|
||||||
|
this.previousLoggingMap = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ESLogger resolveLogger(String loggerName) {
|
||||||
|
if (loggerName.equalsIgnoreCase("_root")) {
|
||||||
|
return ESLoggerFactory.getRootLogger();
|
||||||
|
}
|
||||||
|
return ESLoggerFactory.getLogger(loggerName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.test.integration;
|
package org.elasticsearch.test.integration;
|
||||||
|
|
||||||
|
import com.carrotsearch.randomizedtesting.annotations.Listeners;
|
||||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
|
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
|
||||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
|
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope;
|
||||||
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope;
|
import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope.Scope;
|
||||||
|
@ -27,6 +28,7 @@ import org.apache.lucene.util.AbstractRandomizedTest;
|
||||||
import org.apache.lucene.util.TimeUnits;
|
import org.apache.lucene.util.TimeUnits;
|
||||||
import org.elasticsearch.common.logging.ESLogger;
|
import org.elasticsearch.common.logging.ESLogger;
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
import org.elasticsearch.common.logging.Loggers;
|
||||||
|
import org.elasticsearch.junit.listerners.LoggingListener;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -36,6 +38,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
@ThreadLeakFilters(defaultFilters = true, filters = {ElasticSearchThreadFilter.class})
|
@ThreadLeakFilters(defaultFilters = true, filters = {ElasticSearchThreadFilter.class})
|
||||||
@ThreadLeakScope(Scope.NONE)
|
@ThreadLeakScope(Scope.NONE)
|
||||||
@TimeoutSuite(millis = TimeUnits.HOUR) // timeout the suite after 1h and fail the test.
|
@TimeoutSuite(millis = TimeUnits.HOUR) // timeout the suite after 1h and fail the test.
|
||||||
|
@Listeners(LoggingListener.class)
|
||||||
public abstract class ElasticsearchTestCase extends AbstractRandomizedTest {
|
public abstract class ElasticsearchTestCase extends AbstractRandomizedTest {
|
||||||
|
|
||||||
protected final ESLogger logger = Loggers.getLogger(getClass());
|
protected final ESLogger logger = Loggers.getLogger(getClass());
|
||||||
|
|
Loading…
Reference in New Issue