You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2015/07/07 17:33:01 UTC

logging-log4j2 git commit: LOG4J2-1075 Added support for compressing to bzip2 format on file rollover

Repository: logging-log4j2
Updated Branches:
  refs/heads/master c49cbc428 -> 483d2ca31


LOG4J2-1075 Added support for compressing to bzip2 format on file
rollover

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/483d2ca3
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/483d2ca3
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/483d2ca3

Branch: refs/heads/master
Commit: 483d2ca31b3525079f956bff241da4125d1a8ed2
Parents: c49cbc4
Author: rpopma <rp...@apache.org>
Authored: Wed Jul 8 00:33:11 2015 +0900
Committer: rpopma <rp...@apache.org>
Committed: Wed Jul 8 00:33:11 2015 +0900

----------------------------------------------------------------------
 log4j-core/pom.xml                              |   6 +
 .../rolling/DefaultRolloverStrategy.java        |   5 +
 .../rolling/action/Bzip2CompressAction.java     | 131 +++++++++++++++++++
 log4j-core/src/site/xdoc/index.xml              |   2 +
 .../rolling/RollingAppenderSizeTest.java        |   3 +-
 .../rolling/action/Bzip2CompressActionTest.java | 120 +++++++++++++++++
 .../src/test/resources/log4j-rolling-bzip2.xml  |  59 +++++++++
 pom.xml                                         |   6 +
 src/changes/changes.xml                         |   7 +-
 src/site/xdoc/manual/appenders.xml              |   6 +-
 src/site/xdoc/runtime-dependencies.xml          |   5 +
 11 files changed, 345 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/log4j-core/pom.xml
----------------------------------------------------------------------
diff --git a/log4j-core/pom.xml b/log4j-core/pom.xml
index f351d26..8fbc6f4 100644
--- a/log4j-core/pom.xml
+++ b/log4j-core/pom.xml
@@ -107,6 +107,12 @@
       <scope>provided</scope>
       <optional>true</optional>
     </dependency>
+    <!-- Used for compressing to formats other than zip and gz -->
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-compress</artifactId>
+      <optional>true</optional>
+    </dependency>
 
     <!-- TEST DEPENDENCIES -->
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
index a477c3a..398f12f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
@@ -23,6 +23,7 @@ import java.util.zip.Deflater;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.appender.rolling.action.Action;
+import org.apache.logging.log4j.core.appender.rolling.action.Bzip2CompressAction;
 import org.apache.logging.log4j.core.appender.rolling.action.FileRenameAction;
 import org.apache.logging.log4j.core.appender.rolling.action.GzCompressAction;
 import org.apache.logging.log4j.core.appender.rolling.action.ZipCompressAction;
@@ -79,6 +80,7 @@ public class DefaultRolloverStrategy implements RolloverStrategy {
 
     private static final String EXT_ZIP = ".zip";
     private static final String EXT_GZIP = ".gz";
+    private static final String EXT_BZIP2 = ".bz2";
 
     /**
      * Allow subclasses access to the status logger without creating another instance.
@@ -423,6 +425,9 @@ public class DefaultRolloverStrategy implements RolloverStrategy {
             renameTo = renameTo.substring(0, renameTo.length() - EXT_ZIP.length());
             compressAction = new ZipCompressAction(new File(renameTo), new File(compressedName), true,
                     compressionLevel);
+        } else if (renameTo.endsWith(EXT_BZIP2)) {
+            renameTo = renameTo.substring(0, renameTo.length() - EXT_BZIP2.length());
+            compressAction = new Bzip2CompressAction(new File(renameTo), new File(compressedName), true);
         }
 
         final FileRenameAction renameAction =

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Bzip2CompressAction.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Bzip2CompressAction.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Bzip2CompressAction.java
new file mode 100644
index 0000000..3556415
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/Bzip2CompressAction.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.rolling.action;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
+
+/**
+ * Compresses a file using bzip2 compression.
+ */
+public final class Bzip2CompressAction extends AbstractAction {
+
+    private static final int BUF_SIZE = 8102;
+
+    /**
+     * Source file.
+     */
+    private final File source;
+
+    /**
+     * Destination file.
+     */
+    private final File destination;
+
+    /**
+     * If true, attempt to delete file on completion.
+     */
+    private final boolean deleteSource;
+
+    /**
+     * Create new instance of Bzip2CompressAction.
+     *
+     * @param source file to compress, may not be null.
+     * @param destination compressed file, may not be null.
+     * @param deleteSource if true, attempt to delete file on completion. Failure to delete does not cause an exception
+     *            to be thrown or affect return value.
+     */
+    public Bzip2CompressAction(final File source, final File destination, final boolean deleteSource) {
+        if (source == null) {
+            throw new NullPointerException("source");
+        }
+
+        if (destination == null) {
+            throw new NullPointerException("destination");
+        }
+
+        this.source = source;
+        this.destination = destination;
+        this.deleteSource = deleteSource;
+    }
+
+    /**
+     * Compress.
+     *
+     * @return true if successfully compressed.
+     * @throws IOException on IO exception.
+     */
+    @Override
+    public boolean execute() throws IOException {
+        return execute(source, destination, deleteSource);
+    }
+
+    /**
+     * Compress a file.
+     *
+     * @param source file to compress, may not be null.
+     * @param destination compressed file, may not be null.
+     * @param deleteSource if true, attempt to delete file on completion. Failure to delete does not cause an exception
+     *            to be thrown or affect return value.
+     * @return true if source file compressed.
+     * @throws IOException on IO exception.
+     */
+    public static boolean execute(final File source, final File destination, final boolean deleteSource)
+            throws IOException {
+        if (source.exists()) {
+            try (final FileInputStream fis = new FileInputStream(source);
+                    final BufferedOutputStream os = new BufferedOutputStream(new BZip2CompressorOutputStream(
+                            new FileOutputStream(destination)))) {
+                final byte[] inbuf = new byte[BUF_SIZE];
+                int n;
+
+                while ((n = fis.read(inbuf)) != -1) {
+                    os.write(inbuf, 0, n);
+                }
+            }
+
+            if (deleteSource && !source.delete()) {
+                LOGGER.warn("Unable to delete " + source.toString() + '.');
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Capture exception.
+     *
+     * @param ex exception.
+     */
+    @Override
+    protected void reportException(final Exception ex) {
+        LOGGER.warn("Exception during bzip2 compression of '" + source.toString() + "'.", ex);
+    }
+
+    @Override
+    public String toString() {
+        return Bzip2CompressAction.class.getSimpleName() + '[' + source + " to " + destination //
+                + ", deleteSource=" + deleteSource + ']';
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/log4j-core/src/site/xdoc/index.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/site/xdoc/index.xml b/log4j-core/src/site/xdoc/index.xml
index bbff7de..4332b62 100644
--- a/log4j-core/src/site/xdoc/index.xml
+++ b/log4j-core/src/site/xdoc/index.xml
@@ -56,6 +56,8 @@
                 <li>The NoSQL Appender with Apache CouchDB provider requires the LightCouch CouchDB client library.</li>
                 <li>The NoSQL Appender can be customized with a user-supplied provider, which will require the
                 appropriate client library.</li>
+                <li>bzip2 compression at rollover requires
+                <a href="http://commons.apache.org/proper/commons-compress/">Apache Commons Compress</a>.</li>                
             </ul>
         </section>
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeTest.java
index f37615f..e7aea45 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/RollingAppenderSizeTest.java
@@ -52,7 +52,8 @@ public class RollingAppenderSizeTest {
         return Arrays.asList(
                 new Object[][]{
                         { "log4j-rolling-gz.xml", ".gz" },
-                        { "log4j-rolling-zip.xml", ".zip" }
+                        { "log4j-rolling-zip.xml", ".zip" },
+                        { "log4j-rolling-bzip2.xml", ".bz2" },
                 }
         );
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/Bzip2CompressActionTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/Bzip2CompressActionTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/Bzip2CompressActionTest.java
new file mode 100644
index 0000000..df53c80
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/Bzip2CompressActionTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.core.appender.rolling.action;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests Bzip2CompressAction.
+ */
+public class Bzip2CompressActionTest {
+
+    @Test(expected = NullPointerException.class)
+    public void testConstructorDisallowsNullSource() {
+        new Bzip2CompressAction(null, new File("any"), true);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testConstructorDisallowsNullDestination() {
+        new Bzip2CompressAction(new File("any"), null, true);
+    }
+
+    @Test
+    public void testExecuteReturnsFalseIfSourceDoesNotExist() throws IOException {
+        File source = new File("any");
+        while (source.exists()) {
+            source = new File(source.getName() + Math.random());
+        }
+        boolean actual = Bzip2CompressAction.execute(source, new File("any2"), true);
+        assertEquals("Cannot compress non-existing file", false, actual);
+    }
+
+    @Test
+    public void testExecuteCompressesSourceFileToDestinationFile() throws IOException {
+        final String LINE1 = "Here is line 1. Random text: ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
+        final String LINE2 = "Here is line 2. Random text: ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
+        final String LINE3 = "Here is line 3. Random text: ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n";
+        final File source = new File("target/compressme");
+        try (FileWriter fw = new FileWriter(source, false)) {
+            fw.write(LINE1);
+            fw.write(LINE2);
+            fw.write(LINE3);
+            fw.flush();
+        }
+        final File destination = new File("target/compressme.bz2");
+        destination.delete(); // just in case
+        assertFalse("Destination should not exist yet", destination.exists());
+
+        final boolean actual = Bzip2CompressAction.execute(source, destination, true);
+        assertEquals("Bzip2CompressAction should have succeeded", true, actual);
+        assertTrue("Destination should exist after Bzip2CompressAction", destination.exists());
+        assertFalse("Source should have been deleted", source.exists());
+
+        final byte[] bz2 = new byte[] { (byte) 0x42, (byte) 0x5A, (byte) 0x68, (byte) 0x39, (byte) 0x31, (byte) 0x41,
+                (byte) 0x59, (byte) 0x26, (byte) 0x53, (byte) 0x59, (byte) 0x9C, (byte) 0xE1, (byte) 0xE8, (byte) 0x2D,
+                (byte) 0x00, (byte) 0x00, (byte) 0x1C, (byte) 0xDF, (byte) 0x80, (byte) 0x00, (byte) 0x12, (byte) 0x40,
+                (byte) 0x01, (byte) 0x38, (byte) 0x10, (byte) 0x3F, (byte) 0xFF, (byte) 0xFF, (byte) 0xF0, (byte) 0x26,
+                (byte) 0x27, (byte) 0x9C, (byte) 0x40, (byte) 0x20, (byte) 0x00, (byte) 0x70, (byte) 0x63, (byte) 0x4D,
+                (byte) 0x06, (byte) 0x80, (byte) 0x19, (byte) 0x34, (byte) 0x06, (byte) 0x46, (byte) 0x9A, (byte) 0x18,
+                (byte) 0x9A, (byte) 0x30, (byte) 0xCF, (byte) 0xFD, (byte) 0x55, (byte) 0x4D, (byte) 0x0D, (byte) 0x06,
+                (byte) 0x9A, (byte) 0x0C, (byte) 0x40, (byte) 0x1A, (byte) 0x1A, (byte) 0x34, (byte) 0x34, (byte) 0xCD,
+                (byte) 0x46, (byte) 0x05, (byte) 0x6B, (byte) 0x19, (byte) 0x92, (byte) 0x23, (byte) 0x5E, (byte) 0xB5,
+                (byte) 0x2E, (byte) 0x79, (byte) 0x65, (byte) 0x41, (byte) 0x81, (byte) 0x33, (byte) 0x4B, (byte) 0x53,
+                (byte) 0x5B, (byte) 0x62, (byte) 0x75, (byte) 0x0A, (byte) 0x14, (byte) 0xB6, (byte) 0xB7, (byte) 0x37,
+                (byte) 0xB8, (byte) 0x38, (byte) 0xB9, (byte) 0x39, (byte) 0xBA, (byte) 0x2A, (byte) 0x4E, (byte) 0xEA,
+                (byte) 0xEC, (byte) 0xEE, (byte) 0xAD, (byte) 0xE1, (byte) 0xE5, (byte) 0x63, (byte) 0xD3, (byte) 0x22,
+                (byte) 0xE8, (byte) 0x90, (byte) 0x52, (byte) 0xA9, (byte) 0x7A, (byte) 0x68, (byte) 0x90, (byte) 0x5C,
+                (byte) 0x82, (byte) 0x0B, (byte) 0x51, (byte) 0xBF, (byte) 0x24, (byte) 0x61, (byte) 0x7F, (byte) 0x17,
+                (byte) 0x72, (byte) 0x45, (byte) 0x38, (byte) 0x50, (byte) 0x90, (byte) 0x9C, (byte) 0xE1, (byte) 0xE8,
+                (byte) 0x2D };
+        assertEquals(bz2.length, destination.length());
+
+        // check the compressed contents
+        try (FileInputStream fis = new FileInputStream(destination)) {
+            final byte[] actualBz2 = new byte[bz2.length];
+            int n = 0;
+            int offset = 0;
+            do {
+                n = fis.read(actualBz2, offset, actualBz2.length - offset);
+                offset += n;
+            } while (offset < actualBz2.length);
+            assertArrayEquals("Compressed data corrupt", bz2, actualBz2);
+        }
+        destination.delete();
+
+        // uncompress
+        try (BZip2CompressorInputStream bzin = new BZip2CompressorInputStream(new ByteArrayInputStream(bz2))) {
+            final StringBuilder sb = new StringBuilder();
+            final byte[] buf = new byte[1024];
+            int n = 0;
+            while ((n = bzin.read(buf, 0, buf.length)) > -1) {
+                sb.append(new String(buf, 0, n));
+            }
+            assertEquals(LINE1 + LINE2 + LINE3, sb.toString());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/log4j-core/src/test/resources/log4j-rolling-bzip2.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-rolling-bzip2.xml b/log4j-core/src/test/resources/log4j-rolling-bzip2.xml
new file mode 100644
index 0000000..39d4f49
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-rolling-bzip2.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<Configuration status="OFF" name="XMLConfigTest">
+  <Properties>
+    <Property name="filename">target/rolling1/rollingtest.log</Property>
+  </Properties>
+  <ThresholdFilter level="debug"/>
+
+  <Appenders>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+    <RollingFile name="RollingFile" fileName="${filename}"
+                 filePattern="target/rolling1/test1-$${date:MM-dd-yyyy}-%i.log.bz2">
+      <PatternLayout>
+        <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+      </PatternLayout>
+      <SizeBasedTriggeringPolicy size="500" />
+      <DefaultRolloverStrategy compressionLevel="9" />
+    </RollingFile>
+    <List name="List">
+      <ThresholdFilter level="error"/>
+    </List>
+  </Appenders>
+
+  <Loggers>
+    <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
+      <ThreadContextMapFilter>
+        <KeyValuePair key="test" value="123"/>
+      </ThreadContextMapFilter>
+      <AppenderRef ref="STDOUT"/>
+    </Logger>>
+
+    <Logger name="org.apache.logging.log4j.core.appender.rolling" level="debug" additivity="false">
+      <AppenderRef ref="RollingFile"/>
+    </Logger>>
+
+    <Root level="error">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ffb921f..d42c93d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -681,6 +681,12 @@
         <version>2.4</version>
         <scope>test</scope>
       </dependency>
+      <!-- Used for compressing to formats other than zip and gz -->
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-compress</artifactId>
+        <version>1.9</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>
   <build>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c6baa81..8463521 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,8 +24,11 @@
   </properties>
   <body>
     <release version="2.4" date="2015-MM-DD" description="GA Release 2.4">
-      <action issue="LOG4J2-889" dev="rpopma" type="fix">
-        Header in layout should not be written on application startup if appending to an existing file.
+      <action issue="LOG4J2-1075" dev="rpopma" type="add">
+        Added support for compressing to bzip2 format on file rollover.
+      </action>
+      <action issue="LOG4J2-889" dev="rpopma" type="fix" due-to="Maciej Karaƛ, Kenneth Leider">
+        Header in layout should not be written on application startup if appending to an existing file. Fixes LOG4J2-1030.
       </action>
       <action issue="LOG4J2-918" dev="rpopma" type="fix">
         Clarify documentation for combining async with sync loggers.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/src/site/xdoc/manual/appenders.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/appenders.xml b/src/site/xdoc/manual/appenders.xml
index c9a28a8..e2f85eb 100644
--- a/src/site/xdoc/manual/appenders.xml
+++ b/src/site/xdoc/manual/appenders.xml
@@ -2146,8 +2146,10 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity {
                 is present it will be replaced with the current date and time values. If the pattern contains an integer
                 it will be incremented on each rollover. If the pattern contains both a date/time and integer
                 in the pattern the integer will be incremented until the result of the date/time pattern changes. If
-                the file pattern ends with ".gz" or ".zip" the resulting archive will be compressed using the
-                compression scheme that matches the suffix. The pattern may also contain lookup references that
+                the file pattern ends with ".gz", ".zip" or ".bz2" the resulting archive will be compressed using the
+                compression scheme that matches the suffix. (bzip2 requires 
+                <a href="http://commons.apache.org/proper/commons-compress/">Apache Commons Compress</a>.)
+                The pattern may also contain lookup references that
                 can be resolved at runtime such as is shown in the example below.
               </p>
               <p>The default rollover strategy supports two variations for incrementing the counter. The first is

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/483d2ca3/src/site/xdoc/runtime-dependencies.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/runtime-dependencies.xml b/src/site/xdoc/runtime-dependencies.xml
index caf640d..227dfc3 100644
--- a/src/site/xdoc/runtime-dependencies.xml
+++ b/src/site/xdoc/runtime-dependencies.xml
@@ -90,6 +90,11 @@
             entity that the user implements. It also requires an appropriate JDBC driver
           </td>
         </tr>
+        <tr>
+          <td>bzip2 compression at rollover</td>
+          <td><a href="http://commons.apache.org/proper/commons-compress/">Apache Commons Compress</a>
+          </td>
+        </tr>
       </table>
 
       <a name="log4j-jcl" />