You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@locus.apache.org on 2000/11/30 02:55:33 UTC

cvs commit: jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/valves AccessLogValve.java

remm        00/11/29 17:55:32

  Modified:    catalina/src/share/org/apache/catalina/valves
                        AccessLogValve.java
  Log:
  - Optimized AccessLogValve.
    Contributed by Jason Brittain (jason@olliance.com).
  
  Revision  Changes    Path
  1.2       +218 -45   jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/valves/AccessLogValve.java
  
  Index: AccessLogValve.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/valves/AccessLogValve.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AccessLogValve.java	2000/08/11 17:03:15	1.1
  +++ AccessLogValve.java	2000/11/30 01:55:31	1.2
  @@ -65,7 +65,9 @@
   import java.io.FileWriter;
   import java.io.IOException;
   import java.io.PrintWriter;
  -import java.sql.Timestamp;
  +import java.text.SimpleDateFormat;
  +import java.util.Date;
  +import java.util.TimeZone;
   import javax.servlet.ServletException;
   import javax.servlet.ServletRequest;
   import javax.servlet.ServletResponse;
  @@ -122,7 +124,8 @@
    * can be implemented.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.1 $ $Date: 2000/08/11 17:03:15 $
  + * @author Jason Brittain
  + * @version $Revision: 1.2 $ $Date: 2000/11/30 01:55:31 $
    */
   
   public final class AccessLogValve
  @@ -140,6 +143,7 @@
   
   	super();
   	setPattern("common");
  +        
   
       }
   
  @@ -151,7 +155,7 @@
        * The as-of date for the currently open log file, or a zero-length
        * string if there is no open log file.
        */
  -    private String date = "";
  +    private String dateStamp = "";
   
   
       /**
  @@ -182,6 +186,14 @@
   
   
       /**
  +     * If the current log pattern is the same as the common access log
  +     * format pattern, then we'll set this variable to true and log in
  +     * a more optimal and hard-coded way.
  +     */
  +    private boolean common = false;
  +
  +
  +    /**
        * The pattern used to format our access log lines.
        */
       private String pattern = null;
  @@ -218,6 +230,60 @@
       private PrintWriter writer = null;
   
   
  +    /**
  +     * A date formatter to format a Date into a date in the format
  +     * "yyyy-MM-dd".
  +     */
  +    private SimpleDateFormat dateFormatter = null;
  +
  +
  +    /**
  +     * A date formatter to format Dates into a day string in the format
  +     * "dd".
  +     */
  +    private SimpleDateFormat dayFormatter = null;
  +
  +
  +    /**
  +     * A date formatter to format a Date into a month string in the format
  +     * "MM".
  +     */
  +    private SimpleDateFormat monthFormatter = null;
  +
  +
  +    /**
  +     * A date formatter to format a Date into a year string in the format
  +     * "yyyy".
  +     */
  +    private SimpleDateFormat yearFormatter = null;
  +
  +
  +    /**
  +     * A date formatter to format a Date into a time in the format
  +     * "kk:mm:ss" (kk is a 24-hour representation of the hour).
  +     */
  +    private SimpleDateFormat timeFormatter = null;
  +
  +
  +    /**
  +     * The time zone relative to GMT.
  +     */
  +    private String timeZone = null;
  +
  +
  +    /**
  +     * The system time when we last updated the Date that this valve
  +     * uses for log lines.
  +     */
  +    private Date currentDate = null;
  +
  +
  +    /**
  +     * When formatting log lines, we often use strings like this one (" ").
  +     */
  +    private String space = " ";
  +
  +
       // ------------------------------------------------------------- Properties
   
   
  @@ -276,6 +342,11 @@
   	    pattern = Constants.AccessLog.COMMON_PATTERN;
   	this.pattern = pattern;
   
  +        if (this.pattern.equals(Constants.AccessLog.COMMON_PATTERN))
  +            common = true;
  +        else
  +            common = false;
  +
       }
   
   
  @@ -342,21 +413,77 @@
   	// Pass this request on to the next valve in our pipeline
   	invokeNext(request, response);
   
  -	// Generate a message based on the defined pattern
  -	StringBuffer result = new StringBuffer();
  -	boolean replace = false;
  -	for (int i = 0; i < pattern.length(); i++) {
  -	    char ch = pattern.charAt(i);
  -	    if (replace) {
  -		result.append(replace(ch, request, response));
  -		replace = false;
  -	    } else if (ch == '%')
  -		replace = true;
  -	    else
  -		result.append(ch);
  -	}
  -	log(result.toString());
  +        Date date = getDate();
  +        StringBuffer result = new StringBuffer();
   
  +        // Check to see if we should log using the "common" access log pattern
  +        if (common) {
  +            String value = null;
  +
  +            ServletRequest req = request.getRequest();
  +            HttpServletRequest hreq = null;
  +            if (req instanceof HttpServletRequest)
  +                hreq = (HttpServletRequest) req;
  +
  +            result.append(req.getRemoteHost());
  +
  +            result.append(" - ");
  +            
  +            if (hreq != null)
  +                value = hreq.getRemoteUser();
  +            if (value == null)
  +                result.append("- ");
  +            else {
  +                result.append(value);
  +                result.append(space);
  +            }
  +
  +            result.append("[");
  +            result.append(dayFormatter.format(date));            // Day
  +            result.append('/');
  +            result.append(lookup(monthFormatter.format(date))); // Month
  +            result.append('/');
  +            result.append(yearFormatter.format(date));            // Year
  +            result.append(':');
  +            result.append(timeFormatter.format(date));        // Time
  +            result.append(space);
  +            result.append(timeZone);                            // Time Zone
  +            result.append("] \"");
  +
  +            result.append(hreq.getMethod());
  +            result.append(space);
  +            result.append(hreq.getRequestURI());
  +            result.append(space);
  +            result.append(hreq.getProtocol());
  +            result.append("\" ");
  +
  +            result.append(((HttpResponse) response).getStatus());
  +
  +            result.append(space);
  +
  +            int length = response.getContentCount();
  +            if (length <= 0)
  +                value = "-";
  +            else
  +                value = "" + length;
  +            result.append(value);
  +        } else {
  +            // Generate a message based on the defined pattern
  +            boolean replace = false;
  +            for (int i = 0; i < pattern.length(); i++) {
  +                char ch = pattern.charAt(i);
  +                if (replace) {
  +                    result.append(replace(ch, date, request, response));
  +                    replace = false;
  +                } else if (ch == '%') {
  +                    replace = true;
  +                } else {
  +                    result.append(ch);
  +                }
  +            }
  +        }
  +        log(result.toString(), date);
  +        
       }
   
   
  @@ -373,7 +500,7 @@
   	writer.flush();
   	writer.close();
   	writer = null;
  -	date = "";
  +	dateStamp = "";
   
       }
   
  @@ -383,26 +510,32 @@
        * has changed since the previous log call.
        *
        * @param message Message to be logged
  +     * @param date the current Date object (so this method doesn't need to
  +     *        create a new one)
        */
  -    public void log(String message) {
  +    public void log(String message, Date date) {
   
  -	// Check for a change of date
  -	Timestamp ts = new Timestamp(System.currentTimeMillis());
  -	String tsString = ts.toString().substring(0, 19);
  -	String tsDate = tsString.substring(0, 10);
  -
  -	// If the date has changed, switch log files
  -	if (!date.equals(tsDate)) {
  -	    synchronized (this) {
  -		close();
  -		date = tsDate;
  -		open();
  -	    }
  -	}
  +        // Only do a logfile switch check once a second, max.
  +        if ((System.currentTimeMillis() - currentDate.getTime()) > 1000) {
  +            // We need a new currentDate
  +            currentDate = new Date();
  +
  +            // Check for a change of date
  +            String tsDate = dateFormatter.format(currentDate);
  +
  +            // If the date has changed, switch log files
  +            if (!dateStamp.equals(tsDate)) {
  +                synchronized (this) {
  +                    close();
  +                    dateStamp = tsDate;
  +                    open();
  +                }
  +            }
  +        }
   
   	// Log this message
   	if (writer != null) {
  -	    writer.println(message);
  +            writer.println(message);
   	}
   
       }
  @@ -428,7 +561,7 @@
   
   
       /**
  -     * Open the new log file for the date specified by <code>date</code>.
  +     * Open the new log file for the date specified by <code>dateStamp</code>.
        */
       private void open() {
   
  @@ -442,7 +575,7 @@
   	// Open the current log file
   	try {
   	    String pathname = dir.getAbsolutePath() + File.separator +
  -		prefix + date + suffix;
  +		prefix + dateStamp + suffix;
   	    writer = new PrintWriter(new FileWriter(pathname, true), true);
   	} catch (IOException e) {
   	    writer = null;
  @@ -455,10 +588,13 @@
        * Return the replacement text for the specified pattern character.
        *
        * @param pattern Pattern character identifying the desired text
  +     * @param date the current Date so that this method doesn't need to
  +     *        create one
        * @param request Request being processed
        * @param response Response being processed
        */
  -    private String replace(char pattern, Request request, Response response) {
  +    private String replace(char pattern, Date date, Request request, 
  +                           Response response) {
   
   	String value = null;
   
  @@ -506,8 +642,8 @@
   		value = "";
   	} else if (pattern == 'r') {
   	    if (hreq != null)
  -		value = hreq.getMethod() + " " + hreq.getRequestURI() + " " +
  -		    hreq.getProtocol();
  +		value = hreq.getMethod() + space + hreq.getRequestURI() 
  +                    + space + hreq.getProtocol();
   	    else
   		value = "- - " + req.getProtocol();
   	} else if (pattern == 's') {
  @@ -516,18 +652,16 @@
   	    else
   		value = "-";
   	} else if (pattern == 't') {
  -	    String timestamp =
  -		new Timestamp(System.currentTimeMillis()).toString();
   	    StringBuffer temp = new StringBuffer("[");
  -	    temp.append(timestamp.substring(8, 10));		// Day
  +            temp.append(dayFormatter.format(date));		// Day
   	    temp.append('/');
  -	    temp.append(lookup(timestamp.substring(5, 7)));	// Month
  +	    temp.append(lookup(monthFormatter.format(date)));   // Month
   	    temp.append('/');
  -	    temp.append(timestamp.substring(0, 4));		// Year
  +	    temp.append(yearFormatter.format(date));            // Year
   	    temp.append(':');
  -	    temp.append(timestamp.substring(11, 19));		// Time
  +	    temp.append(timeFormatter.format(date));            // Time
   	    temp.append(' ');
  -	    temp.append("-0800");				// FIXME!!!
  +	    temp.append(timeZone);                              // Timezone
   	    temp.append(']');
   	    value = temp.toString();
   	} else if (pattern == 'u') {
  @@ -554,6 +688,25 @@
       }
   
   
  +    /**
  +     * This method returns a Date object that is accurate to within one
  +     * second.  If a thread calls this method to get a Date and it's been
  +     * less than 1 second since a new Date was created, this method
  +     * simply gives out the same Date again so that the system doesn't
  +     * spend time creating Date objects unnecessarily.
  +     */
  +    private Date getDate() {
  +        
  +        // Only create a new Date once per second, max.
  +        if ((System.currentTimeMillis() - currentDate.getTime()) > 1000) {
  +            currentDate = new Date();
  +        }
  +        
  +        return currentDate;
  +        
  +    }
  +
  +
       // ------------------------------------------------------ Lifecycle Methods
   
   
  @@ -599,6 +752,26 @@
   		(sm.getString("accessLogValve.alreadyStarted"));
   	lifecycle.fireLifecycleEvent(START_EVENT, null);
   	started = true;
  +
  +        // Initialize the timeZone, Date formatters, and currentDate
  +        TimeZone tz = TimeZone.getDefault();
  +        timeZone = "" + (tz.getRawOffset() / (60 * 60 * 10));
  +        if (timeZone.length() < 5)
  +            timeZone = timeZone.substring(0, 1) + "0" +
  +                timeZone.substring(1, timeZone.length());
  +        dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
  +        dateFormatter.setTimeZone(tz);
  +        dayFormatter = new SimpleDateFormat("dd");
  +        dayFormatter.setTimeZone(tz);
  +        monthFormatter = new SimpleDateFormat("MM");
  +        monthFormatter.setTimeZone(tz);
  +        yearFormatter = new SimpleDateFormat("yyyy");
  +        yearFormatter.setTimeZone(tz);
  +        timeFormatter = new SimpleDateFormat("kk:mm:ss");
  +        timeFormatter.setTimeZone(tz);
  +        currentDate = new Date();
  +
  +        open();
   
       }