Change two lines, and wham, brought this in from yohoho.server.util.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@1184 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -0,0 +1,195 @@
|
|||||||
|
//
|
||||||
|
// $Id: AuditLogger.java,v 1.1 2003/08/04 20:58:07 ray Exp $
|
||||||
|
|
||||||
|
package com.threerings.samskivert.util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.text.FieldPosition;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.samskivert.Log;
|
||||||
|
|
||||||
|
import com.samskivert.util.Interval;
|
||||||
|
import com.samskivert.util.IntervalManager;
|
||||||
|
import com.samskivert.util.Throttle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by various services to generate audit logs which can be useful for
|
||||||
|
* auditing, debugging and other logly necessities. The audit logger
|
||||||
|
* automatically rolls over its logs at midnight to facilitate the
|
||||||
|
* collection, processing and possible archiving of the logs.
|
||||||
|
*/
|
||||||
|
public class AuditLogger
|
||||||
|
implements Interval
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates an audit logger that logs to the specified file.
|
||||||
|
*/
|
||||||
|
public AuditLogger (String path, String filename)
|
||||||
|
{
|
||||||
|
_logPath = new File(path, filename);
|
||||||
|
openLog(true);
|
||||||
|
|
||||||
|
// update the day format
|
||||||
|
_dayStamp = _dayFormat.format(new Date());
|
||||||
|
scheduleNextRolloverCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the supplied message to the log, prefixed by a date and
|
||||||
|
* timestamp. A newline will be appended to the message.
|
||||||
|
*/
|
||||||
|
public synchronized void log (String message)
|
||||||
|
{
|
||||||
|
// construct the message
|
||||||
|
StringBuffer buf = new StringBuffer(
|
||||||
|
message.length() + TIMESTAMP_LENGTH);
|
||||||
|
_format.format(new Date(), buf, _fpos);
|
||||||
|
buf.append(message);
|
||||||
|
|
||||||
|
// and write it to the log
|
||||||
|
boolean wrote = false;
|
||||||
|
if (_logWriter != null) {
|
||||||
|
_logWriter.println(buf.toString());
|
||||||
|
wrote = !_logWriter.checkError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// log an error if we failed to write the log message
|
||||||
|
if (!wrote) {
|
||||||
|
// be careful about logging zillions of errors if something
|
||||||
|
// bad happens to our log file
|
||||||
|
if (_throttle.throttleOp()) {
|
||||||
|
_throttled++;
|
||||||
|
} else {
|
||||||
|
if (_throttled > 0) {
|
||||||
|
Log.warning("Suppressed " + _throttled +
|
||||||
|
" intervening error messages.");
|
||||||
|
_throttled = 0;
|
||||||
|
}
|
||||||
|
Log.warning("Failed to write audit log message " +
|
||||||
|
"[file=" + _logPath + ", msg=" + message + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes this audit log (generally only done when the server is
|
||||||
|
* shutting down.
|
||||||
|
*/
|
||||||
|
public void close ()
|
||||||
|
{
|
||||||
|
if (_logWriter != null) {
|
||||||
|
log("log_closed");
|
||||||
|
_logWriter.close();
|
||||||
|
_logWriter = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens our log file, sets up our print writer and writes a message
|
||||||
|
* to it indicating that it was opened.
|
||||||
|
*/
|
||||||
|
protected void openLog (boolean freakout)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// create our file writer to which we'll log
|
||||||
|
_logWriter = new PrintWriter(new FileWriter(_logPath, true), true);
|
||||||
|
|
||||||
|
// log a standard message
|
||||||
|
log("log_opened " + _logPath);
|
||||||
|
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
String errmsg = "Unable to open audit log '" + _logPath + "'";
|
||||||
|
if (freakout) {
|
||||||
|
throw new RuntimeException(errmsg, ioe);
|
||||||
|
} else {
|
||||||
|
Log.warning(errmsg + " [ioe=" + ioe + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface Interval
|
||||||
|
public synchronized void intervalExpired (int id, Object arg)
|
||||||
|
{
|
||||||
|
// check to see if we should roll over the log
|
||||||
|
String newDayStamp = _dayFormat.format(new Date());
|
||||||
|
|
||||||
|
// hey! we need to roll it over!
|
||||||
|
if (!newDayStamp.equals(_dayStamp)) {
|
||||||
|
log("log_closed");
|
||||||
|
_logWriter.close();
|
||||||
|
_logWriter = null;
|
||||||
|
|
||||||
|
// rename the old file
|
||||||
|
String npath = _logPath.getPath() + "." + _dayStamp;
|
||||||
|
if (!_logPath.renameTo(new File(npath))) {
|
||||||
|
Log.warning("Failed to rename audit log file " +
|
||||||
|
"[path=" + _logPath + ", npath=" + npath + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
// open our new log file
|
||||||
|
openLog(false);
|
||||||
|
|
||||||
|
// and set the next day stamp
|
||||||
|
_dayStamp = newDayStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduleNextRolloverCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule the next check to see if we should roll the logs over.
|
||||||
|
*/
|
||||||
|
protected void scheduleNextRolloverCheck ()
|
||||||
|
{
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
|
||||||
|
// schedule the next check for the next hour mark
|
||||||
|
long nextCheck = (1000L - cal.get(Calendar.MILLISECOND)) +
|
||||||
|
(59L - cal.get(Calendar.SECOND)) * 1000L +
|
||||||
|
(59L - cal.get(Calendar.MINUTE)) * (1000L * 60L);
|
||||||
|
|
||||||
|
IntervalManager.register(this, nextCheck, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The path to our log file. */
|
||||||
|
protected File _logPath;
|
||||||
|
|
||||||
|
/** We actually write to this feller here. */
|
||||||
|
protected PrintWriter _logWriter;
|
||||||
|
|
||||||
|
/** Suppress freakouts if our log file becomes hosed. */
|
||||||
|
protected Throttle _throttle = new Throttle(2, 5*60*1000L);
|
||||||
|
|
||||||
|
/** Used to count the number of throttled messages for reporting. */
|
||||||
|
protected int _throttled;
|
||||||
|
|
||||||
|
/** The daystamp of the log file we're currently writing to. */
|
||||||
|
protected String _dayStamp;
|
||||||
|
|
||||||
|
/** Used to format log file suffixes. */
|
||||||
|
protected SimpleDateFormat _dayFormat = new SimpleDateFormat("yyyyMMdd");
|
||||||
|
|
||||||
|
/** Timestamp format used on all log messages. */
|
||||||
|
protected static final String TIMESTAMP_FORMAT =
|
||||||
|
"yyyy/MM/dd HH:mm:ss:SSS ";
|
||||||
|
|
||||||
|
/** The length of the timestamp format. */
|
||||||
|
protected static final int TIMESTAMP_LENGTH = TIMESTAMP_FORMAT.length();
|
||||||
|
|
||||||
|
/** Used to format timestamps. */
|
||||||
|
protected SimpleDateFormat _format =
|
||||||
|
new SimpleDateFormat(TIMESTAMP_FORMAT);
|
||||||
|
|
||||||
|
/** Annoying parameter required by the Format.format() method that
|
||||||
|
* appends to a string buffer. */
|
||||||
|
protected FieldPosition _fpos =
|
||||||
|
new FieldPosition(SimpleDateFormat.DATE_FIELD);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user