FileDocCategorySizeDatePackage
UniformLogFormatter.javaAPI DocGlassfish v2 API15398Fri May 04 22:35:44 BST 2007com.sun.enterprise.server.logging

UniformLogFormatter

public class UniformLogFormatter extends Formatter
UniformLogFormatter conforms to the logging format defined by the Log Working Group in Java Webservices Org. The specified format is "[#|DATETIME|LOG_LEVEL|PRODUCT_ID|LOGGER NAME|OPTIONAL KEY VALUE PAIRS| MESSAGE|#]\n"
author
Hemanth Puttaswamy TODO: 1. Performance improvement. We can Cache the LOG_LEVEL|PRODUCT_ID strings and minimize the concatenations and revisit for more performance improvements 2. Need to use Product Name and Version based on the version string that is part of the product. 3. Stress testing 4. If there is a Map as the last element, need to scan the message to distinguish key values with the message argument.

Fields Summary
private HashMap
loggerResourceBundleTable
private LogManager
logManager
private Date
date
private static String
PRODUCTID_CONTEXTID
private static final String
PRODUCT_VERSION
private static final int
FINE_LEVEL_INT_VALUE
private static boolean
LOG_SOURCE_IN_KEY_VALUE
private static boolean
RECORD_NUMBER_IN_KEY_VALUE
private long
recordNumber
private static final String
LINE_SEPARATOR
private static final String
RECORD_BEGIN_MARKER
private static final String
RECORD_END_MARKER
private static final char
FIELD_SEPARATOR
private static final char
NVPAIR_SEPARATOR
private static final char
NV_SEPARATOR
private static final String
RFC_3339_DATE_FORMAT
private static final SimpleDateFormat
dateFormatter
Constructors Summary
public UniformLogFormatter()


       
        super( );
        loggerResourceBundleTable = new HashMap( );
        logManager = LogManager.getLogManager( );
    
Methods Summary
public java.lang.Stringformat(java.util.logging.LogRecord record)
_REVISIT_: Replace the String Array with an HashMap and do some benchmark to determine whether StringCat is faster or Hashlookup for the template is faster.

        return uniformLogFormat( record );
    
public java.lang.StringformatMessage(java.util.logging.LogRecord record)

        return uniformLogFormat( record );
    
protected voidgetNameValuePairs(java.lang.StringBuilder buf, java.util.logging.LogRecord record)
Sun One Appserver SE/EE? can override to specify their product specific key value pairs.

        
        Object[] parameters = record.getParameters();
        if ((parameters == null)  || (parameters.length == 0)) {
            return;
        }
        
        try {
            for (Object obj : parameters) {
                if (obj == null) {
                    continue;
                }
                if (obj instanceof Map) {
                    Map map = (Map) obj;
                    for (Object key : map.keySet()) {
                        buf.append(key.toString()).append(NV_SEPARATOR).
                            append(map.get(key).toString()).
                            append(NVPAIR_SEPARATOR);
                    }
                } else if (obj instanceof java.util.Collection) {
                    for (Object entry : ((Collection)obj)) {
                        buf.append(entry.toString()).append(NVPAIR_SEPARATOR);
                    }
                } else {
                    buf.append(obj.toString()).append(NVPAIR_SEPARATOR);
                }
            }
        } catch( Exception e ) {
            new ErrorManager().error( 
                "Error in extracting Name Value Pairs", e,
                ErrorManager.FORMAT_FAILURE );
        }
    
protected java.lang.StringgetProductId()
Sun One AppServer SE/EE can override to specify their product version

        return PRODUCT_VERSION;
    
private synchronized java.util.ResourceBundlegetResourceBundle(java.lang.String loggerName)

        if( loggerName == null ) {
            return null;
        }
        ResourceBundle rb = (ResourceBundle) loggerResourceBundleTable.get(
            loggerName );
 
        if( rb == null ) {
            rb = logManager.getLogger( loggerName ).getResourceBundle( );
            loggerResourceBundleTable.put( loggerName, rb );
        }
        return rb;
    
private voiduniformLogFormat(java.lang.StringBuilder buf, com.sun.enterprise.admin.monitor.callflow.ThreadLocalData tld, java.util.logging.Level level)

        
        if (level.equals(Level.INFO) || level.equals(Level.CONFIG)) {
            
            if (tld.getApplicationName() != null) {
                buf.append("_ApplicationName").append(NV_SEPARATOR).
                        append(tld.getApplicationName()).
                        append(NVPAIR_SEPARATOR);
            }
            
        } else {
            
            if (tld.getRequestId() != null) {
                buf.append("_RequestID").append(NV_SEPARATOR).
                        append(tld.getRequestId()).append(NVPAIR_SEPARATOR);
            }
            
            if (tld.getApplicationName() != null) {
                buf.append("_ApplicationName").append(NV_SEPARATOR).
                        append(tld.getApplicationName()).
                        append(NVPAIR_SEPARATOR);
            }
            
            if (tld.getModuleName() != null) {
                buf.append("_ModuleName").append(NV_SEPARATOR).
                        append(tld.getModuleName()).append(NVPAIR_SEPARATOR);
            }
            
            if (tld.getComponentName() != null) {
                buf.append("_ComponentName").append(NV_SEPARATOR).
                        append(tld.getComponentName()).append(NVPAIR_SEPARATOR);
            }
            
            if (tld.getComponentType() != null) {
                buf.append("_ComponentType").append(NV_SEPARATOR).
                        append(tld.getComponentType()).append(NVPAIR_SEPARATOR);
            }
            
            if (tld.getMethodName() != null) {
                buf.append("_MethodName").append(NV_SEPARATOR).
                        append(tld.getMethodName()).append(NVPAIR_SEPARATOR);
            }
            
            if (tld.getTransactionId() != null) {
                buf.append("_TransactionId").append(NV_SEPARATOR).
                        append(tld.getTransactionId()).append(NVPAIR_SEPARATOR);
            }
            
            if (tld.getSecurityId() != null) {
                buf.append("_CallerId").append(NV_SEPARATOR).
                        append(tld.getSecurityId()).append(NVPAIR_SEPARATOR);
            }
        }
    
private java.lang.StringuniformLogFormat(java.util.logging.LogRecord record)
Note: This method is not synchronized, we are assuming that the synchronization will happen at the Log Handler.publish( ) method.

        
        try {   
            
            StringBuilder recordBuffer = new StringBuilder(RECORD_BEGIN_MARKER);
            // The following operations are to format the date and time in a
            // human readable  format.
            // _REVISIT_: Use HiResolution timer to analyze the number of
            // Microseconds spent on formatting date object
            date.setTime(record.getMillis());
            recordBuffer.append(dateFormatter.format(date));
            recordBuffer.append(FIELD_SEPARATOR);

            recordBuffer.append(record.getLevel()).append(FIELD_SEPARATOR);
            recordBuffer.append(getProductId()).append(FIELD_SEPARATOR);
            recordBuffer.append(record.getLoggerName()).append(FIELD_SEPARATOR);
            
            recordBuffer.append("_ThreadID").append(NV_SEPARATOR);
            recordBuffer.append(record.getThreadID()).append(NVPAIR_SEPARATOR);
            
            recordBuffer.append("_ThreadName").append(NV_SEPARATOR);
            recordBuffer.append(Thread.currentThread().getName());
            recordBuffer.append(NVPAIR_SEPARATOR);
            
            // See 6316018. ClassName and MethodName information should be
            // included for FINER and FINEST log levels.
            Level level = record.getLevel();
            if (LOG_SOURCE_IN_KEY_VALUE ||
                    (level.intValue() <= Level.FINE.intValue())) {
                recordBuffer.append("ClassName").append(NV_SEPARATOR);
                recordBuffer.append(record.getSourceClassName());
                recordBuffer.append(NVPAIR_SEPARATOR);
                recordBuffer.append("MethodName").append(NV_SEPARATOR); 
                recordBuffer.append(record.getSourceMethodName());
                recordBuffer.append(NVPAIR_SEPARATOR);
            }

            if (RECORD_NUMBER_IN_KEY_VALUE) {
                recordBuffer.append("RecordNumber").append(NV_SEPARATOR);
                recordBuffer.append(recordNumber++).append(NVPAIR_SEPARATOR);
            }
            
            getNameValuePairs(recordBuffer, record);
            
            Agent callFlowAgent = Switch.getSwitch().getCallFlowAgent();
            if (callFlowAgent != null) {
                // Since it is possible that a log call may happen before
                // the Switch class's callflow agent is initialized during
                // server startup, we perform the null check above.
                ThreadLocalData tld = callFlowAgent.getThreadLocalData();
                if (tld != null) {
                    uniformLogFormat(recordBuffer, tld, level);
                }
            }
            
            recordBuffer.append(FIELD_SEPARATOR);
            
            String logMessage = record.getMessage();
	    if (logMessage == null) {
	        logMessage = "The log message is null.";
	    }
            if( logMessage.indexOf("{0}") >= 0 ) {
                // If we find {0} or {1} etc., in the message, then it's most
                // likely finer level messages for Method Entry, Exit etc.,
                logMessage = java.text.MessageFormat.format(
                    logMessage, record.getParameters() );
            } else { 
                ResourceBundle rb = getResourceBundle(record.getLoggerName( ) );
                if( rb != null ) {
                    try {
                        logMessage = MessageFormat.format(
                            rb.getString( logMessage ),
                            record.getParameters( ) );
                    } catch ( java.util.MissingResourceException e ) {
                        // If we don't find an entry, then we are covered 
                        // because the logMessage is intialized already
                    }
                } 
            }
            recordBuffer.append(logMessage);

            if (record.getThrown() != null) {
                recordBuffer.append(LINE_SEPARATOR);
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                record.getThrown().printStackTrace(pw);
                pw.close();
                recordBuffer.append(sw.toString());
            }
            
            recordBuffer.append(RECORD_END_MARKER);
            return recordBuffer.toString();
            
        } catch( Exception ex ) {
            new ErrorManager().error( 
                "Error in formatting Logrecord", ex,
                ErrorManager.FORMAT_FAILURE );
            // We've already notified the exception, the following
            // return is to keep javac happy
            return new String("");
        }