Change logging level dynamically in spring boot app - java

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.

Related

Jboss logging to slf4j/log4j2 with Keycloak

I have a Keycloak EAR module, deployed on Keycloak 11.0. In my EAR module I want to use log4j2 logging library with slf4j. I successfully accomplished this by adding the following dependencies in the pom directly: log4j-slf4j-impl, log4j-api & log4j-core.
Wildfly logging dependencies are excluded by setting add-logging-api-dependencies to false. log4j2.xml is specified outside the packaged EAR and is referenced with log4j.configurationFile system property.
Now the problem. I also want Keycloak to use log4j2 but I cannot get this to work. Keycloak is using Jboss Logging wrapper which always picks up JbossLogManager no matter which logging provider I set - I always get either ClassNotFoundException or NoClassDefFoundError.
I realize there is a classpath problem but I am out of ideas at this point. I tried creating log4j-slf4j-impl, log4j-api & log4j-core Wildfly modules with the following command but I still get the same error.
./jboss-cli.sh --command="module add --name=org.apache.logging.log4j.log4j-api --resources=/Users/jernej/log4j-api-2.13.3.jar"
If I understand correctly, log4j2 should be in the classpath on Wildfly startup (when searching for LoggerProvider) and Jboss Logging findProvider method should return Log4j2LoggerProvider if modules are correctly added? How can I accomplished this?
Suppose I want to use log4j2 appender, located in separate library. If I add this library as a Wildfly module this log4j2 appender can then be used by other deployments as well - e.g. keycloak-server.war?
Adding a library as a module may not necessary makes it available to your application. Have you defined the dependency to that module in the jboss-deployment-structure.xml in the META-INF folder of your ear file? Something like this:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:jboss:deployment-structure:1.3 http://www.jboss.org/schema/jbossas/jboss-deployment-structure-1_3.xsd">
<deployment>
<dependencies>
<module name="org.apache.logging.log4j.log4j-api" export="true"/>
</dependencies>
</deployment>
</jboss-deployment-structure>

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.

How do I change log level in runtime without restarting Vert.x application

I know that we can change log level by putting it in vertx-default-jul-logging.properties file.
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.ConsoleHandler.level=FINER
java.util.logging.FileHandler.limit=10000000
java.util.logging.FileHandler.count=10
java.util.logging.FileHandler.level=FINER
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
But I need to restart the application when we change log level in this file as it gets built with application. Is there any way to change the log level without restarting the application like we can do in jboss by jboss cli.
This file doesn't have to be built with the application. It just has to be on the classpath.
But anyway, I don't believe JDK logging supports hot reload of a configuration file. There are other logging tools which do though. Like Logback-classic.
Logback-classic can scan for changes in its configuration file and automatically reconfigure itself when the configuration file changes.
For example, to reload every five seconds:
<configuration scan="true" scanPeriod="5 seconds" >
...
</configuration>
Vert.x can be configured to use different logging frameworks. To do so, you must set the vertx.logger-delegate-factory-class-name system property. As Logback-classic is an slf4j implementation, you need:
-Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.SLF4JLogDelegateFactory

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>

Log4J2 - How to disable logging in unit test?

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.

Categories