Log into different files with the same logger with Log4j - java

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.

Related

I can't create a indepente org.apache.log4j.Logger

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.

Logback multiple loggers with different configuration

I want to use 2 different loggers in a class where one logger uses one logback configuration file and another uses another configuration file. eg:
class Sample {
// LOGGER 1 follows configuration from logback1.xml
private static final LOGGER1 = LoggerFactory.getLogger(Sample.class);
// LOGGER 2 follows configuration from logback2.xml
private static final LOGGER2 = LoggerFactory.getLogger(Sample.class);
public myFunc(){
LOGGER1.info("In myFunc"); // writes to file as configured in logback1.xml
LOGGER2.info("Entered myFunc"); // writes to graylog server as configured in logback2.xml
}
}
The reason I want to do this is that I'm injecting a second logger into code at runtime, and I don't want the injected logger to collide with the logger used in the main project. How should I go about doing this?
I went through this post: How to use multiple configurations with logback in a single project? But it seems to address the problem of choosing one configuration file from many but not "being able to use 2 configuration files simultaneously as in the above example."
This is one way to get two loggers from different configs:
LoggerContext c1 = new LoggerContext();
LoggerContext c2 = new LoggerContext();
new ContextInitializer(c1).configureByResource(new URL("file:logback1.xml"));
new ContextInitializer(c2).configureByResource(new URL("file:logback2.xml"));
Logger l1 = c1.getLogger("x");
Logger l2 = c2.getLogger("x");

How to correctly instantiate a log4j Logger object into my class?

I am working on a simple Java command line and I need to insert log4j into my application, so I am following this tutorial:
http://veerasundar.com/blog/2009/07/log4j-tutorial-adding-log4j-logging-to-your-project/
So I have done the following step:
I put the log4j jar file into the library of my project.
I put the log4j.properties into a config package and I configured it with this minimal configuration:
#define the console appender
log4j.appender.consoleAppender = org.apache.log4j.ConsoleAppender
# now define the layout for the appender
log4j.appender.consoleAppender.layout = org.apache.log4j.PatternLayout
log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
# now map our console appender as a root logger, means all log messages will go to this appender
log4j.rootLogger = DEBUG, consoleAppender
So this configuration say that the output have to be printed into the console and I associate the DEBUG mode.
Now the tutorial say that:
In any of your Java file, add the below lines, in order to start
logging.
And show this example code:
private static Logger logger = Logger.getLogger(MyclassName.class);
logger.debug("this is a sample log message.");
Ok, I have not understand what exatly I have to do to instantiate the Logger into my class.
My class is named Mailer so have I to do something like:
private static Logger logger = Logger.getLogger(Mailer.class);
Or what? What exactly have I to do?
EDIT 1: My class is something like:
public class Mailer {
private static final org.apache.log4j.Logger logger = new Logger(Mailer.class);
...................................
...................................
...................................
}
The problem is that IntelliJ show me an error on the Logger(Mailer.class); and say to me: Logger(java.Lang.String) has protected access in 'org.apache.log4j.Logger'
Why? How can I solve this issue?
Tnx
and then in your code you write for example:
logger.debug("Your message);
....
logger.error("Somehting crahsed",e);...
You have to use LogManager
Checkout this link-
https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger()
So for your code the change would be something like this-
private static final org.apache.log4j.Logger logger = LogManager.getLogger(Mailer.class);
logger.debug("Its debugging");

Creating multiple log instances using log4j to output log files in separate locations

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

SLF4J - Logback: How to configure loggers in runtime?

we are using LogBack with our project, I want to configure logger according to some Data Base values, i.e If some DB value is set to true, then logger should use both file and DB appenders, if it's false so logger must use only DB appender,
I also want to preserve using static final loggers, so I won't create a new instance each time logger is called,
so how could I do something like this?
Regards,
You should configure Logback programmatically as described in this example.
public class Main {
public static void main(String[] args) {
Logger logger = (Logger) LoggerFactory.getLogger("abc.xyz");
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
FileAppender<LoggingEvent> fileAppender =
(FileAppender<LoggingEvent>) logger.getAppender("file");
if(fileAppender != null) {
fileAppender.stop();
fileAppender.setFile("new.log");
PatternLayout pl = new PatternLayout();
pl.setPattern("%d %5p %t [%c:%L] %m%n)");
pl.setContext(lc);
pl.start();
fileAppender.setLayout(pl);
fileAppender.setContext(lc);
fileAppender.start();
}
... etc
}
}
Is there a specific reason behind reading the configuration property from the database? One suggestion would be to use JNDI. Logback can read JNDI configured values using the tag.

Categories