SimpleLogFileHandler.java

  1. package gov.usgs.util.logging;

  2. import gov.usgs.util.StreamUtils;

  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.io.OutputStream;
  6. import java.text.SimpleDateFormat;
  7. import java.util.Date;
  8. import java.util.logging.Handler;
  9. import java.util.logging.LogRecord;
  10. import java.util.logging.Logger;

  11. /**
  12.  * A java.util.logging style Handler that does daily log rotation by default.
  13.  */
  14. public class SimpleLogFileHandler extends Handler {

  15.     /** Default format used. */
  16.     public static final String DEFAULT_FILENAME_FORMAT = "'log_'yyyyMMdd'.log'";

  17.     /** The directory where log files are written. */
  18.     private File logDirectory;

  19.     /** Used to generate filename for current log message. */
  20.     private SimpleDateFormat filenameFormat;

  21.     /** The last filename used when logging. */
  22.     private String currentFilename;

  23.     /** Handle to the current log file. */
  24.     private OutputStream currentStream;

  25.     /**
  26.      * Create a default SimpleLogHandler.
  27.      *
  28.      * Uses the system locale to roll log files once a day, and default filename
  29.      * format "log_YYYYMMDD.log".
  30.      *
  31.      * @param logDirectory
  32.      *            the directory to write log files.
  33.      */
  34.     public SimpleLogFileHandler(final File logDirectory) {
  35.         this(logDirectory, new SimpleDateFormat(DEFAULT_FILENAME_FORMAT));
  36.     }

  37.     /**
  38.      * Create a SimpleLogHandler with a custom filename format.
  39.      *
  40.      * @param logDirectory
  41.      *            the directory to write log files.
  42.      * @param filenameFormat
  43.      *            the format for log files. Files are opened as soon as the
  44.      *            format output changes for a given log's message.
  45.      */
  46.     public SimpleLogFileHandler(final File logDirectory,
  47.             final SimpleDateFormat filenameFormat) {
  48.         this.logDirectory = logDirectory;
  49.         this.filenameFormat = filenameFormat;
  50.         this.currentFilename = null;
  51.         this.currentStream = null;
  52.     }

  53.     /**
  54.      * Closes the current log file.
  55.      */
  56.     public void close() throws SecurityException {
  57.         if (currentStream != null) {
  58.             try {
  59.                 // log when the file was closed, if possible
  60.                 currentStream.write(("\nClosing log file at "
  61.                         + new Date().toString() + "\n\n").getBytes());
  62.             } catch (IOException e) {
  63.                 // ignore
  64.             } finally {
  65.                 StreamUtils.closeStream(currentStream);
  66.                 currentStream = null;
  67.             }
  68.         }
  69.     }

  70.     /**
  71.      * Attempts to flush any buffered content. If exceptions occur, the stream
  72.      * is closed.
  73.      */
  74.     public void flush() {
  75.         if (currentStream != null) {
  76.             try {
  77.                 currentStream.flush();
  78.             } catch (IOException e) {
  79.                 close();
  80.                 currentStream = null;
  81.             }
  82.         }
  83.     }

  84.     /**
  85.      * Retrieve the outputstream for the current log file.
  86.      *
  87.      * @param date
  88.      *            the date of the message about to be logged.
  89.      * @return and OutputStream where the log message may be written.
  90.      * @throws IOException
  91.      *             if errors occur.
  92.      */
  93.     protected OutputStream getOutputStream(final Date date) throws IOException {
  94.         String filename = filenameFormat.format(date);
  95.         if (currentStream == null || currentFilename == null
  96.                 || !filename.equals(currentFilename)) {
  97.             // close any existing stream
  98.             close();

  99.             // filename is what is being opened
  100.             currentFilename = filename;
  101.             currentStream = StreamUtils.getOutputStream(new File(logDirectory,
  102.                     filename), true);

  103.             // log when the file was opened
  104.             currentStream
  105.                     .write(("Opened log file at " + new Date().toString() + "\n\n")
  106.                             .getBytes());
  107.             currentStream.flush();
  108.         }
  109.         return currentStream;
  110.     }

  111.     /**
  112.      * Add a LogRecord to the log file.
  113.      */
  114.     public void publish(LogRecord record) {
  115.         if (record == null) {
  116.             return;
  117.         }

  118.         String message = getFormatter().format(record);
  119.         try {
  120.             OutputStream stream = getOutputStream(new Date(record.getMillis()));
  121.             stream.write(message.getBytes());
  122.             flush();
  123.         } catch (Exception e) {
  124.             // close if any exceptions occur
  125.             close();
  126.         }
  127.     }

  128.     private static final Logger LOGGER = Logger
  129.             .getLogger(SimpleLogFileHandler.class.getName());

  130.         /**
  131.          * Testing for handler
  132.          * @param args CLI args
  133.          * @throws Exception if error occurs
  134.          */
  135.             public static void main(final String[] args) throws Exception {
  136.         SimpleDateFormat ridiculouslyShortLogs = new SimpleDateFormat(
  137.                 "'log_'yyyyMMddHHmmss'.log'");
  138.         File logDirectory = new File("log");

  139.         SimpleLogFileHandler handler = new SimpleLogFileHandler(logDirectory,
  140.                 ridiculouslyShortLogs);
  141.         handler.setFormatter(new SimpleLogFormatter());
  142.         LOGGER.addHandler(handler);

  143.         // there should be at least 2 log files created, and more likely 3
  144.         LOGGER.info("message to log");
  145.         handler.close();
  146.         LOGGER.info("message to log");
  147.         Thread.sleep(1000);
  148.         LOGGER.info("another message to log");
  149.         Thread.sleep(250);
  150.         LOGGER.info("another message to log");
  151.         Thread.sleep(1000);
  152.         LOGGER.info("yet another message to log");
  153.         Thread.sleep(250);
  154.         LOGGER.info("yet another message to log");
  155.     }

  156. }