log4j: ОШИБКА Попытка добавить к закрытому приложению с именем при написании приложения автоматически
Я пытаюсь добавить просеивающие приложения для log4j, а затем выполнить тесты JUnit для него. Тест JUnit просто пытается записать некоторый контент в ifx-1.log
, ifx-2.log
, а также ifx-3.log
файлы, а затем сравнить его с уже существующими файлами. Затем он пытается закрыть файл appender перед удалением файла.
У меня есть следующий код;
import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
public class Log4jUtil {
private static String pattern = "%d{HH:mm:ss.SSS} [%thread] %p %c{2}: %m%n";
public final static String DESCRIMINATOR_KEY = "logFileName";
private static final Logger logger = Logger.getRootLogger();
public static boolean addSiftingAppender(String logFileName) {
if (logger.getAppender(logFileName) == null) {
try {
String logfile = logFileName + ".log";
FileAppender fileAppender = new FileAppender(
new PatternLayout(pattern), logfile, true);
fileAppender.setName(logFileName);
fileAppender.addFilter(new RunIdFilter(logFileName));
fileAppender.setImmediateFlush(true);
logger.addAppender(fileAppender);
} catch (Exception e) {
logger.warn("[ifx] Failed to log to file using log4j logger", e);
return false;
}
}
return true;
}
public static void stopFileAppender(String logFileName) {
Appender appender = logger.getAppender(logFileName);
if (appender != null) {
appender.close();
}
}
}
RunIdFilter
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent;
public class RunIdFilter extends Filter {
private final String runId;
public RunIdFilter(String runId) {
this.runId = runId;
}
@Override
public int decide(LoggingEvent event) {
Object mdc = event.getMDC(Log4jUtil.DESCRIMINATOR_KEY);
if (runId.equals(mdc)) {
return Filter.ACCEPT;
}
return Filter.DENY;
}
}
JUnit test
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import jdk.nashorn.internal.ir.annotations.Ignore;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.MDC;
import com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner;
import com.anarsoft.vmlens.concurrent.junit.ThreadCount;
import lombok.extern.slf4j.Slf4j;
@RunWith(ConcurrentTestRunner.class)
@Slf4j
public class Log4jProgrammaticSiftingAppenderTest {
private final static int THREAD_COUNT = 3;
private static int count = 0;
Path resourceDirectory = Paths.get("src", "test", "resources");
// This function will write to file using log4j logger in a multi-threaded manner
@Test
@ThreadCount(THREAD_COUNT)
@Ignore
public void writeLogs() {
Thread.currentThread().setName("ifx-" + ++count);
Log4jUtil.addSiftingAppender(Thread.currentThread().getName());
MDC.put("logFileName", Thread.currentThread().getName());
log.info("Start test");
log.warn("hello in " + Thread.currentThread().getName());
// try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// log.error("Exception occurent in writing log4j ifx logs", e);
// }
MDC.remove(Thread.currentThread().getName());
MDC.put("logFileName", Thread.currentThread().getName());
log.error("hello2 in " + Thread.currentThread().getName());
log.info("End test");
MDC.remove(Thread.currentThread().getName());
Log4jUtil.stopFileAppender(Thread.currentThread().getName());
}
// This function will check if the written log file content is correct
@After
public void checkLogFileContent() {
int numberOfFiles = THREAD_COUNT;
boolean areEqual = true;
while (numberOfFiles > 0) {
try {
BufferedReader resourceDirectoryLogFileReader = new BufferedReader(
new FileReader(resourceDirectory + "\\logs\\ifx-" + numberOfFiles + ".log"));
BufferedReader logFileReader = new BufferedReader(new FileReader("ifx-" + numberOfFiles + ".log"));
String resourceDirectoryLogFileLine = resourceDirectoryLogFileReader.readLine();
String logFileLine = logFileReader.readLine();
while (resourceDirectoryLogFileLine != null && logFileLine != null)
{
if (!logFileLine.contains(resourceDirectoryLogFileLine))
{
areEqual = false;
log.error(
"[ifx] Logs don't contain the desired string. They should contain %s. But they have %s ",
resourceDirectoryLogFileLine, logFileLine);
fail("[ifx] Log files are not being written correctly for ifx using log4j logger");
}
resourceDirectoryLogFileLine = resourceDirectoryLogFileReader.readLine();
logFileLine = logFileReader.readLine();
}
resourceDirectoryLogFileReader.close();
logFileReader.close();
} catch (FileNotFoundException filenotFoundException) {
log.error("", filenotFoundException);
fail("[ifx] Log files are not being written correctly for ifx using log4j logger");
} catch (IOException ioException) {
log.error("", ioException);
fail("[ifx] Log files are not being written correctly for ifx using log4j logger");
} finally {
deleteFile("ifx-" + numberOfFiles + ".log");
}
numberOfFiles--;
}
assertTrue(areEqual);
}
private void deleteFile(String fileName) {
File file = new File(fileName);
if (file.exists() && !file.delete()) {
log.warn("Error occurred while deleting file %s", fileName);
}
}
}
Когда я запускаю тест JUnit, он проходит успешно, но я получаю следующую ошибку
log4j:ERROR Attempted to append to closed appender named [ifx-3].
log4j:ERROR Attempted to append to closed appender named [ifx-3].
2018-03-12 16:53:53,243 INFO Log4jProgrammaticSiftingAppenderTest - End test
log4j:ERROR Attempted to append to closed appender named [ifx-3].
2018-03-12 16:53:53,240 ERROR Log4jProgrammaticSiftingAppenderTest - hello2 in ifx-1
log4j:ERROR Attempted to append to closed appender named [ifx-2].
2018-03-12 16:53:54,257 INFO Log4jProgrammaticSiftingAppenderTest - End test
log4j:ERROR Attempted to append to closed appender named [ifx-3].
log4j:ERROR Attempted to append to closed appender named [ifx-2].
log4j:ERROR Attempted to append to closed appender named [ifx-3].
Я закрываю приложение, когда закончу писать и после MDC.remove
, Что мне не хватает?