Skip to content

Commit b4306b6

Browse files
authored
Add calling class name to mock log appender (opensearch-project#12013)
Issue opensearch-project#10799 is caused by a stopped or unstarted appender still being present in the static logger state. I have not been able to find the improper usage of the log appender that would cause this error. To help debug, this commit adds the calling class name to the mock log appender. Any future occurrence should result in an error message with the class name that incorrected configured the logger. I've also added an override to the `stop()` method to force that callers use the close() method that properly cleans up the logger state as opposed to stopping the appender directly. Signed-off-by: Andrew Ross <andrross@amazon.com>
1 parent 829215c commit b4306b6

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

test/framework/src/main/java/org/opensearch/test/MockLogAppender.java

+20-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.logging.log4j.Logger;
3636
import org.apache.logging.log4j.core.LogEvent;
3737
import org.apache.logging.log4j.core.appender.AbstractAppender;
38+
import org.apache.logging.log4j.core.config.Property;
3839
import org.apache.logging.log4j.core.filter.RegexFilter;
3940
import org.opensearch.common.logging.Loggers;
4041
import org.opensearch.common.regex.Regex;
@@ -68,11 +69,19 @@ public class MockLogAppender extends AbstractAppender implements AutoCloseable {
6869
* write to a closed MockLogAppender instance.
6970
*/
7071
public static MockLogAppender createForLoggers(Logger... loggers) throws IllegalAccessException {
71-
return createForLoggers(".*(\n.*)*", loggers);
72+
final String callingClass = Thread.currentThread().getStackTrace()[2].getClassName();
73+
return createForLoggersInternal(callingClass, ".*(\n.*)*", loggers);
7274
}
7375

7476
public static MockLogAppender createForLoggers(String filter, Logger... loggers) throws IllegalAccessException {
77+
final String callingClass = Thread.currentThread().getStackTrace()[2].getClassName();
78+
return createForLoggersInternal(callingClass, filter, loggers);
79+
}
80+
81+
private static MockLogAppender createForLoggersInternal(String callingClass, String filter, Logger... loggers)
82+
throws IllegalAccessException {
7583
final MockLogAppender appender = new MockLogAppender(
84+
callingClass + "-mock-log-appender",
7685
RegexFilter.createFilter(filter, new String[0], false, null, null),
7786
Collections.unmodifiableList(Arrays.asList(loggers))
7887
);
@@ -83,8 +92,8 @@ public static MockLogAppender createForLoggers(String filter, Logger... loggers)
8392
return appender;
8493
}
8594

86-
private MockLogAppender(RegexFilter filter, List<Logger> loggers) {
87-
super("mock", filter, null);
95+
private MockLogAppender(String name, RegexFilter filter, List<Logger> loggers) {
96+
super(name, filter, null, true, Property.EMPTY_ARRAY);
8897
/*
8998
* We use a copy-on-write array list since log messages could be appended while we are setting up expectations. When that occurs,
9099
* we would run into a concurrent modification exception from the iteration over the expectations in #append, concurrent with a
@@ -116,7 +125,14 @@ public void close() {
116125
for (Logger logger : loggers) {
117126
Loggers.removeAppender(logger, this);
118127
}
119-
this.stop();
128+
super.stop();
129+
}
130+
131+
@Override
132+
public void stop() {
133+
// MockLogAppender should be used with try-with-resources to ensure
134+
// proper clean up ordering and should never be stopped directly.
135+
throw new UnsupportedOperationException("Use close() to ensure proper clean up ordering");
120136
}
121137

122138
public interface LoggingExpectation {

0 commit comments

Comments
 (0)