Get error as
"java.io.IOException: Couldn't get lock for ..\log\abc.log",
not sure why this happen.
Can somebody help me out? Thank you
logger = LogManager.getLogManager().getLogger(className);
FileHandler logFile = new FileHandler(file);
// create txt Formatter
SimpleFormatter formatterTxt = new SimpleFormatter();
logFile.setFormatter(formatterTxt);
logger.addHandler(logFile);
#Catheryan
I also had the same issue.
For me issue was:
private static final String FILE_PATH="/home/jeril/Logs.log";
handler = new FileHandler(FILE_PATH);
FILE_PATH was WRONG
This issue is a long standing bug in FileHandler (reported way back in March 2005, in Java 4):
JDK-6244047 : impossible to specify directories to logging FileHandler unless they exist
Quoting from the description of this bug:
If you specify a patern to the FileHandler that contains directories
that don't currently exist then the FileHandler will fail to
initialise even if the directories can be created
Its mentioned that it has been fixed in Java 8. For versions earlier than 8, the workaround is to either not use any directory in the pattern used for a FileHandler or use a directory which actually exists on the disk.
I think this is due to there being more than one instance of the logger that has it open or some other external application has it open with a read/write lock.
Related
Using Java.util.logging's FileHandler class to create cyclic logs. However why these logs are appended with .0 extension. .1,.2,.3 etc are fine, I only do not need .0 as my extension of file, since its confusing for the customer. Any way to achieve the same?
I am using java version java version "1.8.0_144".
FileHandler fileTxt = new FileHandler(pathOfLogFile+"_%g.log",
Integer.parseInt(prop.getProperty("MAX_LOG_FILE_SIZE")),
Integer.parseInt(prop.getProperty("NO_OF_LOG_FILES")), true);
SimpleFormatter formatterTxt = new SimpleFormatter();
fileTxt.setFormatter(formatterTxt);
logger.addHandler(fileTxt);
Name of log file is LOG_0.log. requirement is to not to have _0 on the latest file, need to be simply LOG.log.
You'll have to add more information about how your are setting up your FileHandler. Include code and or logging.properties file.
Most likely you are creating multiple open file handlers and are simply not closing the previous one before you create the next one. This can happen due to bug in your code or that you are simply not holding a strong reference to the logger that holds your FileHandler. Another way to create this issue is by create two running JVM processes. In which case you have no option but to choose the location of the where the unique number is placed in your file name.
Specify the %g token and %u in your file pattern. For example, %gfoo%u.log.
Per the FileHandler documentation:
If no "%g" field has been specified and the file count is greater than one, then the generation number will be added to the end of the generated filename, after a dot.
[snip]
Normally the "%u" unique field is set to 0. However, if the FileHandler tries to open the filename and finds the file is currently in use by another process it will increment the unique number field and try again. This will be repeated until FileHandler finds a file name that is not currently in use. If there is a conflict and no "%u" field has been specified, it will be added at the end of the filename after a dot. (This will be after any automatically added generation number.)
Thus if three processes were all trying to log to fred%u.%g.txt then they might end up using fred0.0.txt, fred1.0.txt, fred2.0.txt as the first file in their rotating sequences.
If you want to remove the zero from the first file only then the best approximation of the out of the box behavior would be to modify your code to:
If no LOG_0.log file exists then use File.rename to add the zero to the file. This changes LOG.log -> LOG_0.log.
Trigger a rotation. Results in LOG_0.log -> LOG_1.log etc. Then LOG_N.log -> LOG_0.log
Use File.rename to remove the zero from the file. LOG_0.log -> LOG.log
Open your file handler with number of logs as one and no append. This wipes the oldest log file and starts your new current one.
The problem with this is that your code won't rotate based on file size during a single run.
Simply use logger name as filename (Don't include %g in it). The latest file will be filename.log. Also note that the rotated files will have the numbers as extension.
I'm using Tomcat 8.0.21 on RHEL 7. In my Java code I'm logging to a text file with java.util.logging.Logger.
There is always only one log file. If I restart Tomcat the logging starts again from that moment and all previous logs are gone.
I added %g to file name as instructed here but it only adds 0 to file name and no rotation occurs.
Here is my code to create the FileHandler. strFilePath value is for example "/tmp/mylog.log". LogFormatter is my own class.
// Need to set format with own formatter class to get plain text to one line (default format is XML).
FileHandler file_handler = new FileHandler(strFilePath);
file_handler.setFormatter(new LogFormatter());
logger.addHandler(file_handler);
On my Windows 7 laptop logs rotate fine using the same code and Tomcat version.
How can I enable Java Logger log file rotation on my RHEL server?
Edit: I guess I could just add timestamp to file name when constructing FileHandler. I'm going to try that.
The FileHandler only rotates when the limit is exceeded (or unable to lock the file). If you want to rotate files by time then you have to code for that. If you want to just trigger a rotation then just create a throw away file handler with a limit of zero bytes before you open your actual file handler.
new FileHandler(pattern, 0, 1, false).close();
This is not a perfect solution but I think I won't lose old logs when I construct the FileHandler this way:
FileHandler file_handler = new FileHandler(strFilePath.replace("<timestamp>", new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss").format(new Date())));
I have "<timestamp>" string in the file name and that gets replaced here. I think a new log file is only created when I restart Tomcat so the log files might get big. But this is the best I've come up so far.
I wanted to keep track of a Java project main activity logs for debugging in one log file. I used the following approach to open the existed file, and append the new content, but it seems to add another file adding 1,2,3 in front of the name every time I run my program. Although the logfile.log keeps updated, and stored the desired content. But, I couldn't figure out why the other logfile.log.2, logfile.log.3 ... files created
LoggerFile lf = new LoggerFile();
final FileHandler fh = new FileHandler(System.getProperty("user.dir")+"/logfile.log", 1024 * 1024, 1, true);
Logger logger = lf.initialize(fh);
logger.info("log file message ... ");
fh.close();
Here is how the LoggerFile looks like:
public class LoggerFile {
public LoggerFile() {
}
public Logger initialize(FileHandler fh) throws SecurityException, IOException{
Logger logger = Logger.getLogger("MyLog");//Logger.getLogger(UpdateExposureScores.class.getName());
logger.addHandler(fh);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
return logger;
}
}
What seems to be wrong in the above code that it writes the log in several files? Thanks in advance.
I assume you are using java.util.logging. From the j.u.l.FileHandler documentation:
Normally the "%u" unique field is set to 0. However, if the FileHandler tries to open the filename and finds the file is currently in use by another process it will increment the unique number field and try again. This will be repeated until FileHandler finds a file name that is not currently in use. If there is a conflict and no "%u" field has been specified, it will be added at the end of the filename after a dot. (This will be after any automatically added generation number.)
Opening multiple file handlers within the same process also has the same effect. Add lines to log the result of java.lang.management.ManagementFactory.getRuntimeMXBean().getName() and java.lang.management.ManagementFactory.getRuntimeMXBean().getStartTime() so you can identify the JVMs that are creating the log files. You are either creating too many filehandlers pointing to the same location or you are starting multiple instances of your app.
You might want to look at the LogManager documentation which will explain alternate ways to configure your log settings.
I have a situation in which i have to make a different directory to put my logs.
i tried
File file = new File("c:\\className").mkdir(); But got the error incompatible type,
Found:boolean Required java.io.File, although i have imported java.io.File.
For the log file name i want to use something that make difference in log file name so that i can see all logs for several attempts to rub the application? how to achieve that... Please guide me to minimal code that make it...
And in a try statement i did so many thing like
try{
File file=new File("C:\\className").mkdir();
fh = new FileHandler("C:\\className\\className.log");
logger.addHandler(fh);
logger.setUseParentHandlers(false);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
}
catch(Exception e){ }
I want to add a log in catch block so that any kind of exception can be printed in my log file. Kindly help ... Thanks in Advance
File file = new File("c:\\className").mkdir();
mkDir returns boolean you need the correction as
File file = new File("c:\\classname");
file.mkdir();
You get compilation error if you use
File file=new File("C:\\className").mkdir();
Because, mkdir() returns boolean type. So, this has to be in another statement like this -
File file=new File("C:\\className");
boolean created = file.mkdir();
For logging, you may use log4j. It's simple to use.
We're recently switched over to Log4J from JUL (java.util.Logging) because I wanted to add additional log files for different logging levels.
We have the option in the program to optionally append a value and a date/time stamp to the log file name at the (for all intents and purposes) end of the program's execution.
Because JUL seemed to open and close the file as needed to write to the file, it wasn't locked and we could simply use .renameTo() to change the filename.
Now, using Log4J, that file is left open and is locked, preventing us from renaming the file(s).
I can't decide the name of the file before I configure the logging because the property file containing the options for renaming is some time after the logging is needed (this is why we renamed it at the end of the program).
Do you have any suggestions as to how this can be achieved?
Would Logback and/or SLF4J help or hinder this?
I have sort of worked around the issue by using a system parameter in the log4j properties file, setting the property and then reloading the property file.
This allows me to change the name of the log file to something else at the end of the run, and then rename the old files.
It's inelegant, and very much of a kludge, so I would like to avoid this as it also leaves these temporary files around after the run.
One surefire approach would be to implement your own log4j Appender, perhaps based on the FileAppender ( http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/FileAppender.html ). Add your own specialized API to request the file be renamed.
I haven't tried this yet, but the tact I would take would be to use the underlying API setFile(...): http://www.jdocs.com/log4j/1.2.13/org/apache/log4j/FileAppender.html#M-setFile%28String,boolean,boolean,int%29
For example:
public class RenamingFileAppender extends FileAppender {
...
/** fix concurrency issue in stock implementation **/
public synchronized void setFile(String file) {
super.setFile(file);
}
public synchronized void renameFile(String newName) {
// whole method is synchronized to avoid losing log messages
// implementation can be smarter in having a short term queue
// for any messages that arrive while file is being renamed
File currentFile = new File(this.fileName);
File newFile = new File(newName);
// do checks to ensure current file exists, can be renamed etc.
...
// create a temp file to use while current log gets renamed
File tempFile = File.createTempFile("renaming-appender", ".log");
tempFile.deleteOnExit();
// tell underlying impl to use temporary file, so current file is flushed and closed
super.setFile(tempFile.getAbsolutePath(), false, this.bufferedIO, this.bufferSize);
// rename the recently closed file
currentFile.renameTo(newFile);
// now go back to the original log contents under the new name. Note append=true
super.setFile(newFile.getAbsolutePath(), true, this.bufferedIO, this.bufferSize);
}
Consider using a shutdown hooks, and renaming the file there...
http://onjava.com/pub/a/onjava/2003/03/26/shutdownhook.html
http://www.developerfeed.com/threads/tutorial/understanding-java-shutdown-hook
http://download.oracle.com/javase/1.4.2/docs/guide/lang/hook-design.html