Log4J2 - How to disable logging in unit test? - java

I am using Log4J v2.0 Beta3 in my application for logging and I am getting log messages generated when I run my unit tests. I checked the API for some way to set the log level to something like CRITICAL but I could not find any way to change the logger configuration.
In fact, I read this on the log4j2 website:
Note that unlike Log4j 1.x, the public Log4j 2 API does not expose
methods to add, modify or remove appenders and filters or manipulate
the configuration in any way.
So with that said. What is the correct way to disable logging from within unit tests?

I found my answer on the log4j2 website under 'Testing in Maven'. The recommended way seems to be to place a log4j2-test.xml file in src/test/resources. Placing the xml file into this directory will cause it to be used instead of a log4j2.xml.

You can disable logging with setting root level to off (<Root level="off"/>).
So place log4j2.xml file into src/test/resources with following content:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn">
<Loggers>
<Root level="off"/>
</Loggers>
</Configuration>
EDIT:
Removed <!DOCTYPE xml> (based on suggestion from sprynter) to make xml valid.

Both the answers from #Jbug and #Dove work as long as you are placing the file in src/test/resources of the current module. If your app depends on a library to include log4j2.xml it won't work for test runs since library jar won't included test classes and resources.

Related

Logback Spring - Change log levels during runtime using an external yaml file outside of the jar

Inside of my logback-spring.xml file, I am able to change the log levels, and it's able to autodetect changes when I include auto scan. Looks like this:
<configuration debug="true" scan="true" scanPeriod="10 seconds">
However, I want to keep all of my log levels in an external yaml configuration file and I don't want to have to restart the server to detect those changes. Is there a way to use an external yaml file to define log levels and use logback autoscan? Or should I be looking at a completely different way of going about it?
You can do that in application.yml, try adding the following settings
spring:
logging:
level:
org.springframework.web: DEBUG
com.company.package: DEBUG
You can also specify pattern if you like.

Externalize logback-spring.xml programmatically

My application.properties are loaded programmatically
using PropertyPlaceholderConfigurer. So setting logging.config in application.properties (eg: logging.config=file:/home/dev-01/conf/logback.xml)
in the application.properties won't work since logging occurs early in the lifecycle and therefore cannot read values from application.properties.
I need to externalize the logback.xml as there are property values that needs to be configured depending on the environment. If I can externalize it, it can be manage by support/operations without developer intervention. Also, it is easy to maintain without redirection from application.properties. Meaning I can set property values in the logback.xml file itself.
I saw solution of adding the VM options during startup. I have not tried it but I am just wondering if I can load the logback.xml programmatically (similar to my application.properties).
i use a configuration like this to achieve that:
<configuration scan="true" scanPeriod="10 seconds" debug="false">
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
<include file="${CONFDIR}/config/logback-config.xml" />
</configuration>
and then you place another logback config in that location and changes to that file will be refreshed every 10 seconds
Loading logback.xml programmatically does not seem to be a viable solution. My scenario is application.properties is loaded programmatically (from an external path) so setting logging.config property in application.properties file will not work. Note, it works using the default application.properties in classpath. I think the most pragmatic approach is passing -Dlogging.config=/[some-path]/logback.xml. This option works for me and updating logging levels (for debugging purpose) without redeploying the jar file.
Setting the logback.xml configuration scan to true will refresh the settings if logback.xml is updated.
<configuration debug="true" scan="true">
...
</configuration>

Change logging level dynamically in spring boot app

I have a spring boot app where I provide logging configuration using
-Dlog4j.configuration=file:E:\workspace\log4j.properties
I am using slf4j for logging. Is there any way in which I can just change "log4j.rootLogger" property and log level can be changed dynamically. If not then what should be the best approach to do that in which I can have minimal change in code. Thanks in advance
You can configure monitorInterval in your log4j configuration:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
...
</Configuration>
https://logging.apache.org/log4j/2.x/manual/configuration.html
Log4j will automatically detect changes to the configuration file and reconfigure itself.

What is the preferred method for creating a custom appender in log4j2?

The log4j2 documentation shows the preferred method to produce custom components (such as appenders, filters and lookups). However, it is unclear on how to ensure that these custom components are picked up by the logging framework and useable by a logging configuration.
After placing a custom appender with the correct annotations in the classpath, what else do I need to do to be able to start including it in my log4j2.xml file and have it picked up by the logging framework?
To provide an example of this, if I annotate a custon appender with:
#Plugin(name = "Stub", category = "Core", elementType = "appender", printObject = true)
how do I get it to be picked up and used like this in the log4j2.xml configuration:
...
<Appenders>
<Stub name="stub">
...
</Stub>
...
</Appenders>
...
You need to put the package name (or names in a comma-separated list if multiple) in the packages attribute of the Configuration element of your log4j2.xml.
E.g.
<Configuration status="trace" packages="com.mycomp.myproject.appenders">
...
See the Log4j2 Configuration Documentation for more information.
I can't post a comment yet, so I'm writing this as an answer.
packages attribute in configuration element is no longer supported (since version 2.0-rc2), see this answer: https://stackoverflow.com/a/24931395/3145863.
It should be included in the 2.0.1 release of log4j (https://issues.apache.org/jira/browse/LOG4J2-741)
For now, I recommend you to use Maven to build your project.

Weblogic Log4j Loggging Server Logging Bridge throws ClassCastException when starting up

With Weblogic 11g I have done the following:
1 Created log4j.xml file where I created a new appender:
<appender name="WEBLOGIC" class="weblogic.logging.log4j.ServerLoggingAppender">
<param name="Threshold" value="ERROR"/>
</appender>
<root>
<priority value="WARN"/>
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="WEBLOGIC"/>
</root>
2 Updated the ${DOMAIN_HOME}/bin/setDomainEnv.sh script with these changes:
LOG4J_CONFIG_FILE="${DOMAIN_HOME}/config/log4j.xml"
if [ "${LOG4J_CONFIG_FILE}" != "" ] ; then
JAVA_PROPERTIES="${JAVA_PROPERTIES} Dlog4j.configuration=file:${LOG4J_CONFIG_FILE}"
export JAVA_PROPERTIES
fi
JAVA_OPTIONS="${JAVA_OPTIONS} ${JAVA_PROPERTIES} -Dweblogic.log.Log4jLoggingEnabled=true -Dwlw.iterativeDev=${iterativeDevFlag} -Dwlw.testConsole=${testConsoleFlag} -Dwlw.logErrorsToConsole=${logErrorsToConsoleFlag}"
3 Copied the log4j jars to the domain/lib
cp ./wlserver_10.3/server/lib/wllog4j.jar user_projects/domains/my_domain/lib/
cp ./wlserver_10.3/server/lib/consoleapp/APP-INF/lib/log4j-1.2.8.jar user_projects/domains/my_domain/lib/
4 Starts the AdminServer, but I get this error:
java.lang.ClassCastException:
weblogic.logging.log4j.ServerLoggingAppender cannot be cast to
org.apache.log4j.Appender
Keep step 1 and remove changes done in other steps.
Now copy the log4j.xml to $DOMAIN_HOME/lib folder. This will keep your log4j.xml in the server's classpath and the server will use this log4j.xml as its log4j configuration. No additional changes are required.
In setDomainEnv.xml file, please add the set log4j.xml location as below:
set LOG4J_CONFIG_FILE=C:\bea\user_projects\domains\dev\lib\log4j.xml
if NOT "%LOG4J_CONFIG_FILE%"=="" (
set JAVA_PROPERTIES=%JAVA_PROPERTIES% -Dlog4j.configuration=file:%LOG4J_CONFIG_FILE%
)
What you have to see is if despite the warning that you get, if the ServerLogging is effectively not working on your appliction on your domain.
Probably not even there since you are only copying the log4j to the domain/lib folder but not the wllog4j.jar.
So your setup looks like is doomed not to work in any case.
To me, It looks to me that you are undergoing Class Loader Vodoo Messup.
(1) You set a global log4j properties file for the entire app server.
(2) it looks like weblogic console app is itself a ear and it bundles its own LOG4J implementation library, which you are copying into your domain.
When the console app runs, it must for sure make use of Log4j and the class loader loading the Log4j Appender definition is most likely a level lower than the class loader that knows about the ServerLoggin bridge adapter.
I am beting its for reason like this that weblogic is geting rid of LOG4j in future gnerations of the product.
They have too many class loader issues - JUL logging you have the APP class loader behind the core classes - such as Handlers/Adapters.
Anyway.
(3) When weblogic runs, namley when it bootstraps the console it probably runs some sort class loader that gives a level of isolation to the libs bundled in the applicaiton and it sees:
Oh! How nice, LOG4j is here, leets initialize it.
Second, LOG4j bootstraps and hits head on your log4j.properties where you put the server logging appender in there - cross cutingly for everybody (including the weblogic application console).
He goes hunting for this library and where does it find it?
One of them, the wllog4j.jar he finds somewhere in the weblogic generic container libraries. While the base core classes of Log4j he finds a level lower in the domain configuration or in the EAR configuraiton of the console applicaiton.
This is not good.
Try the following:
(a) go into the weblogic console app, go to the Meta Inf folder and re-write the weblogi-application.xml
It will have a prefer applicaiton packages that looks like this:
org.apache.log4j.*</package-name--> <---- here I've commented this line.
If you comment the above line, the application class loader will search for log4j libraries in the highest parent that knows about these classes.
So if you put at the same level where your ServerLogger is found you should be fine.
(b) Pug the log4j implementation library at the same level where the wllog4j.jar will be found.
Check if you still get the casting exceptions.
Be very careful when you make server wide cross cuting configurations.
Good luck.

Categories