Fields Summary |
---|
private MeteredStream | meter |
private final AMXLoggingHook | mAMXLoggingHook |
private Date | date |
private static final String | LOGS_DIR |
private String | logFileName |
private String | absoluteFileName |
private static boolean | isInitialized |
private LogMBean | logMBean |
private com.sun.enterprise.config.serverbeans.LogService | logService |
private static final int | WARNING |
private static final int | SEVERE |
private static final String | INSTANCE_ROOT_PROPERTY |
private static final String | LOGGING_MAX_HISTORY_FILES |
private static final int | MINIMUM_FILE_ROTATION_VALUE |
private int | limitForFileRotation |
private Object | fileUpdateLock |
private boolean | rotationInProgress |
private static final FileandSyslogHandler | thisInstance |
private LinkedList | pendingLogRecordList |
private static boolean | rotationRequested |
private static final String | LOG_ROTATE_DATE_FORMAT |
private static final SimpleDateFormat | logRotateDateFormatter |
private static Vector | _recentErrors |
private static final int | MAX_RECENT_ERRORS |
Methods Summary |
---|
private static synchronized void | addRecentErrorMessage(java.lang.String error)
if (_recentErrors.size() < MAX_RECENT_ERRORS) {
_recentErrors.add(error);
} else {
_recentErrors.removeElementAt(0);
_recentErrors.add(MAX_RECENT_ERRORS - 1, error);
}
|
void | changeFileName(java.lang.String fileName)This method is invoked from LogManager.reInitializeLoggers() to
change the location of the file.
// If the file name is same as the current file name, there
// is no need to change the filename
if( fileName.trim().equals( absoluteFileName ) ) {
return;
}
synchronized( this ) {
super.flush( );
super.close();
try {
openFile( fileName );
// Change the file for LogViewer
LogFilter.setLogFile( new LogFile( fileName ) );
absoluteFileName = fileName;
} catch( IOException ix ) {
new ErrorManager().error(
"FATAL ERROR: COULD NOT OPEN LOG FILE. " +
"Please Check to make sure that the directory for " +
"Logfile exists. Currently reverting back to use the " +
" default server.log", ix, ErrorManager.OPEN_FAILURE );
try {
// Reverting back to the old server.log
openFile( absoluteFileName );
} catch( Exception e ) {
new ErrorManager().error(
"FATAL ERROR: COULD NOT RE-OPEN SERVER LOG FILE. ", e,
ErrorManager.OPEN_FAILURE );
}
}
}
|
public void | cleanUpHistoryLogFiles()cleanup the history log file based on JVM system property "max_history_files".
If it is defined with valid number, we only keep that number of history logfiles;
If "max_history_files" is defined without value, then default that number to be 10;
If "max_history_files" is defined with value 0, no histry log file will
be keeped; and server.log is the only log file.
String nStr = System.getProperty(LOGGING_MAX_HISTORY_FILES);
if (nStr==null) return;
int maxHistryFiles = 10;
if (!"".equals(nStr)) {
try {
maxHistryFiles = Integer.parseInt(nStr);
} catch (NumberFormatException e) {};
}
if (maxHistryFiles<0) return;
File dir = new File(absoluteFileName).getParentFile();
if (dir==null) return;
File[] fset = dir.listFiles();
ArrayList candidates = new ArrayList();
for (int i=0; fset!=null && i<fset.length; i++) {
if ( !logFileName.equals(fset[i].getName()) &&
fset[i].isFile() &&
fset[i].getName().startsWith(logFileName) ) {
candidates.add(fset[i].getAbsolutePath() );
}
}
if (candidates.size() <= maxHistryFiles) return;
Object[] pathes = candidates.toArray();
java.util.Arrays.sort(pathes);
try {
for (int i=0; i<pathes.length-maxHistryFiles; i++) {
new File((String)pathes[i]).delete();
}
} catch (Exception e) {
new ErrorManager().error("FATAL ERROR: COULD NOT DELETE LOG FILE..",
e, ErrorManager.GENERIC_FAILURE );
}
|
public static synchronized void | clearRecentErrorMessages()
_recentErrors = new Vector();
|
protected AMXLoggingHook | createAMXLoggingHook()Returns the AMXLoggingHook to use for this logger.
This method is here primarily so a subclass can override it if needed.
return new AMXLoggingHook();
|
public java.lang.String | createFileName()Creates the File under the specified instance directory
ServerContext sc = ApplicationServer.getServerContext();
String instDir = "";
if (sc != null) {
instDir = sc.getInstanceEnvironment().getInstancesRoot();
} else {
instDir = System.getProperty( INSTANCE_ROOT_PROPERTY );
}
String[] names = {instDir, LOGS_DIR, getLogFileName() };
// Create an absolute log filename
return StringUtils.makeFilePath(names, false);
|
java.lang.String | getAbsoluteLogFileName()A simple getter to access the complete fileName used by this FileHandler.
return absoluteFileName;
|
public static synchronized com.sun.enterprise.server.logging.FileandSyslogHandler | getInstance()
return thisInstance;
|
protected java.lang.String | getLogFileName()
return logFileName;
|
public static synchronized java.util.Vector | getRecentErrorMessages()
return _recentErrors;
|
private void | openFile(java.lang.String fileName)Creates the file and initialized MeteredStream and passes it on to
Superclass (java.util.logging.StreamHandler).
File file = new File( fileName );
FileOutputStream fout = new FileOutputStream( fileName, true );
BufferedOutputStream bout = new BufferedOutputStream( fout );
meter = new MeteredStream( bout, file.length() );
setOutputStream( meter );
|
private void | planBLogRotate(java.lang.String originalFileName, java.lang.String renamedFileName)This method is solely provided as a plan B for Windows. On Windows
the file rename fails if there are open handles to the file.
We want to make sure that the log rotation succeeds in this case also.
Basically we copy the contents of the file instead of renaming.
FileOutputStream fo = null;
FileInputStream fi = null;
try {
fo = new FileOutputStream( renamedFileName );
fi = new FileInputStream( originalFileName );
int BUF_SIZE = 4096;
byte[] buffer = new byte[BUF_SIZE];
int i = -1;
do {
i = fi.read( buffer );
// Reached EOF.
if( i == -1 ) { break; }
if( i == BUF_SIZE ) {
fo.write( buffer );
} else {
// We have less number of bytes to read than the BUF_SIZE
// So, just create a temporary buffer with the exact
// number of bytes read and write that to the rotated
// file.
byte[] tempBuffer = new byte[i];
int j = 0;
for( j = 0; j < i; j++ ) {
tempBuffer[j] = buffer[j];
}
fo.write( tempBuffer );
}
} while( true );
} catch( Exception e ) {
// If we fail in Plan B. Too bad, we should not
// log a message here as it may lead to recursion.
} finally {
try {
fo.close( );
fi.close( );
} catch( Exception e ) { }
}
|
public synchronized void | publish(java.util.logging.LogRecord record)Publishes the logrecord using the super class and checks to see
if a file rotation is required.
// This is provided to avoid the recursion. When Log Rotation
// is called, there is a chance that any of the called routines
// in the Log Rotation call path may log a message, which may
// result in a recursion. Hence, we shall log those log messages
// after the rotation is completed, so as to avoid the recursion.
if( rotationInProgress ) {
pendingLogRecordList.addLast(record);
return;
}
// Important: There are issues with double instantiation of
// FileandSyslogHandler if we move the createFile/openFile calls
// to the constructor. For now, we will do this for the first
// publish call.
if( meter == null ) {
try {
absoluteFileName = createFileName( );
openFile( absoluteFileName );
} catch( Exception e ) {
throw new RuntimeException(
"Serious Error Couldn't open Log File" + e );
}
}
super.publish( record );
flush( );
if ( ( rotationRequested )
|| ( ( limitForFileRotation > 0 )
&& ( meter.written >= limitForFileRotation ) ) )
{
rotationInProgress = true;
// If we have written more than the limit set for the
// file, or rotation requested from the Timer Task or LogMBean
// start fresh with a new file after renaming the old file.
rotate( );
rotationInProgress = false;
rotationRequested = false;
while (pendingLogRecordList.size() != 0) {
publish((LogRecord) pendingLogRecordList.removeFirst());
}
}
if (mAMXLoggingHook != null) {
mAMXLoggingHook.publish( record, getFormatter() );
}
int level = record.getLevel( ).intValue();
// The processing here is to raise alarms if
// alarm flag in domain.xml is on and the log level is SEVERE or
// WARNING
if(( level != WARNING ) && (level != SEVERE)) {
return;
}
//Any WARNING or SEVERE message is placed onto a singleton rolling
// error message list. This can be queried as part of a running
// server's status. This allows the last N error messages to be easily
// viewed without having to consult the log file.
String logMessage = getFormatter().format(record);
addRecentErrorMessage(logMessage);
ErrorStatistics.singleton().updateStatistics(record); // error stats.
if( logService == null ) {
logService = ServerLogManager.getLogService( );
}
// _REVISIT_: Deprecate Alarms flag
if( logService == null ) return;
// Raise an alarm if the logged message is a SEVERE or WARNING
// message.
if( record.getLevel( ).intValue() == WARNING ) {
LogMBean.getInstance().raiseWarningAlarm( record );
} else if( record.getLevel( ).intValue() == SEVERE ) {
LogMBean.getInstance().raiseSevereAlarm( record );
}
|
void | requestRotation()Request Rotation called from Rotation Timer Task or LogMBean
synchronized( this ) {
rotationRequested = true;
}
|
private void | rotate()A Simple rotate method to close the old file and start the new one
when the limit is reached.
final FileandSyslogHandler thisInstance = this;
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run( ) {
thisInstance.flush( );
thisInstance.close();
StringBuffer renamedFileName = null;
try {
File oldFile = new File( absoluteFileName );
renamedFileName =
new StringBuffer( absoluteFileName + "_" );
logRotateDateFormatter.format(
new Date(), renamedFileName,
new FieldPosition( 0 ) );
File rotatedFile = new File(
renamedFileName.toString() );
boolean renameSuccess = oldFile.renameTo( rotatedFile );
if( !renameSuccess ) {
// If we don't succeed with file rename which
// most likely can happen on Windows because
// of multiple file handles opened. We go through
// Plan B to copy bytes explicitly to a renamed
// file.
planBLogRotate(absoluteFileName,
renamedFileName.toString( ) );
String freshServerLogFileName = createFileName( );
// We do this to make sure that server.log
// contents are flushed out to start from a
// clean file again after the rename..
FileOutputStream fo =
new FileOutputStream( freshServerLogFileName );
fo.close( );
}
openFile( createFileName( ) );
LogFilter.setLogFile( new LogFile( absoluteFileName) );
// This will ensure that the log rotation timer
// will be restarted if there is a value set
// for time based log rotation
LogRotationTimer.getInstance( ).restartTimer( );
cleanUpHistoryLogFiles();
} catch( IOException ix ) {
new ErrorManager().error(
"FATAL ERROR: COULD NOT OPEN LOG FILE..", ix,
ErrorManager.OPEN_FAILURE );
}
return null;
}
}
);
|
synchronized void | setLimitForRotation(int rotationLimitInBytes)A package private method to set the limit for File Rotation.
if ((rotationLimitInBytes == 0) ||
(rotationLimitInBytes >= MINIMUM_FILE_ROTATION_VALUE )) {
limitForFileRotation = rotationLimitInBytes;
}
|