remm        00/11/29 17:55:32

  Modified:    catalina/src/share/org/apache/catalina/valves
                        AccessLogValve.java
  Log:
  - Optimized AccessLogValve.
    Contributed by Jason Brittain ([EMAIL PROTECTED]).
  
  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();
   
       }
   
  
  
  

Reply via email to