com.bristle.javalib.log
Class LoggerUtil

java.lang.Object
  extended by com.bristle.javalib.log.LoggerUtil

public class LoggerUtil
extends Object

This class supports a useful convention for logging via the Logger class, and makes the logging calls simpler, shorter, and less obtrusive.

Usage:
   - See the Logger documentation for the typical appearance of 
     a log file line without this class.  This class enhances that format.
   - When used as described below, this class generates log file lines  
     that:
         1)  Have a  field that contains a user name, optional 
             location and optional user agent, formatted as: 
                   username
                   username@location
                   anonymous
                   anonymous@location
                   username/useragent
                   username@location/useragent
                   anonymous/useragent
                   anonymous@location/useragent
             The caller can specify:
             - The username, which defaults to "anonymous".
             - The location, which has no default but is typically specified 
               as an IP address, host name, domain name, fully qualified 
               hostname, or any other string.
             - The user agent, which has no default but is typically specified
               as a short identifier of a Web browser, operating system, or 
               other user agent, or any other string.
             Examples:   
                   fred
                   fred@127.0.0.1
                   fred@neptune
                   fred@bristle.com
                   fred@neptune.bristle.com
                   fred@"The Internet Cafe"
                   fred@The Internet Cafe  (A way to create the effect of new 
                                            space-separated fields in the 
                                            logger following the username and
                                            location.)  
                   fred/FF2
                   fred@127.0.0.1/WinXP
                   fred@neptune/IE6WinXP
                   fred@bristle.com/FF2Linux
                   fred@neptune.bristle.com/Moz1
                   fred@"The Internet Cafe"/[[Mozilla/5.0 (Windows; U; 
                     Windows NT 5.0; en-US; rv:1.8.0.12) Gecko/20070508 
                     Firefox/1.5.0.12]]
                                           (Makes for very long log lines.
                                            It is probably better to log all 
                                            this detail once per login session
                                            or something, not once per line.
                                            However, you can use as long a 
                                            string, with as many of your own 
                                            delimiters, as you like.) 
                   fred/RedHat More words
                                           (A way to create the effect of new 
                                            space-separated fields in the 
                                            logger following the username
                                            and user agent.)  
                   fred@neptune/FF2 More words
                                           (A way to create the effect of new 
                                            space-separated fields in the 
                                            logger following the username,
                                            location, and user agent.)  
                   anonymous
                   anonymous@127.0.0.1
                   anonymous@neptune
                   etc...
             Note: See the HttpUtil.getHttpUserAgentAbbrev() method, as a way 
                   to produce short unique strings from the HTTP user-agent 
                   header of common Web browsers.      
         2)  Have a structured  field on each line to produce a nested 
             effect like: 
                   BEGIN ContextBO.login()
                   . BEGIN ContextBO.hasRight(LOGIN)
                   . . BEGIN getResultSet()
                   . . END   getResultSet() : 5
                   . END   ContextBO.hasRight(LOGIN) : 5
                   END   ContextBO.login() : 6
                   BEGIN ProductListBO.load()
                   . BEGIN ContextBO.hasRight(VIEW_PRODUCT)
                   . . BEGIN getResultSet()
                   . . END   getResultSet() : 24
                   . END   ContextBO.hasRight(VIEW_PRODUCT) : 25
                   . BEGIN Getting product data from the database.
                   . . BEGIN getResultSet()
                   . . END   getResultSet() : 12
                   . END   Getting product data from the database. : 13
                   END   ProductListBO.load() : 40
             where:
             - The numbers following the colons (5, 6, 24, etc.) on lines
               starting with "END" are the number of milliseconds since the
               corresponding "BEGIN".

   - The typical scenario for using this class is:
       LoggerUtil loggerUtil = new LoggerUtil
           (safelyWithoutThrowingAnyExceptionGetOrCreateLoggerSomehow());
       try
       {
           // Initialize the LoggerUtil, and log the beginning of an operation
           // in either one step:
           loggerUtil.logBegin
               (intLogLevel
               ,ObjUtil.getShortClassName(this) + ".methodName(params...)"
               ,getUsernameOrNullFromSomewhere()
               ,getClientIPAddressOrNullFromSomewhere()
               ,getUserAgentOrNullFromSomewhere()
               );
           // or two steps:
           loggerUtil.init
               (intLogLevel
               ,getUsernameOrNullFromSomewhere()
               ,getClientIPAddressOrNullFromSomewhere()
               ,getUserAgentOrNullFromSomewhere()
               );
           loggerUtil.logBegin
               (ObjUtil.getShortClassName(this) + ".methodName(params...)");

           // Log additional messages for the operation.
           if (userAccessIsDeniedForSomeReason())
           {
               loggerUtil.logDenied("dummy reason");
               return; 
           } 
           doSomething();
           loggerUtil.log(intLogLevel + 1, "Log this more detailed message.");
           doSomethingElse();
           loggerUtil.log(intLogLevel + 2, "Log this even more detailed message.");
           if (somethingFailedAndWillBeRetried())
           {
               loggerUtil.logRetry("This operation failed and will be retried...");
           } 
       }
       catch (Throwable exception)
       {
           // Call one of the following to log an error:
           loggerUtil.logError(strMessage, exception);
           loggerUtil.logError(strMessage);
           loggerUtil.logError(exception);
           
           // Or set the Aborted flag to tell logEnd() to log an abnormal
           // end, and re-throw the exception to be handled by the caller.
           loggerUtil.setAborted(true);
           throw exception;
       }
       finally
       {
           // Log the end of the operation.
           loggerUtil.logEnd();
       }

   - You can also initialize one LoggerUtil from another LoggerUtil, in which
     case it logs at a level one greater than the specified LoggerUtil.  
     This is useful for logging at nested levels of detail without having to 
     keep track of the levels.  For example, your caller can pass you its
     LoggerUtil, and you can log to the same Logger at one nesting level 
     deeper:
       LoggerUtil loggerUtil = new LoggerUtil(callersLoggerUtil); 
       try
       {
           loggerUtil.logBegin
               (ObjUtil.getShortClassName(this) + ".methodName(params...)");
       ... etc.  (Same as previous example)
     Note: Be sure to never use the same LoggerUtil instance for multiple 
           concurrent or nested operations (including subroutine calls, 
           , and concurrent multi-threaded operations.  Calling 
           logBegin() again before calling logEnd() overwrites the current 
           operation name and start time, causing the 2nd operation to be 
           logged instead of the 1st operation.  Use a separate LoggerUtil
           instance for each concurrent or nested operation.            

   - You can also use a LoggerUtil simply to access an existing Logger to get
     the BEGIN END functionality, without disturbing the username of the 
     existing Logger.  This is especially useful when the Logger's username 
     is already initialized with info not available to you.  Initialize it 
     from the Logger, and set the PreserveLoggerUsername flag before calling
     any methods that specify a username, user location, or user agent.   
     
       LoggerUtil loggerUtil = new LoggerUtil
           (safelyWithoutThrowingAnyExceptionGetOrCreateLoggerSomehow());
       try
       {
           loggerUtil.setPreserveLoggerUsername(true);
           loggerUtil.setLogLevelOfOperation(intLogLevel);
           loggerUtil.logBegin
               (ObjUtil.getShortClassName(this) + ".methodName(params...)");
       ... etc.  (Same as previous example)


Assumptions:
Effects:
Anticipated Changes:
Notes:
Implementation Notes:
Portability Issues:
Revision History:
   $Log$

See Also:
Logger

Nested Class Summary
static class LoggerUtil.Tester
          Each class contains a Tester inner class with a main() for easier unit testing.
 
Constructor Summary
LoggerUtil(Logger logger)
          Constructor.
LoggerUtil(LoggerUtil loggerUtil)
          Constructor.
 
Method Summary
 boolean getAborted()
          Get the aborted flag.
 Logger getLogger()
          Get the Logger.
 int getLogLevelOfOperation()
          Get the log level of the current operation.
 String getOperationName()
          Get the name of the current operation.
 boolean getPreserveLoggerUsername()
          Get the PreserveLoggerUsername flag.
 boolean getShowElapsedTime()
          Get the flag about whether to show elapsed time on logEnd() calls.
 String getUserAgent()
          Get the user agent.
 String getUserLocation()
          Get the user location.
 String getUsername()
          Get the username.
 void init(int intLogLevelOfOperation, String strUsername, String strUserLocation, String strUserAgent)
          Initialize the LoggerUtil with info to be used in future calls.
 void log(int intLogLevelOfMessage, String strMsg)
          Log a message.
 void log(String strMsg)
          Log a message at the log level specified in the call to logBegin().
 void logBegin(int intLogLevelOfOperation, String strOperationName, String strUsername, String strUserLocation, String strUserAgent)
          Log the beginning of an operation.
 void logBegin(LoggerUtil parentLoggerUtil, String strOperationName)
          Log the beginning of an operation, using the same user info as the specified parentLoggerUtil, and a log level one greater than it.
 void logBegin(String strOperationName)
          Log the beginning of an operation, using the info previously specified, and remembering the current operation name to use on subsequent calls to logEnd(), LogDenied(), etc.
 void logDenied(String strReason)
          Log the fact that a request was denied, and optionally the reason.
 void logEnd()
          Log the end of an operation.
 void logError(String strMsg)
          Log an error.
 void logError(String strMsg, Throwable exception)
          Log an error.
 void logError(Throwable exception)
          Log an error.
 void logNested(String strMsg)
          Log a message at one more than the log level of the current operation.
 void logRetry(String strMsg)
          Log the fact that something failed and will be retried.
 void setAborted(boolean blnAborted)
          Set the aborted flag.
 void setLogger(Logger logger)
          Set the Logger.
 void setLoggersUserInfoString()
          Set the Logger to impersonate the previously specified user, location, and user agent, rather than logging all entries as the current username logged into the computer, which may be a Web Server.
 void setLogLevelOfOperation(int intLogLevelOfOperation)
          Set the log level of the current operation.
 void setOperationName(String strOperationName)
          Set the name of the current operation.
 void setPreserveLoggerUsername(boolean blnPreserveLoggerUsername)
          Set the PreserveLoggerUsername flag.
 void setShowElapsedTime(boolean blnVal)
          Set the flag about whether to show elapsed time on logEnd() calls.
 void setUserAgent(String strUserAgent)
          Set the user agent.
 void setUserLocation(String strUserLocation)
          Set the user location.
 void setUsername(String strUsername)
          Set the username.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

LoggerUtil

public LoggerUtil(Logger logger)
Constructor.

Parameters:
logger - The Logger to be used for logging.

LoggerUtil

public LoggerUtil(LoggerUtil loggerUtil)
Constructor.

Parameters:
loggerUtil - A LoggerUtil to copy from, but using a log level that is greater by 1. Note: The information about the current operation (name, start time, aborted) is not copied.
Method Detail

init

public void init(int intLogLevelOfOperation,
                 String strUsername,
                 String strUserLocation,
                 String strUserAgent)
Initialize the LoggerUtil with info to be used in future calls.

Parameters:
intLogLevelOfOperation - Log level for future operations. It is compared with the current log level of the logger to decide whether to actually log those operations.
strUsername - Name of user, or null to use "anonymous".
strUserLocation - Location (typically IP Address or hostname), or null to display no location and no "@" sign.
strUserAgent - User agent (typically a value like "FF2", "IE6", etc, often generated by HttpUtil.getHttpUserAgentAbbrev()), or null to display no user agent and no "/".

setLoggersUserInfoString

public void setLoggersUserInfoString()
Set the Logger to impersonate the previously specified user, location, and user agent, rather than logging all entries as the current username logged into the computer, which may be a Web Server. Log the user as one of: username@location/useragent anonymous@location/useragent username/useragent anonymous/useragent username@location anonymous@location username anonymous depending on whether the specified username, location and/or user agent are null. See the "Usage" section of this class for examples.


logBegin

public void logBegin(String strOperationName)
Log the beginning of an operation, using the info previously specified, and remembering the current operation name to use on subsequent calls to logEnd(), LogDenied(), etc.

Parameters:
strOperationName - Name of operation being logged

logBegin

public void logBegin(int intLogLevelOfOperation,
                     String strOperationName,
                     String strUsername,
                     String strUserLocation,
                     String strUserAgent)
Log the beginning of an operation. Note: This is a convenience method that is identical to calling init() followed by logBegin(String).

Parameters:
intLogLevelOfOperation - Log level for this operation. It is compared with the current log level of the logger to decide whether to actually log this operation.
strOperationName - Name of operation being logged
strUsername - Name of user, or null to use "anonymous".
strUserLocation - Location (typically IP Address or hostname), or null to display no location and no "@" sign.
strUserAgent - User agent (typically a value like "FF2", "IE6", etc, often generated by HttpUtil.getHttpUserAgentAbbrev()), or null to display no user agent and no "/".

logBegin

public void logBegin(LoggerUtil parentLoggerUtil,
                     String strOperationName)
Log the beginning of an operation, using the same user info as the specified parentLoggerUtil, and a log level one greater than it. The idea is that this LoggerUtil would log lines that are nested inside the BEGIN END pair of those logged by parentLoggerUtil.

Parameters:
parentLoggerUtil - The parent LoggerUtil
strOperationName - Name of operation being logged

logDenied

public void logDenied(String strReason)
Log the fact that a request was denied, and optionally the reason.

Parameters:
strReason - String specifying reason for denial, or null.

logRetry

public void logRetry(String strMsg)
Log the fact that something failed and will be retried.

Parameters:
strMsg - Message to log

log

public void log(int intLogLevelOfMessage,
                String strMsg)
Log a message.

Parameters:
intLogLevelOfMessage - Log level for this message. It is compared with the current log level of the logger to decide whether to actually log this message.
strMsg - Message to log

log

public void log(String strMsg)
Log a message at the log level specified in the call to logBegin().

Parameters:
strMsg - Message to log

logNested

public void logNested(String strMsg)
Log a message at one more than the log level of the current operation.

Parameters:
strMsg - Message to log

logError

public void logError(String strMsg,
                     Throwable exception)
Log an error.

Parameters:
strMsg - Message to log, or null.
exception - Throwable to include in the message text, or null.

logError

public void logError(String strMsg)
Log an error.

Parameters:
strMsg - Message to log

logError

public void logError(Throwable exception)
Log an error.

Parameters:
exception - Throwable to include in the message text, or null.

logEnd

public void logEnd()
Log the end of an operation.


getLogger

public Logger getLogger()
Get the Logger.

Returns:
The Logger.

setLogger

public void setLogger(Logger logger)
Set the Logger.

Parameters:
logger - The value to set.

getLogLevelOfOperation

public int getLogLevelOfOperation()
Get the log level of the current operation.

Returns:
The log level.

setLogLevelOfOperation

public void setLogLevelOfOperation(int intLogLevelOfOperation)
Set the log level of the current operation.

Parameters:
intLogLevelOfOperation - The value to set.

getOperationName

public String getOperationName()
Get the name of the current operation.

Returns:
The name.

setOperationName

public void setOperationName(String strOperationName)
Set the name of the current operation.

Parameters:
strOperationName - The value to set.

getUsername

public String getUsername()
Get the username.

Returns:
The username.

setUsername

public void setUsername(String strUsername)
Set the username.

Parameters:
strUsername - The value to set, or null to use "anonymous".

getUserLocation

public String getUserLocation()
Get the user location.

Returns:
The user location.

setUserLocation

public void setUserLocation(String strUserLocation)
Set the user location.

Parameters:
strUserLocation - The value to set, (typically an IP Address or hostname), or null to display no location and no "@" sign.

getUserAgent

public String getUserAgent()
Get the user agent.

Returns:
The user agent.

setUserAgent

public void setUserAgent(String strUserAgent)
Set the user agent.

Parameters:
strUserAgent - The value to set (typically a value like "FF2", "IE6", etc, often generated by HttpUtil.getHttpUserAgentAbbrev()), or null to display no user agent and no "/".

getAborted

public boolean getAborted()
Get the aborted flag.

Returns:
The flag.

setAborted

public void setAborted(boolean blnAborted)
Set the aborted flag. This causes logEnd() to add " (ABORTED)" to the END line before the colon and duration. For example:
   . END   Getting product data from the database. (ABORTED) : 13
 

Parameters:
blnAborted - The value to set.

getPreserveLoggerUsername

public boolean getPreserveLoggerUsername()
Get the PreserveLoggerUsername flag.

Returns:
The flag.

setPreserveLoggerUsername

public void setPreserveLoggerUsername(boolean blnPreserveLoggerUsername)
Set the PreserveLoggerUsername flag. This causes the LoggerUtil to not set the Logger's username to the structured "username@location/agent" value. This is useful when the Logger's username is already initialized with info not available to you.

Parameters:
blnPreserveLoggerUsername - The value to set.

setShowElapsedTime

public void setShowElapsedTime(boolean blnVal)
Set the flag about whether to show elapsed time on logEnd() calls. It is useful to turn these fields off if you are planning to compare the results with a previously captured set of results, and don't really care about the elapsed time.

Parameters:
blnVal - The new value.

getShowElapsedTime

public boolean getShowElapsedTime()
Get the flag about whether to show elapsed time on logEnd() calls.

Returns:
The value of the flag.