I have a web Application Java class running into a Wildfly named Sincronizador. I did create a specific org.apache.log4j.Logger in Sincronizador.java but the logger.log(...) also put info in the Wildfly server.log. I would like to log info only in this logger
Logger logger = Logger.getLogger(SASComm.class);
logger.removeAllAppenders();
RollingFileAppender rollingFileAppender = new RollingFileAppender();
rollingFileAppender.setLayout(new PatternLayout("[%d{dd-MM-yyyy HH:mm:ss SSS}][%p] %m%n"));
rollingFileAppender.setMaxBackupIndex(7);
rollingFileAppender.setMaxFileSize("50MB");
rollingFileAppender.setName("Sinc");
rollingFileAppender.setFile(getLogFile());
rollingFileAppender.activateOptions();
logger.addAppender(rollingFileAppender);
You just need to set the additivity flag to false on your logger so that it doesn't inherit from a parent logger:
logger.setAdditivity(false);
This line logger.removeAllAppenders(); will remove all the assigned appenders from this logger but the inheritance is still there (at least from the rootLogger) which you need to remove as well.
Related
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.
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.
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.
Hello StackOverflow community,
I am writing a multi-threaded application in which I need a log file output for each thread using log4j. Ideally, I would like to have a separate log instance running for each thread. I am debating as to how I should tackle this. Because the location of the file output is different for each log instance, I need to update the log4j.appender.BrokerFile.File= property for each instance. As of right now I am trying to create a new Logger, set the new properties into a properties object, and load the new properties into my newly created Logger object using PropertyConfigurator.configure(log4jProperties); While the new Logger instance is being created just fine, the new properties do not seem to be recognized by the new instance. Do I need to create a new FileAppender for each new Logger instance?
public class Broker implements Runnable{
private Settings ss; //The Settings object associated with this broker.
private String loggerName = null;
private Logger log = null;
private Properties log4jProperties = new Properties();
}
//Constructor
public Broker(Settings ss){
this.ss = ss;
}
public void run() {
loggerName = ss.getBrokerName() + "_Logger";
log = Logger.getLogger(loggerName);
log4jProperties.setProperty("log4j.loggerName", "DEBUG, FILE");
log4jProperties.setProperty("log4j.appender.FILE","org.apache.log4j.FileAppender");
log4jProperties.setProperty("log4j.appender.FILE.File", "C:/Logz/"+loggerName+".out");
log4jProperties.setProperty("log4j.appender.FILE.ImmediateFlush", "true");
log4jProperties.setProperty("log4j.appender.FILE.Threshold", "DEBUG");
log4jProperties.setProperty("log4j.appender.FILE.Append", "FALSE");
log4jProperties.setProperty("log4j.appender.FILE.layout", "org.apache.log4j.PatternLayout");
log4jProperties.setProperty("log4j.appender.FILE.layout.conversionPattern", "%m%n");
PropertyConfigurator.configure(log4jProperties);
log.debug("This is a debug message");
// This will be set to true as long as the Broker is running
while(isRunnable){
//Listen for and process files
}
}
Here is the console output. As you can see the new logger instances are being created but the new properties are not being recognized.
log4j:WARN No appenders could be found for logger (Broker1_Logger).
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:WARN No appenders could be found for logger (Broker2_Logger).
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:WARN No appenders could be found for logger (Broker3_Logger).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
This goes on for every broker. Is there any way to directly apply my configuration settings to the Logger object? For example, something like
log.PropertyConfigurator.configure(log4jproperties);
There must be a way to apply the configuration settings to each logger object created.
Thank You,
Jim
It seems that creating a new appender for each new instance is necessary, since each instance needs to print to a different file output location. I solved this problem by creating a generateLogger() method with the necessary parameters to create new loggers and appenders programmitcally. If you will notice the first parameter contains the name of a parent logger. If I include this in my new logger name, it will inherit the properties of its parent, which is configured in my master.properties file, and vice versa. For example, if my parent logger is "Broker" and my logger name is "Broker1", then the full loggerName will be "Broker.Broker1". This way I can track all the brokers in one log file while also having separate log files for each broker in their own separate file output locations. Not to mention, this method can be re-used with many different kinds of Logs using different parent loggers. Though the parent Logger is not even necessary if you choose. If you choose to not have a parent Logger, simply delete it from the method and disregard my master.properties file.
public Logger generateLogger(String parent, String name, String logDirectory, String filePattern, String fileThreshold) {
// TODO Auto-generated method stub
//Create Logger
String loggerName = parent + "." + name;
Logger log = Logger.getLogger(loggerName);
//Create Logging File Appender
RollingFileAppender fileApp = new RollingFileAppender();
fileApp.setName("Broker." + loggerName + "_FileAppender");
fileApp.setFile(logDirectory +"/"+ name+".log");
fileApp.setLayout(new PatternLayout(filePattern));
fileApp.setThreshold(Level.toLevel(fileThreshold));
fileApp.setAppend(true);
fileApp.activateOptions();
log.addAppender(fileApp);
return log;
}
Here is the Broker logger configuration inside my master.properties file for reference.
log4j.logger.Broker=DEBUG, BrokerFile
# Broker Appenders
# Broker File Appender
log4j.appender.BrokerFile=org.apache.log4j.RollingFileAppender
log4j.appender.BrokerFile.File=C:/Documents and Settings/gr2cher/My Documents/KTLO/Java/CMInbound/BrokerLogs/Logs/Broker.log
log4j.appender.BrokerFile.MaxFileSize=1MB
log4j.appender.BrokerFile.MaxBackupIndex=1
log4j.appender.BrokerFile.layout=org.apache.log4j.PatternLayout
log4j.appender.BrokerFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
log4j.appender.BrokerFile.threshold=DEBUG
I have a Class "Example.class". I get my Logger with:
private final Logger log = Logger.getLogger(Example.class);
My log4j.properties looks like:
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=log.txt
log4j.appender.file.MaxFileSize=1024KB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%p %t %c - %m%n
My Class is logging via log.info(..), log.debug(..) and so on into the file log.txt.
Now i want to have a different logger for the same class e.g.:
private final Logger differentLogger = Logger.getLogger(Example.class);
and this logger should log into a different file for example
differentLogger.info("Hello World");
//writes 'Hello World' into differentLogFile.txt
Is this possible somehow?
No, the category identifies the logger.
That said, you are not forced to use the class as the category. You could use in the same class:
private final Logger log = Logger.getLogger(Example.class);
private final Logger differentLogger = Logger.getLogger(mylogs.different);
After that, in the configuration file you can define several appenders and assign each category to a different appender.
Calling Logger.getLogger(Example.class) twice will return the same or undistinguishable instances of Logger. This means Log4J cannot make any distinction between them and they will always land up in the same file.
The solution is obvious: use a different logger!
Logger differentLogger = Logger.getLogger("differentLogger");
And configure log4j.xml to use different appender for differentLogger.