I want to be able to programmatically set the logging level for all loggers.
This works:
Logger log = Logger.getLogger(Example.class);
LogManager.getLogger(Example.class).setLevel(Level.FATAL);
log.debug("Should not see!");
LogManager.getLogger(Example.class).setLevel(Level.DEBUG);
log.debug("Should see!");
However this does not:
Logger log = Logger.getLogger(Example.class);
LogManager.getRootLogger().setLevel(Level.FATAL);
log.debug("Should not see!");
LogManager.getRootLogger().setLevel(Level.DEBUG);
log.debug("Should see!");
Get the logger names from LogManager.getCurrentLoggers() and then set the LogManager.getLogger("<name from loop>").setLevel(Level.FATAL); using loop.
When you are getting LogManager.getRootLogger() gets the root level logger. It is not going to affect all the individual configuration.
Related
I'am still working on a problem with the Http Builder in Java. The Builder is using a Log which is private. This Log is generated with the Logger Factory.
On debugging I notice that the logger level is null and so the logs are not printed. On debugging I can change the logger level and the logs are printed.
The Problem is that i can not set the Logger Level from outside of the HTTP Builder.
So is it possible to set the Level of all Log property which are generated by the Log Factory ?
I managed to find a solution
Just import
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
And Set
Logger rootLogger = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)
rootLogger.setLevel(mLevel)
In Log4j 1.2, you could simply take a logger and add an appender at runtime. This was handy for test purposes for instance. We used to create a mock appender and add it to the logger. Subsequently we could make different assertions.
What is the equivalent thing with log4j2?
This example for instance shows how other people were adding test appenders.
The log4j2 page shows a few examples on how to add appenders. However, they add appenders to the overall context. Which seems different from adding appenders for one specific logger.
Another observation is that if you use org.apache.logging.log4j.core.Logger as opposed to org.apache.logging.log4j.Logger, you can still add appenders. However most people use org.apache.logging.log4j.Logger. And in fact, LogManager returns an instance of org.apache.logging.log4j.Logger. So, I am not sure how to connect these two classes and whether they should be connected at all.
Another observation is that if I call
LogManager.getContext().getConfiguration().getLoggers()
I can get a ist of all LoggerConfig objects in the context. I subsequently add appenders to any LoggerConfig object. The question however is, how do I get the LoggerConfig related to an instance of org.apache.logging.log4j.Logger?
This is confusing me.
org.apache.logging.log4j.Logger is an interface located in the log4j-api module. org.apache.logging.log4j.core.Logger is a concrete class (implementing the above interface) which lives in the log4j-core module.
LogManager (also in the log4j-api module) returns something that implements the org.apache.logging.log4j.Logger interface, and if the log4j-core module is in the classpath this will be an instance of org.apache.logging.log4j.core.Logger.
So you can cast the returned Logger to org.apache.logging.log4j.core.Logger and add the Appender.
Each core Logger has a LoggerConfig (1-to-1 relationship). You can find the LoggerConfig that corresponds to the desired Logger because they have the same name.
Is some path to write log messages only to the 'child' logger, avoiding root logger?
The root logger is using by other components, so there is no ability to decrease it's level or disable appender.
thanks
Please use Log4j additivity.
Set the additivity property of a Log4j logger to false and then the log messages which are coming to that logger will not be propagated to parent loggers.
Log4j configuration file:
log4j.category.com.demo.moduleone = INFO, moduleOneFileAppender
log4j.additivity.com.demo.moduleone = false
log4j.category.com.demo.moduletwo = INFO, moduleTwoFileAppender
log4j.additivity.com.demo.moduletwo = false
log4j.rootLogger = INFO, rootFileAppender
With the above configuration, the log messages from the com.demo.moduleone will go to the moduleOneAppender only and the rest of the log messages will go to the rootFileAppender.
Im using Log4j and i have the following problem: is there a way to add one more logger from your code ? (not root logger).
In my config file, i set up the following two loggers :
log4j.rootCategory=INFO, ALogFile
log4j.logger.BLog=INFO,BLog
I would like to remove second line from config file and add BLog from code. Is that possible?
The equivalent code should be:
Logger logger = Logger.getLogger("BLog");
logger.setLevel(Level.INFO);
logger.addAppender(Logger.getRootLogger().getAppender("BLog")); // see notes below
I.e. you obtain a Logger object for the name BLog, you then set the level to INFO and attach the appender you've presumable defined elsewhere in your config file, called BLog.
Note: based on the answers from this related question, you may need to attach the appender to a logger in order to be able to reference it, as my code does above. Or just define the appender in your code.
What is the significance of log4j.rootLogger property in log4j.properties file? What happens if I don't use this property?
Example:
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
What happens if I set this property to ERROR mode.
Samudra Gupta explains in his book1:
The Logger object is the main object that an application developer uses to log any message. The Logger objects acting within a particular instance of an application follow a parent-child hierarchy.
If you have the following configuration:
log4j.rootLogger=WARN, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
log4j.logger.com.me.proj2=INFO
This is how the logger hierarchy could end up looking:2
Samudra Gupta continues to explain:
At the top of the hierarchy exists a root logger. The root logger exists outside the scope of any custom logger hierarchy that we may come up with. It always exists as the root logger for all possible logger hierarchies, and it has no namespace. All the other application-specific Logger objects are child objects to the root logger. The parent-child relationship of loggers signifies the dependency of the loggers acting within the same application. A child logger can inherit properties from its parent logger recursively up the tree. Typically, a child logger will inherit the following properties from its parent logger(s):
Level: If the child logger has no explicit tree level specified, it will use the level of its closest parent or the first proper level it finds recursively up the hierarchy.
Appender: If there is no appender attached to a logger, the child logger uses the appender of its closest parent logger or the first appender it finds recursively up the tree.
ResourceBundle: ResourceBundles are key-value pattern properties files used for the localization of logging messages. A child logger inherits any ResourceBundle associated with its parent logger.
NOTES
1 Samudra Gupta, Pro Apache Log4j, Second Edition (Berkeley, CA: Apress, 2005), 24-25, ISBN13: 978-1-59059-499-5
2 Dominic Mitchell, Logging in Java, http://happygiraffe.net/blog/2008/09/03/logging-in-java/, Retrieved 26 May 2014.
To answer
What happens if I don't use this property?
If you don't set the rootLogger to a level and an appender, you will get a warning.
For example, if you omit or comment out the line log4j.rootLogger=DEBUG, stdout, i.e. say your log4j.properties file contains only the rootlogger and no additional loggers, here the root logger being commented out:
#log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
You will get something like the following output:
log4j:WARN No appenders could be found for logger (log4jtests.Log4jHelloWorld).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
log4j.rootLogger property sets the Level (DEBUG here) and Appender (A1 here) for root Logger. This is not mandatory. Root logger does not have a default appender attached and it can exist without an appender. So, your log4j properties file can be without this property being set.
Root logger is the highest logger in the log4j hierarchy similar to Object class in Java.