Log4j 2 seems to get pumped up on steroids if you started MDC logging for free already using the copied file.
Anyway, your log4j fragment looks weird. We see the element tag of the closing appender, but not its corresponding opening appender tag.
Your download file name has a space between the dynamic test name and the test start time.
fileName = "target / logs / $ {ctx: packageTimestamp} / $ {ctx: testName ($ {ctx: testStartTime}) log"
Suggestion: How about you sharing the conqueror.
If this type of dynamic configuration is really supported. Why are you not trying to configure only the dynamic template file name first?
It seems you are putting your log4j configuration on full steroids before you have the easiest configuration possible for your problem.
So, put your feet on the break and focus on getting: FileName = "target / logs / dummyTest_dynamicComponent _ $ {CTX: ASMAP} .log"
To work for you.
In log4j 1.x, you will have the log4j.debug system property to help you understand the bugy configuration, and the result was very useful.
Finally, in log4j 1.X, the function you want to use will require you to explicitly program the MDC application. Your MDC binder usually creates an instance of RollingFileAppenders to enter the files, and you will use the MDC context pairs (keyxValue) entered by the user.
But what you do looks promising, just reduce the complexity level of your configuration if it does not work for you.
Finally, I would be very surprised if you saw that any log file is created when the following error occurs:
ERROR Cannot call factory method on class class org.apache.logging.log4j.core.appender.RollingFileAppender on the RollingFile element. Failed to create Appender type RollingFile.
Log4j tells you: Hey, this is the application that you define. My factory trying to execute this procedure will not be able to process it, and I will not create an instance of the copied file with this configuration.
So you have to fix this configuration.
Adding an answer.
Here you have a working Log4j 2 configuration to accomplish what you want:
The first fragment, if the configuration is log4j 2, where you will see that the root logger is given 3 different applications for playback. You mainly care about appender 3, but the other two add-ons are a more typical starting point.
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> <RollingFile name="AppenderTwo" fileName="target/logs/test.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="10 MB" /> </Policies> </RollingFile> <Routing name="AppenderThree"> <Routes pattern="${ctx:stackOverFlow}"> <Route> <RollingFile name="NestedAppender-${ctx:stackOverFlow}" fileName="target/logs/test_threadContext_${ctx:stackOverFlow}.log" filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m%n</Pattern> </PatternLayout> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="10 MB" /> </Policies> </RollingFile> </Route> <Route ref="Console" key="${ctx:stackOverFlow}" /> </Routes> </Routing> </Appenders> <Loggers> <Root level="all"> <AppenderRef ref="Console" /> <AppenderRef ref="AppenderTwo" /> <AppenderRef ref="AppenderThree" /> </Root> </Loggers> </Configuration>
This latest appender is configured based on the following thread: https://issues.apache.org/jira/browse/LOG4J2-129
The second snippet is a dummy junit test, which you exit from the eclipse when you create a new maven project from the base archetype. In the test fragment, you will see that the context of the stack context in the stream is set to the stream context, as in your fragments.
package stackoverflow.test.tutorial; import org.apache.logging.log4j.ThreadContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; public class AppTest extends TestCase { private static final Logger LOGGER = LoggerFactory.getLogger(TestCase.class); public AppTest(String testName) { super(testName); } public static Test suite() { return new TestSuite(AppTest.class); } public void testApp() { ThreadContext.put("stackOverFlow", "dummyContextValue"); LOGGER.info("LALAL LLA"); assertTrue(true); } }
The last snippet is the maven dependencies:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>stackoverflow.test</groupId> <artifactId>tutorial</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>tutorial</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.5</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.5</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
I find it funny that log4j contributes this new Routing Appender. If you could imagine how many people had to implement their own copied file applications with MDC context support to make this type of material. This is very useful in web applications.
Greetings.