Author: rjung
Date: Wed Nov 28 20:04:52 2012
New Revision: 1414889

URL: http://svn.apache.org/viewvc?rev=1414889&view=rev
Log:
Add new ALV attribute "renameOnRotate" (Default:false).

If set to "true", the "fileDateFormat" will not be part
of the current log file. Only at the time of log rotation
the file is renamed to the final name including the
"fileDateFormat".

This mimics the behavior e.g. of Log4J and similar frameworks,
where the active file does not have the timestamp in the file
name.

Pro: current file has stable name, all files with
     timestamp in name are old.
Con: Slightly more complex impl.

Modified:
    tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java
    tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/valves/mbeans-descriptors.xml
    tomcat/trunk/webapps/docs/config/valve.xml

Modified: tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java?rev=1414889&r1=1414888&r2=1414889&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java (original)
+++ tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java Wed Nov 28 
20:04:52 2012
@@ -208,6 +208,12 @@ public class AccessLogValve extends Valv
      */
     protected boolean rotatable = true;
 
+    /**
+     * Should we defer inclusion of the date stamp in the file
+     * name until rotate time? Default is false.
+     */
+    protected boolean renameOnRotate = false;
+
 
     /**
      * Buffered logging.
@@ -729,6 +735,26 @@ public class AccessLogValve extends Valv
 
 
     /**
+     * Should we defer inclusion of the date stamp in the file
+     * name until rotate time
+     */
+    public boolean isRenameOnRotate() {
+        return renameOnRotate;
+    }
+
+
+    /**
+     * Set the value if we should defer inclusion of the date
+     * stamp in the file name until rotate time
+     *
+     * @param renameOnRotate true if defer inclusion of date stamp
+     */
+    public void setRenameOnRotate(boolean renameOnRotate) {
+        this.renameOnRotate = renameOnRotate;
+    }
+
+
+    /**
      * Is the logging buffered
      */
     public boolean isBuffered() {
@@ -968,7 +994,7 @@ public class AccessLogValve extends Valv
 
         if (currentLogFile != null) {
             File holder = currentLogFile;
-            close();
+            close(false);
             try {
                 holder.renameTo(new File(newFileName));
             } catch (Throwable e) {
@@ -994,12 +1020,76 @@ public class AccessLogValve extends Valv
     /**
      * Close the currently open log file (if any)
      */
-    private synchronized void close() {
+    private File getLogFile(boolean useDateStamp) {
+
+        // Create the directory if necessary
+        File dir = new File(directory);
+        if (!dir.isAbsolute()) {
+            dir = new File(getContainer().getCatalinaBase(), directory);
+        }
+        if (!dir.mkdirs() && !dir.isDirectory()) {
+            log.error(sm.getString("accessLogValve.openDirFail", dir));
+        }
+
+        // Calculate the current log file name
+        File pathname;
+        if (useDateStamp) {
+            pathname = new File(dir.getAbsoluteFile(), prefix + dateStamp
+                    + suffix);
+        } else {
+            pathname = new File(dir.getAbsoluteFile(), prefix + suffix);
+        }
+        File parent = pathname.getParentFile();
+        if (!parent.mkdirs() && !parent.isDirectory()) {
+            log.error(sm.getString("accessLogValve.openDirFail", parent));
+        }
+        return pathname;
+    }
+
+    /**
+     * Move a current but rotated log file back to the unrotated
+     * one. Needed if date stamp inclusion is deferred to rotation
+     * time.
+     */
+    private void restore() {
+        File newLogFile = getLogFile(false);
+        File rotatedLogFile = getLogFile(true);
+        if (rotatedLogFile.exists() && !newLogFile.exists() &&
+            !rotatedLogFile.equals(newLogFile)) {
+            try {
+                if (!rotatedLogFile.renameTo(newLogFile)) {
+                    log.error(sm.getString("accessLogValve.renameFail", 
rotatedLogFile, newLogFile));
+                }
+            } catch (Throwable e) {
+                ExceptionUtils.handleThrowable(e);
+                log.error(sm.getString("accessLogValve.renameFail", 
rotatedLogFile, newLogFile), e);
+            }
+        }
+    }
+
+
+    /**
+     * Close the currently open log file (if any)
+     *
+     * @param rename Rename file to final name after closing
+     */
+    private synchronized void close(boolean rename) {
         if (writer == null) {
             return;
         }
         writer.flush();
         writer.close();
+        if (rename && renameOnRotate) {
+            File newLogFile = getLogFile(true);
+            try {
+                if (!currentLogFile.renameTo(newLogFile)) {
+                    log.error(sm.getString("accessLogValve.renameFail", 
currentLogFile, newLogFile));
+                }
+            } catch (Throwable e) {
+                ExceptionUtils.handleThrowable(e);
+                log.error(sm.getString("accessLogValve.renameFail", 
currentLogFile, newLogFile), e);
+            }
+        }
         writer = null;
         dateStamp = "";
         currentLogFile = null;
@@ -1027,7 +1117,7 @@ public class AccessLogValve extends Valv
 
                         // If the date has changed, switch log files
                         if (!dateStamp.equals(tsDate)) {
-                            close();
+                            close(true);
                             dateStamp = tsDate;
                             open();
                         }
@@ -1041,7 +1131,7 @@ public class AccessLogValve extends Valv
             synchronized (this) {
                 if (currentLogFile != null && !currentLogFile.exists()) {
                     try {
-                        close();
+                        close(false);
                     } catch (Throwable e) {
                         ExceptionUtils.handleThrowable(e);
                         log.info(sm.getString("accessLogValve.closeFail"), e);
@@ -1078,28 +1168,9 @@ public class AccessLogValve extends Valv
      * Open the new log file for the date specified by <code>dateStamp</code>.
      */
     protected synchronized void open() {
-        // Create the directory if necessary
-        File dir = new File(directory);
-        if (!dir.isAbsolute()) {
-            dir = new File(getContainer().getCatalinaBase(), directory);
-        }
-        if (!dir.mkdirs() && !dir.isDirectory()) {
-            log.error(sm.getString("accessLogValve.openDirFail", dir));
-        }
-
         // Open the current log file
-        File pathname;
         // If no rotate - no need for dateStamp in fileName
-        if (rotatable) {
-            pathname = new File(dir.getAbsoluteFile(), prefix + dateStamp
-                    + suffix);
-        } else {
-            pathname = new File(dir.getAbsoluteFile(), prefix + suffix);
-        }
-        File parent = pathname.getParentFile();
-        if (!parent.mkdirs() && !parent.isDirectory()) {
-            log.error(sm.getString("accessLogValve.openDirFail", parent));
-        }
+        File pathname = getLogFile(rotatable && !renameOnRotate);
 
         Charset charset = null;
         if (encoding != null) {
@@ -1222,6 +1293,9 @@ public class AccessLogValve extends Valv
         fileDateFormatter = new SimpleDateFormat(format, Locale.US);
         fileDateFormatter.setTimeZone(timezone);
         dateStamp = fileDateFormatter.format(new 
Date(System.currentTimeMillis()));
+        if (rotatable && renameOnRotate) {
+            restore();
+        }
         open();
 
         setState(LifecycleState.STARTING);
@@ -1239,7 +1313,7 @@ public class AccessLogValve extends Valv
     protected synchronized void stopInternal() throws LifecycleException {
 
         setState(LifecycleState.STOPPING);
-        close();
+        close(false);
     }
 
     /**

Modified: tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties?rev=1414889&r1=1414888&r2=1414889&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/valves/LocalStrings.properties Wed 
Nov 28 20:04:52 2012
@@ -22,6 +22,7 @@ accessLogValve.openFail=Failed to open a
 accessLogValve.closeFail=Failed to close access log file
 accessLogValve.openDirFail=Failed to create directory [{0}] for access logs
 accessLogValve.rotateFail=Failed to rotate access log
+accessLogValve.renameFail=Failed to rename access log from [{0}] to [{1}]
 accessLogValve.invalidLocale=Failed to set locale to [{0}]
 accessLogValve.unsupportedEncoding=Failed to set encoding to [{0}], will use 
the system default character set.
 

Modified: tomcat/trunk/java/org/apache/catalina/valves/mbeans-descriptors.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/mbeans-descriptors.xml?rev=1414889&r1=1414888&r2=1414889&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/mbeans-descriptors.xml 
(original)
+++ tomcat/trunk/java/org/apache/catalina/valves/mbeans-descriptors.xml Wed Nov 
28 20:04:52 2012
@@ -94,6 +94,11 @@
                is="true"
                type="boolean"/>
 
+    <attribute name="renameOnRotate"
+               description="Flag to defer inclusion of the date stamp in the 
log file name until rotation."
+               is="true"
+               type="boolean"/>
+
     <attribute name="stateName"
                description="The name of the LifecycleState that this component 
is currently in"
                type="java.lang.String"
@@ -252,6 +257,11 @@
                is="true"
                type="boolean"/>
 
+    <attribute name="renameOnRotate"
+               description="Flag to defer inclusion of the date stamp in the 
log file name until rotation."
+               is="true"
+               type="boolean"/>
+
     <attribute name="suffix"
                description="The suffix that is added to log file filenames"
                type="java.lang.String"/>

Modified: tomcat/trunk/webapps/docs/config/valve.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/valve.xml?rev=1414889&r1=1414888&r2=1414889&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/valve.xml (original)
+++ tomcat/trunk/webapps/docs/config/valve.xml Wed Nov 28 20:04:52 2012
@@ -180,6 +180,20 @@
         </p>
       </attribute>
 
+      <attribute name="renameOnRotate" required="false">
+        <p>By default for a rotatable log the active access log file name
+           will contain the current timestamp in <code>fileDateFormat</code>.
+           During rotation the file is closed and a new file with the next
+           timestamp in the name is created and used. When setting
+           <code>renameOnRotate</code> to <code>true</code>, the timestamp
+           is no longer part of the active log file name. Only during rotation
+           the file is closed and then renamed to include the timestamp.
+           This is similar to the behavior of most log frameworks when
+           doing time based rotation.
+           Default value: <code>false</code>
+        </p>
+      </attribute>
+
       <attribute name="conditionIf" required="false">
         <p>Turns on conditional logging. If set, requests will be
            logged only if <code>ServletRequest.getAttribute()</code> is



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to