LogFilterpublic class LogFilter extends Object
LogFilter will be used by Admin Too Log Viewer Front End to filter the
records. LogMBean delegates the getLogRecordsUsingQuery method to this
class static method. |
Fields Summary |
---|
private static final String | RESULTS_ATTRIBUTE | private static final String | NV_SEPARATOR | protected static final String[] | LOG_LEVELS | private static SimpleDateFormat | SIMPLE_DATE_FORMAT | private static String[] | serverLogElements | private static LogFile | _logFile | private static Hashtable | logFileCache |
Methods Summary |
---|
protected static boolean | allChecks(LogFile.LogEntry entry, java.util.Date fromDate, java.util.Date toDate, java.lang.String queryLevel, boolean onlyLevel, java.util.List listOfModules, java.util.Properties nameValueMap)This method accepts the first line of the Log Record and checks
to see if it matches the query.
if ((!dateTimeCheck(entry.getLoggedDateTime(), fromDate, toDate))
|| (!levelCheck(entry.getLoggedLevel(), queryLevel, onlyLevel))
|| (!moduleCheck(entry.getLoggedLoggerName(), listOfModules))
|| (!nameValueCheck(entry.getLoggedNameValuePairs(), nameValueMap)))
{
return false;
}
return true;
| private static javax.management.AttributeList | convertResultsToTheStructure(java.util.List results)This method converts the results to the appropriate structure for
LogMBean to return to the Admin Front End.
AttributeList Results contain 2 attributes
Attribute 1: Contains the Header Information, that lists out all the
Field Names and Positions
Attribute 2: Contains the actual Results, Each Log record is an entry
of this result. The LogRecord itself is an ArrayList of
all fields.
if( results == null ) { return null; }
AttributeList resultsInTemplate = new AttributeList( );
resultsInTemplate.add( LogRecordTemplate.getHeader( ) );
Iterator iterator = results.iterator( ) ;
ArrayList listOfResults = new ArrayList( );
Attribute resultsAttribute = new Attribute( RESULTS_ATTRIBUTE,
listOfResults );
resultsInTemplate.add( resultsAttribute );
while( iterator.hasNext() ) {
LogFile.LogEntry entry = (LogFile.LogEntry) iterator.next();
ArrayList logRecord = new ArrayList( );
logRecord.add( new Long(entry.getRecordNumber()) );
logRecord.add( entry.getLoggedDateTime() );
logRecord.add( entry.getLoggedLevel() );
logRecord.add( entry.getLoggedProduct() );
logRecord.add( entry.getLoggedLoggerName() );
logRecord.add( entry.getLoggedNameValuePairs() );
logRecord.add( entry.getMessageId() );
logRecord.add( entry.getLoggedMessage() );
listOfResults.add( logRecord );
}
return resultsInTemplate;
| protected static boolean | dateTimeCheck(java.util.Date loggedDateTime, java.util.Date fromDateTime, java.util.Date toDateTime)
if ((fromDateTime == null) || (toDateTime == null)) {
// If user doesn't specify fromDate and toDate, then S/He is
// not interested in DateTime filter
return true;
}
// Now do a range check
if (!(loggedDateTime.before(fromDateTime) ||
loggedDateTime.after(toDateTime))) {
return true;
}
return false;
| protected static javax.management.AttributeList | fetchRecordsUsingQuery(LogFile logFile, long startingRecord, boolean next, boolean forward, long requestedCount, java.util.Date fromDate, java.util.Date toDate, java.lang.String logLevel, boolean onlyLevel, java.util.List listOfModules, java.util.Properties nameValueMap)Internal method that will be called from getLogRecordsUsingQuery()
// If !next, then set to search in reverse
boolean origForward = forward;
if (next) {
startingRecord++;
forward = true;
} else {
forward = false;
}
// Setup forward/reverse stuff
int inc = 1;
int start = 0; // depends on length of results (for reverse)
int end = -1; // depends on length of results (for forward)
long searchChunkIncrement = requestedCount;
if (!forward) {
inc = -1;
// Move back to find records before the startingRecord
// -1 because we still want to see the starting record (only if in
// "next" mode)
startingRecord -=
((next) ? (searchChunkIncrement-1) : (searchChunkIncrement));
if (startingRecord < 0) {
// Don't go past the original startingRecord
searchChunkIncrement += startingRecord;
startingRecord = 0;
}
}
// Make sure the module names are correct
//updateModuleList(listOfModules);
// Keep pulling records to search through until we get enough matches
List results = new ArrayList();
List records = null;
LogFile.LogEntry entry = null;
while (results.size() < requestedCount) {
// The following will always return unfiltered forward records
records = logFile.getLogEntries(
startingRecord, searchChunkIncrement);
if (records == null) {
break;
}
// Determine end/start
if (forward) {
end = records.size();
} else {
start = records.size()-1;
}
// Loop through the records, filtering and storing the matches
for (int count=start;
(count != end) && (results.size() < requestedCount);
count += inc)
{
entry = (LogFile.LogEntry)records.get(count);
if (allChecks(entry, fromDate, toDate, logLevel, onlyLevel,
listOfModules, nameValueMap)) {
results.add(entry);
}
}
// Update startingRecord / searchChunkIncrement & check for finish
if (forward) {
// If the record size is smaller than requested, then there
// are no more records.
if (records.size() < searchChunkIncrement) {
break;
}
// Get starting record BEFORE updating searchChunkIncrement to
// skip all the records we already saw
startingRecord += searchChunkIncrement*inc;
searchChunkIncrement = requestedCount-results.size();
} else {
// If we already searched from 0, then there are no more
if (startingRecord == 0) {
break;
}
// Get starting record AFTER updating searchChunkIncrement
searchChunkIncrement = requestedCount-results.size();
startingRecord += searchChunkIncrement*inc;
if (startingRecord < 1) {
searchChunkIncrement += startingRecord;
startingRecord = 0;
}
}
}
// Deal with previous&forward or next&reverse
if (next ^ origForward) {
List reversedResults = new ArrayList();
// Reverse the results
for (int count=results.size()-1; count>-1; count--) {
reversedResults.add(results.get(count));
}
results = reversedResults;
}
// Return the matches. If this is less than requested, then there are
// no more.
return convertResultsToTheStructure( results );
| public static LogFile | getLogFile()This provides access to the LogFile object.
return _logFile;
| public static LogFile | getLogFile(java.lang.String fileName)This fetches or updates logFileCache entries.
_REVISIT_: We may want to limit the entries here as each logFile
takes up so much of memory to maintain indexes
// No need to check for null or zero length string as the
// test is already done before.
String logFileName = fileName.trim( );
LogFile logFile = (LogFile) logFileCache.get( fileName );
String parent = null;
if( logFile == null ) {
try {
// First check if the fileName provided is an absolute filename
// if yes, then we don't have to construct the parent element
// path with the parent.
if( new File( fileName ).exists( ) ) {
logFile = new LogFile( fileName );
logFileCache.put( fileName, logFile );
return logFile;
}
// If the absolute path is not provided, the burden of
// constructing the parent path falls on us. We try
// using the default parent path used for the current LogFile.
if( getLogFile() != null ) {
parent = new File(
getLogFile().getLogFileName() ).getParent( );
} else {
String[] logPath = { System.getProperty(
SystemPropertyConstants.INSTANCE_ROOT_PROPERTY ),
"logs"};
parent = StringUtils.makeFilePath( logPath, false );
}
} catch( Exception e ) {
System.err.println( "Exception " + e +
"thrown in Logviewer backend" );
}
if( parent != null ) {
// Just use the parent directory from the other server.log
// file.
String[] logFileNameParts = { parent, logFileName };
logFileName = StringUtils.makeFilePath(
logFileNameParts , false );
}
logFile = new LogFile( logFileName );
logFileCache.put( fileName, logFile );
}
return logFile;
| public static javax.management.AttributeList | getLogRecordsUsingQuery(java.lang.String logFileName, java.lang.Long fromRecord, java.lang.Boolean next, java.lang.Boolean forward, java.lang.Integer requestedCount, java.util.Date fromDate, java.util.Date toDate, java.lang.String logLevel, java.lang.Boolean onlyLevel, java.util.List listOfModules, java.util.Properties nameValueMap)The public method that Log Viewer Front End will be calling on.
The query will be run on records starting from the fromRecord.
If any of the elements for the query is null, then that element will
not be used for the query. If the user is interested in viewing only
records whose Log Level is SEVERE and WARNING, then the query would
look like:
fromDate = null, toDate = null, logLevel = WARNING, onlyLevel = false,
listOfModules = null, nameValueMap = null.
LogFile logFile = null;
if( ( logFileName != null )
&&( logFileName.length() != 0 ) )
{
logFile = getLogFile( logFileName );
} else {
logFile = getLogFile( );
}
boolean forwd = (forward == null) ? true : forward.booleanValue();
boolean nxt = (next == null) ? true : next.booleanValue();
long reqCount = (requestedCount == null) ?
logFile.getIndexSize() : requestedCount.intValue();
long startingRecord;
if (fromRecord == null) {
// In this case next/previous (before/after) don't mean much since
// we don't have a reference record number. So set before/after
// according to the direction.
nxt = forwd;
// We +1 for reverse so that we see the very end of the file (the
// query will not go past the "startingRecord", so we have to put
// it after the end of the file)
startingRecord = forwd ?
(-1) :((logFile.getLastIndexNumber()+1)*logFile.getIndexSize());
} else {
startingRecord = fromRecord.longValue();
if (startingRecord < -1) {
throw new IllegalArgumentException(
"fromRecord must be greater than 0!");
}
}
// TO DO: If the fromRecord count is zero and the fromDate entry is
// non-null, then the system should take advantage of file Indexing.
// It should move the file position to the marker where the DateTime
// query matches.
try {
return fetchRecordsUsingQuery(logFile, startingRecord, nxt, forwd,
reqCount, fromDate, toDate, logLevel,
onlyLevel.booleanValue(), listOfModules, nameValueMap);
} catch (Exception ex) {
System.err.println( "Exception in fetchRecordsUsingQuer.." + ex );
// FIXME: Handle this correctly...
throw new RuntimeException(ex);
}
| protected static boolean | levelCheck(java.lang.String loggedLevel, java.lang.String queryLevelIn, boolean isOnlyLevelFlag)
// If queryLevel is null, that means user is not interested in
// running the query on the Log Level field.
if (queryLevelIn == null) {
return true;
}
final String queryLevel = queryLevelIn.trim();
if (isOnlyLevelFlag) {
// This means the user is interested in seeing log messages whose
// log level is equal to what is specified
if (loggedLevel.equals(queryLevel)) {
return true;
}
} else {
// FIXME: rework this...
for (int idx=0; idx<LOG_LEVELS.length; idx++) {
if (loggedLevel.equals(LOG_LEVELS[idx])) {
return true;
}
if (LOG_LEVELS[idx].equals(queryLevel)) {
break;
}
}
}
return false;
| protected static boolean | moduleCheck(java.lang.String loggerName, java.util.List modules)
if ((modules == null) || (modules.size() == 0)) {
return true;
}
Iterator iterator = modules.iterator();
while (iterator.hasNext()) {
if (loggerName.startsWith((String)iterator.next())) {
return true;
}
}
return false;
| protected static boolean | nameValueCheck(java.lang.String loggedNameValuePairs, java.util.Properties queriedNameValueMap)
if (queriedNameValueMap == null) {
return true;
}
if (loggedNameValuePairs == null) {
// We didn't match the name values...
return false;
}
StringTokenizer nvListTokenizer =
new StringTokenizer( loggedNameValuePairs, NV_SEPARATOR );
while( nvListTokenizer.hasMoreTokens( ) ) {
String nameandvalue = nvListTokenizer.nextToken( );
StringTokenizer nvToken = new StringTokenizer( nameandvalue, "=" );
if (nvToken.countTokens() < 2)
continue;
String loggedName = nvToken.nextToken( );
String loggedValue = nvToken.nextToken( );
// Reset the iterator to start from the first entry AGAIN
// FIXME: Is there any other cleaner way to reset the iterator
// position to zero than recreating a new iterator everytime
Iterator queriedNameValueMapIterator =
queriedNameValueMap.entrySet().iterator( );
while( queriedNameValueMapIterator.hasNext( ) ) {
Map.Entry entry =
(Map.Entry) queriedNameValueMapIterator.next();
if(entry.getKey().equals( loggedName ) ) {
Object value = entry.getValue( );
// We have a key with multiple values to match.
// This will happen if the match condition is like
// _ThreadID=10 or _ThreadID=11
// _REVISIT_: There is an opportunity to improve performance
// for this search.
Iterator iterator = ((java.util.List) value).iterator( );
while( iterator.hasNext( ) ) {
if( ((String)iterator.next()).equals(
loggedValue ) )
{
return true;
}
}
}
}
}
return false;
| public static synchronized void | setLogFile(LogFile logFile)
_logFile=logFile;
| protected static void | updateModuleList(java.util.List listOfModules)Utility method to replace the Module Names with their actual logger
names.
if (listOfModules == null) {
return;
}
Iterator iterator = listOfModules.iterator();
int index = 0;
while (iterator.hasNext()) {
String[] loggerNames = ModuleToLoggerNameMapper.getLoggerNames(
((String)iterator.next()).trim());
if (loggerNames!=null && loggerNames.length>0) {
listOfModules.set(index, loggerNames[0]); //todo: support multiple loggers per module
}
index++;
}
|
|