Disclaimer: I apologize that this question is so long. I have added code as I have explored suggestions made here and done additional research since asking
The immediate thing that comes to mind is, take a look at log4j. It's an open source logging framework that's very widely used in all sorts of libraries and applications.
Edit:
java.util.logging is the basic API. It really doesn't do anything you don't tell it to do, explicitly, in code. log4j is a library with full configuration facilities and other goodies. It sits atop java.util.logging and expands it with functionality that is much easier to use than the (relatively) low-level java.util.logging.
Edit:
The problem in your original code is that you're closing the handler early.
Original Text:
I see two problems with your (original) code:
Problem one, you're calling getLogger("")
in your init, but calling getLogger(xxx.class.getName())
in your implementations. Each of those loggers is a different logger, and you're only setting the file handler for the ""
one.
Problem two, which was being masked by problem one, you're closing the handler early.
Here's something you can try for multiple classes in one file:
LoggingSSCCE.java:
package loggingsscce;
import java.io.IOException;
import java.util.Hashtable;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
public class LoggingSSCCE {
private static String LOG_FILE_NAME = "loggingsscce.log";
Hashtable<String, Logger> loggers = new Hastable<String, Logger>();
FileHandler handler = null;
public static void main(String[] args) throws IOException {
LogTest lta = new LogTestA();
lta.doLog();
LogTest ltb = new LogTestB();
ltb.doLog();
}
public static Logger getLogger(String loggerName) throws IOException {
if ( loggers.get(loggerName) != null )
return loggers.get(loggerName);
if ( handler == null ) {
boolean append = true;
handler = new FileHandler(LoggingSSCCE.LOG_FILE_NAME, append);
handler.setFormatter(new SimpleFormatter());
}
Logger logger = Logger.getLogger(loggerName);
logger.setLevel(Level.ALL);
logger.addHandler(handler);
loggers.put(loggerName, logger);
return logger;
}
}
LogTest.java:
package loggingsscce;
interface LogTest {
public void doLog();
}
LogTestA.java:
package loggingsscce;
import java.util.logging.Level;
import java.util.logging.Logger;
class LogTestA implements LogTest {
@Override
public void doLog() {
LoggingSSCCE.getLogger(LogTestA.class.getName()).log(Level.INFO, "LogTestA.doLog()");
}
}
LogTestB.java:
package loggingsscce;
import java.util.logging.Level;
import java.util.logging.Logger;
class LogTestB implements LogTest {
@Override
public void doLog() {
LoggingSSCCE.getLogger(LogTestB.class.getName()).log(Level.INFO, "LogTestB.doLog()");
}
}
If you want this to work for one file per class, or some other criteria, simply modify LoggingSSCCE.getLogger
to compute an appropriate file name for each case.