JUnit XML system-out shows logs from all threads - log4j2

I have a JUnit5 integration test project where I'm running the test classes in parallel. My problem is that my log messages are being mixed together in the junit XML report generated after the test class finishes executing. This makes it difficult to debug the root cause of a failure because sometimes the xml containing a failed test won't even have a system-out section for the failed test because another xml report grabbed them already.
This xml report is showing the system-out from 3 out of 4 threads. How do I get this so that it is only showing the correct thread in the xml report?
<testcase name="beforeEachFailure" classname="tests.BeforeEachTests" time="32.962">
<failure type="java.lang.AssertionError">
<![CDATA[
java.lang.AssertionError
at tests.BeforeEachTests.beforeEach(BeforeEachTests.java:19)
]]>
</failure>
<system-out>
<![CDATA[
10:45:23.227 [Thread-0] INFO StaticUtil - Sleep for 3s
10:45:23.228 [Thread-0] INFO BeforeAllTests - continue doing a thing
10:45:26.228 [Thread-1] INFO StaticUtil - Sleep for 3s
10:45:29.228 [Thread-1] INFO StaticUtil - Sleep for 3s
10:45:32.229 [Thread-1] INFO StaticUtil - Sleep for 3s
10:45:32.229 [Thread-1] INFO TestTests - half the things done
10:45:35.230 [Thread-2] INFO StaticUtil - Sleep for 3s
10:45:38.231 [Thread-2] INFO StaticUtil - Sleep for 3s
]]>
</system-out>
</testcase>
Configuration for maven-surefire-plugin:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<statelessTestsetReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5Xml30StatelessReporter">
<version>3.0</version>
<usePhrasedTestCaseMethodName>true</usePhrasedTestCaseMethodName>
</statelessTestsetReporter>
<consoleOutputReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5ConsoleOutputReporter">
<encoding>UTF-8</encoding>
</consoleOutputReporter>
<statelessTestsetInfoReporter implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5StatelessTestsetInfoReporter">
<usePhrasedClassNameInTestCaseSummary>true</usePhrasedClassNameInTestCaseSummary>
</statelessTestsetInfoReporter>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<reportsDirectory>${basedir}/target/surefire-reports</reportsDirectory>
<includes>
<include>**/*Test*.java</include>
</includes>
<properties>
<configurationParameters>
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = same_thread
junit.jupiter.execution.parallel.mode.classes.default = concurrent
junit.jupiter.execution.parallel.config.strategy = fixed
junit.jupiter.execution.parallel.config.fixed.parallelism = 4
</configurationParameters>
</properties>
</configuration>
</plugin>
</plugins>
log4j2 configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %c{1} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

Related

log4j2 not logging to a file

Java 1.8, WebSphere Liberty 19.0.0.3 running in localhost, log4j v.2.17.1, Maven v.3.5.2
I have read some posts of similar issues, but I have not seen a solution that works for my case.
I cannot get anything to write to the log files. Presently, I am focusing on the root logger, as that writes to both the console and to file.
Pom file:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.17.1</version>
</dependency>
Here is the configuration for the root logger:
<Root>
<!-- change level to EROR -->
<Level value="TRACE"/>
<AppenderRef ref="APS-FILE"/>
<AppenderRef ref="STDOUT"/>
</Root>
The root logger is correctly calling the STDOUT appender and writing to the console. Note the pair of asterisks. Those match the output I am seeing in the console.
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout>
<Pattern>"** %d{DATE} %5p %c{1}:%L - %m%n **"</Pattern>
</PatternLayout>
</Console>
console output:
"** 07 Jan 2022 09:50:42,331 INFO WSWebSsoFilter:44 - Exiting WSWebSsoFilter.doFilter **"
"** 07 Jan 2022 09:50:42,331 INFO WSWebSsoFilter:44 - Exiting WSWebSsoFilter.doFilter **"
This is the appender configuration for root logger to write to file.
<RollingFile name="APS-FILE" fileName="/logs/aps/${company-code}/aps-A.log"
filePattern="logs/aps/${company-code}/aps-1.log">
<PatternLayout>
<Pattern>"%d{DATE} %5p %c{1}:%L - %m%n"</Pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy minSize="0"/>
<!--SizeBasedTriggeringPolicy size="10 MB"/-->
<SizeBasedTriggeringPolicy size="1 KB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
The OnStartupTriggeringPolicy is firing, as you can see from this file:
LastWriteTime Length Name
------------------ ------ ---------
1/7/2022 9:49 AM 0 aps-A.log
Any ideas about how to fix this? Thanks.
Try to change the STDOUT target to your rolling file appender
<Console name="STDOUT" target="**APS-FILE**">
<PatternLayout>
<Pattern>"** %d{DATE} %5p %c{1}:%L - %m%n **"</Pattern>
</PatternLayout>
</Console>

Including classpath resource in external log4j configuration

I use external log4j configuration and load it in servlet context listener using org.apache.logging.log4j.core.config.Configurator
I would like to reference some application properties (like application version) that are generated on build time.
Here is what I would like to do:
/external-folder/log4j.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xi="http://www.w3.org/2001/XInclude"
monitorInterval="60">
<xi:include href="log4j2-properties.xml" />
<Appenders>
<Console name="stdout" target="SYSTEM_OUT">
<PatternLayout pattern="%d %5p %t [${app-version}] %m (%F:%L) %n" />
</Console>
</Appenders>
<!-- ... -->
</Configuration>
log4j2-properties.xml
is supposed to be a classpath resource, #version# is filtered by gradle.
<?xml version="1.0" encoding="UTF-8"?>
<Properties>
<Property name="app-version">#version#</Property>
</Properties>
However this approach doesn't work. I can xinclude only resource from the same folder as top level log4j.xml
How can I solve my problem?
(I know how to do this using logback, but I would like to upgrade to log4j2)

facing issue with log4j2 : java.lang.ExceptionInInitializerError

I'm facing issue with log4j2
below is my log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.opensymphony.xwork2" level="info"/>
<Logger name="org.apache.struts2" level="info"/>
<Root level="info">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
below is the exception
<Jun 21, 2018 7:23:48 PM IST> <Error> <HTTP> <BEA-101165> <Could not load user defined filter in web.xml: org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.
java.lang.ExceptionInInitializerError
at org.apache.logging.log4j.core.impl.Log4jLogEvent.createContextData(Log4jLogEvent.java:472)
at org.apache.logging.log4j.core.impl.Log4jLogEvent.<init>(Log4jLogEvent.java:331)
at org.apache.logging.log4j.core.impl.DefaultLogEventFactory.createEvent(DefaultLogEventFactory.java:54)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:401)
at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:63)
Truncated. see log file for complete stacktrace
Caused By: java.lang.IllegalArgumentException: Initial capacity must be at least one but was 0
at org.apache.logging.log4j.util.SortedArrayStringMap.<init>(SortedArrayStringMap.java:102)
at org.apache.logging.log4j.core.impl.ContextDataFactory.createContextData(ContextDataFactory.java:109)
at org.apache.logging.log4j.core.impl.ContextDataFactory.<clinit>(ContextDataFactory.java:57)
at org.apache.logging.log4j.core.impl.Log4jLogEvent.createContextData(Log4jLogEvent.java:472)
at org.apache.logging.log4j.core.impl.Log4jLogEvent.<init>(Log4jLogEvent.java:331)
Truncated. see log file for complete stacktrace
>
above exception resulting to failure of war file deployment.
below are the jars used
1.commons-fileupload-1.3.3.jar
2.commons-io-2.5.jar
3.commons-lang3-3.6.jar
4.commons-logging-1.1.3.jar
5.freemarker-2.3.26-incubating.jar
6.javassist-3.20.0-GA.jar
7.log4j-1.2-api-2.11.0.jar
8.log4j-api-2.10.0.jar
9.log4j-core-2.11.0.jar
10.ognl-3.1.15.jar
11.struts2-core-2.5.16.jar
what do i need to correct?
Try upgrading log4j-api-2.10.0.jar to 2.11.0.
IllegalArgumentException is thrown from the constructor of org.apache.logging.log4j.util.SortedArrayStringMap:
public SortedArrayStringMap(final int initialCapacity) {
if (initialCapacity < 1) {
throw new IllegalArgumentException("Initial capacity must be at least one but was " + initialCapacity);
}
threshold = ceilingNextPowerOfTwo(initialCapacity);
}
and the given parameter initialCapacity has been changed since 2.11 as follows:
https://github.com/apache/logging-log4j2/blob/log4j-2.10.0/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataFactory.java#L54
https://github.com/apache/logging-log4j2/blob/log4j-2.11.0/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ContextDataFactory.java#L57
Updating the log4j-api and log4j-core from 2.11.1 to 2.12.0 solved the same problem for me.

log4j2 with XMLLayout How To?

There are very less info on the web for log4j2 with XMLLayout.
I have not found any links with simple examples (log4j2 + XMLLayout);
Can somebody post a simple example of the same ....
with regards
Karthik
Here is a minimal sample application that demonstrates use of XmlLayout.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test-log4j2</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Test Log4J 2</name>
<description>Test Log4J 2</description>
<properties>
<jackson.version>2.5.0</jackson.version>
<log4j.version>2.5</log4j.version>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<mainClass>Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${project.artifactId}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
</project>
src/main/java/Main.java
import org.apache.logging.log4j.LogManager;
public class Main {
public static void main(String[] args) {
LogManager.getLogger(Main.class).info("This is a test.");
}
}
src/main/resources/log4j2.properties
status = ERROR
name = PropertiesConfig
rootLogger.level = INFO
rootLogger.appenderRefs = CONSOLE
rootLogger.appenderRef.CONSOLE.ref = CONSOLE
appenders = CONSOLE
appender.CONSOLE.type = Console
appender.CONSOLE.name = CONSOLE
appender.CONSOLE.layout.type = XmlLayout
appender.CONSOLE.layout.complete = true
appender.CONSOLE.layout.compact = true
Demo
> mvn clean package
> java -jar target/test-log4j2.jar
<?xml version="1.0" encoding="UTF-8"?><Events xmlns="http://logging.apache.org/log4j/2.0/events"><Event xmlns="" xmlns="http://logging.apache.org/log4j/2.0/events" timeMillis="1451539702378" thread="main" level="INFO" loggerName="Main" endOfBatch="false" loggerFqcn="org.apache.logging.log4j.spi.AbstractLogger"><Message>This is a test.</Message></Event></Events>
The trickiest part was figuring out the Jackson dependency required. Without that, Log4J 2 experiences internal ClassNotFoundException errors and fails to initialize XmlLayout.
If you prefer XML-based configuration, then here is the equivalent XML configuration.
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error" name="XMLConfig">
<Loggers>
<Root level="INFO">
<AppenderRef ref="CONSOLE"/>
</Root>
</Loggers>
<Appenders>
<Console name="CONSOLE">
<XMLLayout complete="true" compact="true"/>
</Console>
</Appenders>
</Configuration>

Log4j 2 not logging to file

I am trying to use log4j 2 for the first time but having trouble getting my code to log to a file.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.3</version>
</dependency>
My code is not logging to my File Appender or Console Appender:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout>
<Pattern pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</PatternLayout>
</Console>
<File name="File" fileName="resources/app-log.log">
<PatternLayout>
<Pattern pattern="%d{MM.dd.yyyy HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Logger name="x.y" level="ALL" additivity="true">
<AppenderRef ref="File"/>
<AppenderRef ref="Console"/>
</Logger>
</Loggers>
</Configuration>
Here is my Java code doping the logging:
package x.y;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Foo {
private static Logger logger = LogManager.getLogger(Foo.class.getName());
public static void main(String[] args) {
Foo foo = new Foo;
logger.info("Application starting");
}
}
Edit: My app is logging to the console but not using the pattern layout I specified. My app is a Maven app and I have put log4j2.xml in src/main/resources. I know my configuration xml is being read because when I put in something invalid I get an exception.
Figured it out. Changed to:
<PatternLayout pattern="%d{MM.dd.yyyy HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
Now it logging to my file.

Resources