Ich habe einige WebDriver Tests in TestNG parallel ausgeführt. Und ich möchte in der Lage für jeden Testprotokollierung Protokoll in eine separate Datei zu haben, die in einer Verzeichnisstruktur wie folgt laufen gelassen:SLF4j mit Log4j2 ERROR Factory-Methode in Klasse Klasse kann nicht aufgerufen werden ... RollingFileAppender für Element RollingFile
target\logs\TestNGSuiteName(SuiteStartTime)
Test1ClassName.TestMethod1 (TestStartTime).log
Test1ClassName.TestMethod2 (TestStartTime).log
usw.
Mit Log4j und SLF4J ist es möglich, eine separate zu erstellen Protokolldatei für jeden einzelnen TestNG-Test?
Ich habe versucht, einen RollingFileAppender zu verwenden, aber es sieht nicht so aus, dass für separate Instanzen getrennte Protokolldateien ausgeführt werden sollen, wie ich hier versuche.
Und ich bin immer die Fehler
ERROR Unable to invoke factory method in class class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile.
Unable to create Appender of type RollingFile.
Log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Routing name="Routing">
<Routes pattern="$${ctx:ROUTINGKEY}">
<Route>
<RollingFile name="Rolling-${ctx:ROUTINGKEY}"
fileName="target/logs/${ctx:suiteTimestamp}/${ctx:testName} (${ctx:testStartTime}).log"
filePattern="target/logs/${ctx:testname} ${ctx:testStartTime}_%i.log.gz">
<PatternLayout>
<pattern>%d{HH:mm:ss.SSS} [%t] %p %c{3} - %m%n</pattern>
</PatternLayout>
<Policies> <!-- 6 hour rollover-->
<TimeBasedTriggeringPolicy interval="6" modulate="true"/>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
</RollingFile>
</Route>
</Routes>
</Routing>
</Appenders>
<Loggers>
<Logger name="james.log" level="debug" additivity="false">
<AppenderRef ref="Routing"/>
</Logger>
</Loggers>
</Configuration>
LumberJack.java
package james.log;
import james.util.ConcurrentDateFormatAccess;
import org.apache.logging.log4j.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.ITestContext;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.lang.reflect.Method;
/**
* @author james.affleck
*/
public class LumberjackTest {
private static final Logger logger = LoggerFactory.getLogger(LumberjackTest.class);
private static ThreadLocal<String> methodLogName = new ThreadLocal<>();
private static String suiteName = "";
@BeforeMethod
public void loggerDoTheThings(ITestContext context, Method method) {
if(suiteName.isEmpty()) {
String suite = context.getSuite().getName() + "(";
String suiteTime = new ConcurrentDateFormatAccess().getCurrentDateSPrecision();
suite += suiteTime + ")";
suiteName = suite;
}
// Test filename = testClass.testMethodname
String classname = this.getClass().getName();
classname = classname.substring(classname.lastIndexOf(".") + 1); //get rid of package info we don't care about
String testName = classname + "." + method.getName();
// Using this to store logger instance for later
String testStart = new ConcurrentDateFormatAccess().getCurrentDateMSPrecision();
methodLogName.set(testName + testStart);
ThreadContext.put("suiteTimestamp", suiteName);
ThreadContext.put("testName", testName);
ThreadContext.put("testStartTime", testStart);
}
@AfterMethod
public void closeTheThings() {
methodLogName.set(null);
}
@AfterSuite
public void closeSuite() {
suiteName = null;
}
@Test
public void testLog1() {
logThings();
}
@Test
public void testLog2() {
logThings();
}
public void logThings() {
logger.info("info message");
logger.debug("debug message");
logger.warn("warn message");
}
}
Haben Sie einen Stacktrace mit der Fehlermeldung? Es ist nicht klar, warum der Fehler angehängt wird. – juherr
Hallo Julien, ich habe gerade den Code erneut ausgeführt, und es gibt keine Stack-Trace. Die Protokolldateien werden ordnungsgemäß erstellt, aber ihnen wird nichts geschrieben. Ich bin mir nicht sicher, welchen Teil ich hier falsch mache, aber ich denke, dass es mit dieser Zeile zu tun haben kann: LoggerFactory.getLogger (LumberjackTest.class); Oder der RollingFile Appender ist nicht der richtige Weg, dies zu tun. Ich konnte keinen Weg finden, Log-Dateien-Namen zu erhalten, indem ich eine Variable wie die folgende mit einem Datei-Appender übergab. –
@JulienHerr fileName = "target/logs/$ {ctx: suiteTimestamp}/$ {ctx: testName ($ {ctx: testStartTime}). Log" –