我正在创建允许循环浏览文件的java.util.logging.FileHandler
。运行我的应用程序的多个实例时,将为该应用程序的每个实例创建一个新的日志文件。我需要知道应用程序正在使用哪个文件,因为我想将日志文件上传到我的服务器以供进一步查看。如何判断某个FileHandler正在使用哪个文件?
答案 0 :(得分:2)
最简单的方法是在文件名本身中放置某种标识符,即创建FileHandler时的pattern
参数。由于这些是同一个应用程序的实例,区分它们的一种方法是通过它们的进程ID,因此您可以创建该模式的那一部分。更好的方法是通过命令行传入标识符并使用它来创建文件名。这样你可以控制在某种意义上创建的文件。最后,如果您的应用程序知道为什么它与其他所有应用程序不同,例如它连接到特定的数据库服务器,那么您可以将该数据库服务器名称用作文件名的一部分。
编辑:似乎没有任何API可以获取FileHandler正在使用的文件的名称。我建议查看x4juli中的日志记录扩展(它将很多log4j功能移植到java.util.logging规范中):
你应该能够替换提供getFile()方法的FileHandler实例:
答案 1 :(得分:1)
实际上,只需自己扩展FileHandler就可以做到这一点。例如......
MyFileHandler.java:
import java.io.IOException;
import java.util.logging.FileHandler;
public class MyFileHandler extends FileHandler {
protected String _MyFileHandler_Patern;
public MyFileHandler(String pattern) throws IOException {
_MyFileHandler_Patern = pattern;
}
public String getMyFileHandlerPattern() {
return _MyFileHandler_Patern;
}
}
DeleteMe.java:
import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Logger;
public class DeleteMe {
public static void main(String[] args) throws IOException {
Logger log = Logger.getLogger(DeleteMe.class.getName());
MyFileHandler output = new MyFileHandler("output.log");
log.addHandler(output);
for (Handler handler : log.getHandlers()) {
if (handler instanceof MyFileHandler) {
MyFileHandler x = (MyFileHandler) handler;
if ("output.log".equals(x.getMyFileHandlerPattern())) {
System.out.println("found hanlder writing to output.log");
}
}
}
}
}
答案 2 :(得分:0)
好的,我不得不说FileHandler没有提供确定日志文件的方法是非常愚蠢的。
我开始编写一个名为“chooseFile()”的函数,该函数在/ tmp中搜索下一个可用的日志文件名并返回该文件。然后,您可以将该文件的名称传递给新的FileHandler()。
/**
* Utility: select a log file. File is created immediately to reserve
* its name.
*/
static public File chooseFile(final String basename) throws IOException {
final int nameLen = basename.length();
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
String[] logs = tmpDir.list(new FilenameFilter() {
public boolean accept(File d, String f) {
return f.startsWith(basename);
}
});
int count = 0;
if (logs.length > 0) {
for (String name : logs) {
int n = atoi(name.substring(nameLen));
if (n >= count) count = n + 1;
}
}
String filename = String.format("%s%d.log", basename, count);
File logFile = new File(tmpDir, filename);
logFile.createNewFile();
return logFile;
}
答案 3 :(得分:0)
这是我相当愚蠢的方式。如果你不使用任何格式字符串,它适用于默认值,如果你在文件名中使用g和u格式字符串,而不是其他格式字符串,则它可以工作。
public class FriendlyFileHandler extends FileHandler {
/***
* In order to ensure the most recent log file is the file this one owns,
* we flush before checking the directory for most recent file.
*
* But we must keep other log handlers from flushing in between and making
* a NEW recent file.
*/
private static Object[] flushLock = new Object[0];
private String pattern;
public FriendlyFileHandler(String pattern, int maxLogLengthInBytes, int count) throws IOException,
SecurityException {
super(pattern, maxLogLengthInBytes, count);
this.pattern = pattern;
}
/***
* Finds the most recent log file matching the pattern.
* This is just a guess - if you have a complicated pattern
* format it may not work.
*
* IMPORTANT: This log file is still in use. You must
* removeHandler() on the logger first, .close() this handler,
* then add a NEW handler to your logger. THEN, you can read
* the file.
*
* Currently supported format strings: g, u
*
* @return A File of the current log file, or null on error.
*/
public synchronized File getCurrentLogFile() {
synchronized(flushLock) {
// so the file has the most recent date on it.
flush();
final String patternRegex =
// handle incremental number formats
pattern.replaceAll("%[gu]", "\\d*") +
// handle default case where %g is appended to end
"(\\.\\d*)?$";
final Pattern re = Pattern.compile(patternRegex);
final Matcher matcher = re.matcher("");
// check all files in the directory where this log would be
final File basedir = new File(pattern).getParentFile();
final File[] logs = basedir.listFiles(new FileFilter() {
@Override
public boolean accept(final File pathname) {
// only get files that are part of the pattern
matcher.reset(pathname.getAbsolutePath());
return matcher.find();
}
});
return findMostRecentLog(logs);
}
}
private File findMostRecentLog(File[] logs) {
if (logs.length > 0) {
long mostRecentDate = 0;
int mostRecentIdx = 0;
for (int i = 0; i < logs.length; i++) {
final long d = logs[i].lastModified();
if (d >= mostRecentDate) {
mostRecentDate = d;
mostRecentIdx = i;
}
}
return logs[mostRecentIdx];
}
else {
return null;
}
}
@Override
public synchronized void flush() {
// only let one Handler flush at a time.
synchronized(flushLock) {
super.flush();
}
}
}