I am trying to write log4j2 logs using a specific pattern:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout charset="UTF-8"
pattern="%d{HH:mm:ss.SSS} ${main:-jobId} %-5.-5level %-25.-25c{1}%-25.-25method(%5.5line) - %msg%n" />
</Console>
<RollingFile name="LogFile" fileName="${sys:logFile}"
filePattern="${sys:logFile}-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout charset="UTF-8"
pattern="%d{yyy-MM-dd HH:mm:ss.SSS} ${main:-jobId} [%-30.-30t] %-5.-5level %-25.-25c{1}%-25.-25method(%5.5line) - %msg%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="100 MB" />
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="LogFile" level="debug" />
<AppenderRef ref="Console" level="info" />
</Root>
</Loggers>
</Configuration>
I am passing a few arguments -o abc -d def -jobId 1234 -DlogFile /usr/lib/logpath.log This works for system parameters but the log prints as:
15:33:34.889 jobId INFO Test main ( 74) - -b
15:33:34.890 jobId INFO Test main ( 74) - -o
15:33:34.890 jobId INFO Test main ( 74) - account
15:33:34.890 jobId INFO Test main ( 74) - document
15:33:34.890 jobId INFO Test main ( 74) - -d
15:33:34.891 jobId INFO Test main ( 74) - rest
15:33:34.891 jobId INFO Test main ( 74) - -l
15:33:34.891 jobId INFO Test main ( 74) - 100
15:33:34.891 jobId INFO Test main ( 74) - -skipmd
15:33:34.891 jobId INFO Test main ( 74) - -db
15:33:34.891 jobId INFO Test main ( 74) - -jobId
15:33:34.891 jobId INFO Test main ( 74) - 1234
The code in main starts with:
public static void main(String[] args) throws Exception
{
MainMapLookup.setMainArguments(args);
for (String s : args)
logger.info(s);
...
}
I have tried using the argument based on the index and it works. However, the main argument lookup does not seem to work. Am I missing something here?
Maybe an off-topic question, what is the legit use-case of handling system variable over the main arguments in logging?
The reason for it not working is because there is a collision on the format between MainMapLookup by name and the StrSubstitutor default value delimiter.
${main:-jobId} gets parsed as Property main OR jobId
This is a known bug reported here: https://issues.apache.org/jira/browse/LOG4J2-1013
Related
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>
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.
I try to config log4j to appends loggs in diffrent color per log type (INFO, ERROR, DEBUG etc.)
Here is my log4j2.xml:
<Configuration monitorInterval="60">
<Properties>
<Property name="log-path">applogs</Property>
</Properties>
<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout>
<pattern>
%highlight{%d{HH:mm:ss.SSS} %-5level %logger{36}.%M() [%L] - %msg%n}{FATAL=red, ERROR=red, WARN=yellow, INFO=green}
</pattern>
</PatternLayout>
</Console>
<someMoreAppenders>
</Appenders>
<Loggers>
<Logger name="RepositoriesController" level="info" additivity="false">
<AppenderRef ref="Console-Appender"/>
</Logger>
<Root level="error" additivity="false">
<AppenderRef ref="Console-Appender"/>
</Root>
</Loggers>
</Configuration>
And in class RepositoriesController, i create logger in this way:
private static final Logger logger = LogManager.getLogger("RepositoriesController");
logger.info("Hello, World!");
My log4j.properties are empty. Output seems to be formatted used by my pattern but font color is still white:
Intelij console
i tried to add this properties:
spring.main.banner-mode=off
spring.output.ansi.enabled=ALWAYS
and modify pattern but without succesed, any advices?
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t]
%highlight{%level}{FATAL=bg_red, ERROR=red, WARN=yellow, INFO=green, DEBUG=blue} - %msg%n" />
</Console>
%highlight{%level} - using this you can highlight colors for different levels of logs.
This will generate output as:
I have a little problem and canĀ“t find a solution. I want to set pattern layout for level info another than for level warn. If I have a log in level INFO everything is OK, but if the log is levelWARN it is written out into console two times (as level info and as level warn). Simply all logs at a specific level is written out us log at that level and the level below.
I want to logs in level INFO write out to console like: "%-5level %d{dd-MM-yyyy HH:mm:ss} %msg%n" and level WARN like "%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n".
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="ConsoleInfo" target="SYSTEM_OUT">
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} %msg%n"/>
</Console>
<Console name="ConsoleWarning" target="SYSTEM_OUT">
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n"/>
</Console>
<File name="File" fileName="logs/cli.log">
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n"/>
</File>
</Appenders>
<Loggers>
<Root level="ALL">
<AppenderRef ref="ConsoleInfo"/>
<AppenderRef ref="ConsoleWarning"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
As I understand it you want to have log events with a level of WARN or higher (WARN,ERROR,FATAL) go to the "ConsoleWarning" appender only rather than going to both "ConsoleWarning" and "ConsoleInfo".
The simplest way to do this would be to modify your filter configuration in your "ConsoleInfo" appender to basically do the opposite approach like this:
<Console name="ConsoleInfo" target="SYSTEM_OUT">
<ThresholdFilter level="WARN" onMatch="DENY" onMismatch="ACCEPT"/>
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} %msg%n"/>
</Console>
This works because as the log4j2 manual states:
This filter returns the onMatch result if the level in the LogEvent is the same or more specific than the configured level and the onMismatch value otherwise. For example, if the ThresholdFilter is configured with Level ERROR and the LogEvent contains Level DEBUG then the onMismatch value will be returned since ERROR events are more specific than DEBUG.
This will cause the appender to accept only events that have a level less than WARN.
Another possible solution would be to use a RoutingAppender to specify the destination for each level. If you do it this way then you don't need the ThresholdFilters at all. Also note that you can ignore events of specific levels by not providing a default route and not providing a route for that level. For example, if you remove <Route ref="ConsoleInfo" key="DEBUG" /> from the configuration below then all DEBUG events will be ignored by the routing appender and will not be printed to console. Here is the configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="ConsoleInfo" target="SYSTEM_OUT">
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} %msg%n"/>
</Console>
<Console name="ConsoleWarning" target="SYSTEM_OUT">
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n"/>
</Console>
<File name="File" fileName="logs/cli.log">
<PatternLayout pattern="%-5level %d{dd-MM-yyyy HH:mm:ss} [%l] %msg%n"/>
</File>
<Routing name="Routing">
<Routes>
<Script name="RoutingInit" language="JavaScript"><![CDATA[
logEvent.getLevel();]]>
</Script>
<Route ref="ConsoleInfo" key="TRACE" />
<Route ref="ConsoleInfo" key="DEBUG" />
<Route ref="ConsoleInfo" key="INFO" />
<Route ref="ConsoleWarning" key="WARN" />
<Route ref="ConsoleWarning" key="ERROR" />
<Route ref="ConsoleWarning" key="FATAL" />
</Routes>
</Routing>
</Appenders>
<Loggers>
<Root level="ALL">
<AppenderRef ref="Routing"/>
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
Hope this helps!
I have configured log4j2.xml within eclipse and all logs write correctly to a file.
When I export maven project as a jar and run from command promt the logs are displayed on the console instead of writing to a file.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace">
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
<File name="file_all" fileName="C:/log/logsALL.log" immediateFlush="true" append="true">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<Root level="ERROR">
<AppenderRef ref="file_all"/>
</Root>
<Logger name="com.api.main" level="INFO">
<AppenderRef ref="file_all"/>
</Logger>
</Loggers>
</Configuration>
When log4j starts up, it shows internal logging on the console (because status=trace in the configuration).
This internal log should show the location of the config file that is being used. Double-check that this is the correct location: I suspect that an old config file is being loaded that logs to the console...