Log4j2 release 2.11.0 / 2.11.1 worked fine in Java 8 applications but not in Java 11
Here is an example of log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="log-path">C:\\MyTestXXXX\\EnterpriseLogs</Property>
</Properties>
<Appenders>
<RollingFile name="MyTestOnly" fileName="${log-path}\ServerLog.log" filePattern="${log-path}\ServerLog_%d{yyyy-MM-dd}_%i.log" append="true">
<PatternLayout>
<Pattern>[#%d{HH:mm:ss}|%p|%m#]%n</Pattern>
</PatternLayout>
<Policies>
<CronTriggeringPolicy schedule="0 0 0 * * ?" evaluateOnStartup="true"/>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
<DefaultRolloverStrategy/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="OnlyLOG" additivity="true">
<AppenderRef ref="MyTestOnly" level="ALL" />
<Logger>
<Root level="ALL" />
</Loggers>
</Configuration>
In the Java source code, I did this:
import org.apache.logging.log4j.*;
import org.apache.logging.log4j.core.Logger;
...
// Get org.apache.logging.log4j.core.Logger
Logger logger = (Logger) LogManager.getLogger("OnlyLOG");
logger.log(Level.forName("INFO", 600), "Log this text now!", new Exception("xxxxxx"));
Running in Java 8, I can see that serverLog.log has the content, which is good.
Running in Java 11, there is no log.
Through further study (debugging), I found this line interesting:
Logger logger = (Logger) LogManager.getLogger("OnlyLOG");
After execution, in Java 8, logger was something like "ALL in 2f333739", and log was fine.
But in Java 11, logger was something like "ERROR in 2f333739" and there was no log. Obviously the level became "ERROR" instead of "ALL".
So, I tries this in Java 11:
Level loggerLevel = logger.getLevel(); // Obviously it is ERROR level
logger.log(loggerLevel, "Log this text now!", new Exception("xxxxxx"));
The log happened in console (likely went through Root), not in the ServerLog.log that was configured in log4j2.xml for logger OnlyLOG.
So, what caused the level difference between Java 8 and Java 11? In other words, what should be modified so that in Java 11, log can still work the same way as in Java 8?
The issue is resolved. Here is the reason.
I used a new Eclipse IDE to run Java 11, when adding a project, I added lib folder to the class path, since log4j2.xml was in the lib folder. Now I inspected the IDE configuration a second time and found out that the lib folder was not in the class path. After a second attempt, the configuration is fine and logging becomes normal.
I made a second test by adding a brand new project into the Eclipse IDE. Interestingly enough, when adding lib folder to the class path, indeed I had to try twice, because the first time it was not added. By the way, the computer runs Windows 10. This did not happen when using a computer running in Windows 7.
Regardless, Log4j2 works fine in both Java 8 and Java 11.
Related
Goal: Have Log4j2:
Create the root "logs" directory if it doesn't exist.
Create an "archive" directory if it doesn't exist so RollingFile appender can save the rolled logs.
Expected Result:
..\logs\MyLog.log
..\logs\archive\MyLog_2022-03-03_1.log
..\logs\archive\MyLog_2022-03-03_2.log
..\logs\archive\MyLog_2022-03-03_3.log
.
.
..\logs\archive\MyLog_2022-03-03_20.log
I'm expecting the creation of "logs" & "archive" directories in case they aren't there on start-up/1st roll.
Actual Results:
Regarding the "logs" directory:
if the "logs" directory doesn't exist prior to start-up then system continues running without logging anything or creating the directory.
if the "logs" directory exists prior to start-up then it saves the main log file to it.
Regarding the "archive" directory for rolling logs:
if the "archive" directory doesn't exist prior to start-up then it is created, the system crashes and an exception is thrown.
if the "logs" directory exists prior to start-up then the system crashes and an exception is thrown.
What I have tried:
Replacing the properties with their actual hard-coded values.
Replacing the path with "./" at the beginning.
Replacing the path with "../" at the beginning.
Replacing the beginning of the path with various possible Lookups from Log4j2's documentation.
Hard-coding the full-path, which worked but is not an option to use as it will change according to the customer's installation location.
Configuration:
<Properties>
<Property name="log.dir">logs</Property>
<Property name="log.file">MyLog</Property>
<Property name="pattern">%d %-5p [%t] %c{2}:%L - %m%n</Property>
</Properties>
<RollingFile name="MainLog" fileName="${log.dir}/${log.file}.log" filePattern="${log.dir}/archive/${log.file}_%d{MM-dd-yyyy}_%i.log.gz">
<PatternLayout pattern="${pattern}" />
<Policies>
<SizeBasedTriggeringPolicy size="20 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
Research:
I've tried various Google searches and looked into many Stackoverflow questions, I will not be listing them here as they do not include any actual relevant data. Weirdly enough, I wasn't able to find any similar question.
What am I missing?
I would like to reduce the log level displayed in the console during my automation run in QAF / QMetry framework. When I tried playing around in log4j.properties, it is not showing any difference in the console logging. Tried following in log4j.properties:
log4j.logger.com.qmetry.qaf=ERROR
log4j.rootCategory=off
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=ERROR
log4j.appender.CONSOLE.Follow=false
Note: Not seeing any ws.log file created as mentioned in the below property
log4j.logger.com.qmetry.qaf.automation.ws=DEBUG, file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.file=${outputDir}/ws.log
log4j.appender.file.MaxFileSize=1GB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.conversionPattern=%d{[dd.MM.yyyy] [HH:mm:ss]} %p [%t] %c (%F:%L) - %m%n
Log4j is set in the Maven config: (I have also tried putting the log4j config in the src folder).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>${testSuiteFile}</suiteXmlFile>
</suiteXmlFiles>
<reportsDirectory>${test.results.dir}/${run.time}</reportsDirectory>
<systemPropertyVariables>
<org.uncommons.reportng.xml-dialect>testng</org.uncommons.reportng.xml-dialect>
<org.uncommons.reportng.escape-output>false</org.uncommons.reportng.escape-output>
<log4j.configuration>file:///${resource.dir}/log4j.properties</log4j.configuration>
<outputDir>${output.dir}</outputDir>
<test.results.dir>${output.dir}/html</test.results.dir>
<json.report.root.dir>${test.results.dir}</json.report.root.dir>
<json.report.dir>${output.dir}/json</json.report.dir>
<selenium.screenshots.dir>${output.dir}/img</selenium.screenshots.dir>
<selenium.screenshots.relative.path>../img</selenium.screenshots.relative.path>
</systemPropertyVariables>
</configuration>
</plugin>
You need to set log4j properties file location. Refer sample ant or maven project. If you are not familiar, easiest way is to move log4j.properties file under src directory.
I have an application with the name cat_tiger.war that gets deployed as localhost:8080/cat_tiger but I want to change the context path to localhost:8080/cat/lion/ instead. I've added the META-INF/context.xml file as
<?xml version="1.0" encoding="UTF-8"?>
<Context copyXML="true" docBase="cat_tiger" path="/cat/lion"/>
and the server.xml file to be
<Host name="localhost" appBase="webapps"
copyXML="true" deployXML="true"
unpackWARs="true" autoDeploy="true">
but it still deploys as localhost:8080/cat_tiger/
Any ideas as to what else needs to be changed?
EDIT:
[1] Tomcat 8.5.3
[2]
04-Sep-2018 13:50:41.830 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of configuration descriptor [/opt/tomcat/conf/Catalina/localhost/cat_tiger.xml] has finished in [2,750] ms
...
...
04-Sep-2018 13:50:39.070 WARNING [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDescriptor A docBase [/opt/tomcat/webapps/cat_tiger] inside the host appBase has been specified, and will be ignored
[3] I'm deploying through Netbeans but will have to be deployed in a Docker container eventually.
I don't understand why you are having problems, but I've created the web project using NetBeans 8.2 (File > New Project... > Java Web > Web Application), and successfully changed the context, so perhaps if I give details of my project you can identify where there's a crucial difference.
1 cat_tiger\web\META-INF\context.xml
My file looks identical to yours:
<?xml version="1.0" encoding="UTF-8"?>
<Context copyXML="true" docBase="cat_tiger" path="/cat/lion"/>
[2] Run output
Select the project node, right click and select Run from the popup menu to run on Tomcat 8.5:
ant -f D:\\NB82\\cat_tiger -Dnb.internal.action.name=run -Ddirectory.deployment.supported=true -DforceRedeploy=false -Dnb.wait.for.caches=true -Dbrowser.context=D:\\NB82\\cat_tiger -Duser.properties.file=C:\\Users\\johndoe\\AppData\\Roaming\\NetBeans\\8.2\\build.properties run
init:
deps-module-jar:
deps-ear-jar:
deps-jar:
library-inclusion-in-archive:
library-inclusion-in-manifest:
compile:
compile-jsps:
In-place deployment at D:\NB82\cat_tiger\build\web
Deployment is in progress...
deploy?config=file%3A%2FC%3A%2FUsers%2Fjohndoe%2FAppData%2FLocal%2FTemp%2Fcontext7953615149857268018.xml&path=/cat/lion
OK - Deployed application at context path [/cat/lion]
Start is in progress...
start?path=/cat/lion
OK - Started application at context path [/cat/lion]
run-deploy:
Browsing: http://localhost:8080/cat/lion
run-display-browser:
run:
BUILD SUCCESSFUL (total time: 0 seconds)
Actually, you probably don't need to run the application to see the problem; just select Deploy instead of Run from the popup menu. This is the output I get from Deploy:
ant -f D:\\NB82\\cat_tiger -Dnb.internal.action.name=redeploy -Ddirectory.deployment.supported=true -DforceRedeploy=true -Dnb.wait.for.caches=true -Dbrowser.context=D:\\NB82\\cat_tiger -Duser.properties.file=C:\\Users\\johndoe\\AppData\\Roaming\\NetBeans\\8.2\\build.properties run-deploy
init:
deps-module-jar:
deps-ear-jar:
deps-jar:
library-inclusion-in-archive:
library-inclusion-in-manifest:
compile:
compile-jsps:
Undeploying ...
undeploy?path=/cat_tiger
OK - Undeployed application at context path [/cat_tiger]
In-place deployment at D:\NB82\cat_tiger\build\web
Deployment is in progress...
deploy?config=file%3A%2FC%3A%2FUsers%2Fjohndoe%2FAppData%2FLocal%2FTemp%2Fcontext5063723197082921373.xml&path=/cat/lion
OK - Deployed application at context path [/cat/lion]
Start is in progress...
start?path=/cat/lion
OK - Started application at context path [/cat/lion]
run-deploy:
BUILD SUCCESSFUL (total time: 0 seconds)
[3] Tomcat log
Here are the deployment details in the Tomcat log, where you can see that my deployment shows the context correctly, whereas yours does not:
05-Sep-2018 23:09:09.321 INFO [http-nio-8080-exec-6] org.apache.catalina.startup.HostConfig.deployDescriptor Deploying configuration descriptor [C:\apache-tomcat-8.5.20\conf\Catalina\localhost\cat#lion.xml]
05-Sep-2018 23:09:09.334 INFO [http-nio-8080-exec-6] org.apache.catalina.startup.HostConfig.deployDescriptor Deployment of configuration descriptor [C:\apache-tomcat-8.5.20\conf\Catalina\localhost\cat#lion.xml] has finished in [13] ms
05-Sep-2018 23:09:09.338 INFO [http-nio-8080-exec-5] org.apache.catalina.util.LifecycleBase.start The start() method was called on component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/cat/lion]] after start() had already been called. The second call will be ignored.
[4] C:\apache-tomcat-8.5.20\conf\Catalina\localhost\cat#lion.xml
This is the file Tomcat created when deploying the application:
<?xml version="1.0" encoding="UTF-8"?>
<Context copyXML="true" docBase="D:\NB82\cat_tiger\build\web" path="/cat/lion"/>
Note that docBase contains an absolute path.
[5] server.xml
Here's the entire content. I'm using Tomcat 8.5. Note that the <host> element is slightly different to yours, but when I added copyXML="true" deployXML="true" to the <host> element (so it looked like yours) everything continued to work fine:
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
</GlobalNamingResources>
<Service name="Catalina">
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" relaxedQueryChars="[]|{}^+\`"<>"/>
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
<Engine defaultHost="localhost" name="Catalina">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/>
<Context docBase="C:\apache-tomcat-8.5.20\wtpwebapps\PlusServlet" path="/PlusServlet" reloadable="true" source="org.eclipse.jst.jee.server:PlusServlet"/>
</Host>
</Engine>
</Service>
</Server>
Updated 9/6/2018:
Ignore the answer given above! Even though it happened to work for my configuration, the approach is explicitly disallowed in the Tomcat documentation.
Specifically, path should not be specified within the <Context> of a context.xml file placed within the application's META-INF directory. From the path description in the Common Attributes section of the Tomcat 8.5 documentation for the Context Container:
This attribute must only be used when statically defining a Context in
server.xml. In all other circumstances, the path will be inferred from
the filenames used for either the .xml context file or the docBase.
Even when statically defining a Context in server.xml, this attribute
must not be set unless either the docBase is not located under the
Host's appBase or both deployOnStartup and autoDeploy are false. If
this rule is not followed, double deployment is likely to result.
My unmanaged server extension uses slf4j-log4j logging. When log4j.properties is bundled with the extension, logging works fine.
When it's not bundled but instead placed in Neo4j's conf directory, I assumed
wrapper.java.additional=-Dlog4j.configuration=file:conf/log4j.properties
from neo4j-wrapper.conf would ensure that it's picked up.
However, I don't see the log file being created or the specified log level being used.
The config file must be correct because it works as designed when bundled with the extension.
Adding -Dlog4j.debug as suggested in other posts adds no further information.
Is there something I've missed? I'm using Neo4j 2.1.3 on Mac OS X
Neo4j internally has the logback jars aboard, so every logging using slf4j will be handled by logback.
My approach to logging from an unmanaged extension is as follows:
Set up your logger in the unmanaged extension have a dependency on slf4j-api (do not add and other slf4j implementations to the classpath) and use the logger like this:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(com.mycompany.UnmanagedExtension.class);
Modify conf/custom-logback.xml and amend at the end:
<appender name="EXTENSIONLOG" class="ch.qos.logback.core.FileAppender">
<file>extensions.log</file>
<encoder>
<pattern>%date{yyyy-MM-dd HH:mm:ss.SSSZ} %-5level [%logger{15}]: %message%n</pattern>
</encoder>
</appender>
<logger name="com.mycompany" level="debug">
<appender-ref ref="EXTENSIONLOG"/>
</logger>
conf/custom-logback.xml is included by Neo4j's internal logback configuration, see https://github.com/neo4j/neo4j/blob/master/community/kernel/src/main/resources/neo4j-logback.xml
I have a very weird problem with Struts 2.1.8 and SLF4J with Logback. I think I have setup everything as it should be (logback-core, logback-classic, slf4j-api and removed commons-logging from Struts JARs), but the logs look like this:
16:23:59,985 INFO [stdout] (ajp-localhost-127.0.0.1-8009-3) 2013-05-11 16:23:59,985 DEBUG [BasicTilesContainer.java:615] [ODk3Cc2-mn-X8eVfnemQn5WZ.undefined] - Render request recieved for definition 'DocumentList'
Clearly there are two timestamps, and one logging framework is logging through another somewhere, which causes this problem.
JBoss 7.1.1 is used.
Any ideas how to solve this problem?
EDITED:
This is how Logback configuration looks like:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %5p [%F:%L] [%X{sessionId}] - %m%n</pattern>
</encoder>
</appender>
I had a problem with modules in JBoss 7, but now although they are solved and Logback is really loaded, but the log files still are a mess. They look like if they are logged through JUL:
20:23:46,128 INFO [stdout] (connector_xxxx) 2013-05-11 20:23:46,127 DEBUG [ReConnector.java:83] [] - Next connection attempt in (ms) 20000
It looks like one logger is logging through the other.