log4j not logging the details coming from some java classes - java

I am trying to log data from my project into files based on the input parameter. My project has 5 classes of which 3 contain log messages.
I used the following code to configure log4j.
public static void configureLog4j(String log4j,String logs,String timeStamp) throws IOException {
PropertyConfigurator.configure(log4j);
FileAppender fileapp = (FileAppender) Logger.getRootLogger().getAppender("FILE");
if(fileapp != null)
logger.removeAppender(fileapp);
String filename = logs + "/test_" + info + "_" + timeStamp;
fileapp.setFile(filename);
fileapp.setLayout(new PatternLayout("%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"));
fileapp.setWriter(new FileWriter(new File(fileapp.getFile())));
Logger.getRootLogger().addAppender(fileapp);
}
info represent name of the user. Now once I configure this in the beginning of the applications only two classes are writing logs in the file the third file which contains code to send & receive data does not write the logs to the log file. Is there any thing I am missing here.
Please help me with this issue.

Chances are that the third class is already logging before you have a chance to configure your logger. This is one reason why I switched to logback: It has a much more powerful (and better documented) config file format.
The code above also contains a problem:
if(fileapp != null)
logger.removeAppender(fileapp);
logger isn't defined anywhere and fileapp must be non-null or you'd get NPEs later.

Please be insure that your third class should not logging before configuration.

Related

FileHandler generate extra logs files when original log is locked

I need generate one log file by each application installed and running on websphere application server 9.
I use JUL for generate log's file. My solution was create a especific Class thas inherits from FileHandler and set logs properties by a config file.
This is my code:
//Read config file
LogManager.getLogManager().readConfiguration(LoggerJUL.class.getResourceAsStream("/Logger.properties"));
//Add handler to logger
Logger.getLogger(clazz)).addHandler(new PersonalFileHandler());
PersonalFileHandler extends FileHandler, and properties are set by configure method on FileHandler class on runtime.
In this way i achieve make one log file by application running over Websphere, without overwriting the destination of the server log.
Although I achieve part of the objective, extra files are generated if the original log file is locked, same like this: testLogs.log.0, testLogs.log.1, testLogs.log.0.1, etc.
I read many suggestions and solutions, but i can't stop this isue.
Any suggestions ?
handlers = com.mucam.xxxx.PersonalFileHandler
# Set the default formatter to be the simple formatter
com.mucam.xxxx.PersonalFileHandler.formatter = java.util.logging.SimpleFormatter
# Write the log files to some file pattern
com.mucam.xxxx.PersonalFileHandler.pattern = C:/Users/pmendez/Documents/Log/testLogs.log
# Limit log file size to 5 Kb
com.mucam.xxxx.PersonalFileHandler.limit = 5000
# Keep 10 log files
com.mucam.xxxx.PersonalFileHandler.count = 10
#Customize the SimpleFormatter output format
java.util.logging.SimpleFormatter.format = %d{ISO8601} [%t] %-5p %c %x - %m%n
#Append to existing file
com.mucam.xxxx.PersonalFileHandler.append = true
Although I achieve part of the objective, extra files are generated if the original log file is locked, same like this: testLogs.log.0, testLogs.log.1, testLogs.log.0.1, etc. I read many suggestions and solutions, but i can't stop this isue. Any suggestions ?
Since your count is set to 10 you need to specify the %g pattern to log the generation.
com.mucam.xxxx.PersonalFileHandler.pattern = C:/Users/pmendez/Documents/Log/testLogs%g.log
The pattern is absolute path so if you create multiple filehandlers it will resolve conflicts by appending unique number to the end. This is specified by the %u pattern. So if you want to move where the integer is placed in the file name you specify the %u token in the pattern.
This also means that you are creating multiple instances of your custom file handler and they are not being closed. If you want to control the number of files you either need to control the number of PersonalFileHandler you create and or share a reference to singleton PersonalFileHandler. Otherwise you need to make sure that if you explicitly create a PersonalFileHandler that you are explicit closing that PersonalFileHandler before you create a second new PersonalFileHandler.
Loggers are subject to garbage collection. The line:
Logger.getLogger(clazz).addHandler(new PersonalFileHandler());
Is subject to garbage collection unless the code elsewhere as already pinned that logger in memory. This can cause log files to be created, locked, and empty.

How to read from multithreading log4j2 buffer

I have executed automated test cases with multithreads, managed by maven-surefire-plugin. Each class has their own thread where it is executing and the log4j2 is configured with bufferIO = true and immediateFlush= true. In the output file, all the threads are mixing the information. I know that log4j2 has this buffer and I would like to know if each thread has their own buffer and if I can read from it before the information is written into the output file.
I read other question related to this topic, but it hasn't arrived at a solution. And for that reason, I'm trying to search another path to follow.
The first thing I found is that JUnit5 is the cause of the mixed output log file, when we execute the test cases in multithreading way. When I used JUnit4 the default output, usually the console waits for the end of the test case to write.
In other hand the output file from log4j, when the user execute it with multithreding, always it shows mixing all the threads, regardless of the JUnit version.
Them, I add the thread id to the log4j layout pattern:
%d{yyyy-MM-dd HH:mm:ss} %-5p- **[%tid]** %m%n
And after finish each thread I read the last lines of the output log4j file and I filter by the thread id number to obtain the relevant lines. With this point I had to solve other problem. How to obtain the absolute path of a dynamic log4j output log file? I test two solutions:
By reflection (not recommended, but faster)
Implement your own FileAppender to create a method to access to the fileName field
The two steps to follow the first option are this:
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Appender appender = ctx.getConfiguration().getAppenders().get("file");
The appendervariable has the fileName field, but it is private.

Log4j properties | Create new log file with timestamp for every run [duplicate]

This question already has answers here:
One logfile per run with log4j
(4 answers)
Closed 5 years ago.
I'm quite new to log4j and have managed to create the logs for my code.
But what I need is, a new file to be created for each run, rather than appending the logs to the same file.
Below are the properties I'm setting (found somewhere on google).
Please suggest changes, so that new file will be created with the timestamp after each run.
// Here we have defined root logger
log4j.rootLogger=INFO,R,HTML
// Here we define the appender
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.HTML=org.apache.log4j.FileAppender
// Here we define log file location
log4j.appender.R.File=./Logs/LastRunLog.log
log4j.appender.HTML.File=./Logs/LastRunLog.html
// Here we define the layout and pattern
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d - %c -%p - %m%n
log4j.appender.HTML.layout=org.apache.log4j.HTMLLayout
log4j.appender.HTML.layout.Title=Application log
log4j.appender.HTML.layout.LocationInfo=true
You can use a system property to set the log4j file names with it's value and give that property an unique value for each run.
Something like this on your starter class (timeInMillis and a random to avoid name clashes):
static {
long millis = System.currentTimeMillis();
System.setProperty("log4jFileName", millis+"-"+Math.round(Math.random()*1000));
}
And then you refer to the system property on log4j conf properties:
log4j.appender.R.File=./Logs/${log4jFileName}.log
log4j.appender.HTML.File=./Logs/${log4jFileName}.log
Hope it helps!
You need to write (or find) a custom appender which will create the file with a timestamp in the name.
The 3 defaults implementation for file logging in log4j are :
FileAppender : One file logging, without size limit.
RollingFileAppender : Multiple files and rolling file when current file hits the size limit
DailyRollingFileAppender : A file per day
The simpliest way is to extend FileAppender and overwrite the setFile and getFile methods.
i think this answer would be helpful for you click here
i have ran code as the page said, and i got a new log file each time i start my application.
result like that :
and all code in my Test.java is :`
private static final Logger log = Logger.getLogger(Test.class);
public static void main(String[] args) {
log.info("Hello World");
}
`

Retrieving slf4j log file in java

I'm making a project backup java application, that needs to create a mail report and send it every day. My idea was to generate the body message, and to attach to the email the application log.
I'm using slf4j logger, and I don't know ho to automatically retrieve the log file path using the logger.
Using plain log4j seems to be easy, but I can't get out trying to retrieve it from the slf4j logger. Anyone faced this problem?
At the end this is what I did, and it seems to work fine.
Any review or comment will be appreciated!
private File getLogFile(){
File file = null;
Appender rightAppender = null;
Enumeration<Appender> e = org.apache.log4j.Logger.getRootLogger().getAllAppenders();
while(e.hasMoreElements()){
Appender appender = (Appender)e.nextElement();
if(appender instanceof FileAppender){
rightAppender = appender;
}
}
if(null != rightAppender){
file = new File(((FileAppender)rightAppender).getFile());
}
return file;
}
There is no such thing as an SLF4J logger. SLF4J is a facade for another logging framework (log4j, commons-logging, java.util.Log, etc.). So an SLF4J logger is always just a wrapper around a logger in one of the supported frameworks. Look at how you configured the logger underneath.
So in your case, if you are using slf4j with log4j, consult your log4j.properties or log4j.xml as usual to find where your logs are. And if you haven't set up either of those files (or otherwise initialized log4j), you don't have logs.

How to invoke a new notepad with Java and save it in a directory in windows?

I am currently logging test execution results in to a textfile(An existing one.) How do I create a textfile with a timestamp and save it in a windows directory? The code I am using currently is
File outputResultFile = new File(CompleteFileNameForNotepad);
PrintWriter outputFile = new PrintWriter(new FileWriter(outputResultFile));
String str = "text to write in to the file";
outputFile.println(str);
outputFile.close();
Thanks for your help.
String fileName = new SimpleDateFormat("yyyy-MM-ddTHH-mm-ss").format(new Date()) + ".txt";
File outputResultFile = new File(fileName);
...
Note: what you call a notepad is more commonly called a "file".
You should consider using a logging framework instead. Check out Log4j for example. You can then alter the logging format and which classes are logged by tweaking the logging configuration. This means you don't have to alter your code.
The log4j.properties below would log all classes under the package foo, at WARN level or higher to the Console, using the pattern "2000-09-07 14:07:41,508 [main] INFO MyApp - Entering application."
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
# Print the date in ISO 8601 format
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
# Print only messages of level WARN or above in the package com.foo.
log4j.logger.com.foo=WARN
To log to a file use a different Appender, such as org.apache.log4j.FileAppender or org.apache.log4j.RollingFileAppender. For your purpose org.apache.log4j.DailyRollingFileAppender would be suitable.

Categories