SLF4j with Log4j2 ERROR Unable to invoke factory method in class class ...RollingFileAppender for element RollingFile
<p>I have some WebDriver tests running in parallel in TestNG. And I want to be able to have logging log to a separate file for each test that's run in a directory structure like this:</p>

<pre><code>target\logs\TestNGSuiteName(SuiteStartTime)
    Test1ClassName.TestMethod1 (TestStartTime).log
    Test1ClassName.TestMethod2 (TestStartTime).log
</code></pre>

<p>etc.  </p>

<p>Using Log4j and SLF4j is it possible to create a separate log file for each individual TestNG tests?</p>

<p>I have attempted using a RollingFileAppender but it doesn't look like that is designed for having separate instances run for separate log files like I'm attempting to do here.</p>

<p>And I'm getting the errors</p>

<pre><code>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.
</code></pre>

<p>Log4j2.xml
 </p>

<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;Configuration&gt;
        &lt;Routing name="Routing"&gt;
            &lt;Routes pattern="$${ctx:ROUTINGKEY}"&gt;
                &lt;Route&gt;
                    &lt;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"&gt;
                        &lt;PatternLayout&gt;
                            &lt;pattern&gt;%d{HH:mm:ss.SSS} [%t] %p %c{3} - %m%n&lt;/pattern&gt;
                        &lt;/PatternLayout&gt;
                        &lt;Policies&gt; &lt;!-- 6 hour rollover--&gt;
                            &lt;TimeBasedTriggeringPolicy interval="6" modulate="true"/&gt;
                            &lt;SizeBasedTriggeringPolicy size="10 MB"/&gt;
                        &lt;/Policies&gt;
                    &lt;/RollingFile&gt;
                &lt;/Route&gt;
            &lt;/Routes&gt;
        &lt;/Routing&gt;
    &lt;/Appenders&gt;
    &lt;Loggers&gt;
        &lt;Logger name="james.log" level="debug" additivity="false"&gt;
            &lt;AppenderRef ref="Routing"/&gt;
        &lt;/Logger&gt;
    &lt;/Loggers&gt;
&lt;/Configuration&gt;
</code></pre>

<p>LumberJack.java
 </p>

<pre><code>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&lt;String&gt; methodLogName = new ThreadLocal&lt;&gt;();
    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");
    }
}
</code></pre>