This is an automated email from the ASF dual-hosted git repository.

ramanathan1504 pushed a commit to branch ramanathan1504-issue-2351
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 73e2e8a2a9c0462624d475878e85fd53722d2aa4
Author: Ramanathan <[email protected]>
AuthorDate: Thu May 28 14:51:18 2026 +0530

    Add support for max compression delay in compression actions (#4071)
    
    Co-authored-by: Volkan Yazıcı <[email protected]>
---
 .../rolling/FileExtensionCompressDelayTest.java    | 179 +++++++++++++++++++++
 .../rolling/action/GzCompressActionTest.java       | 120 ++++++++++++++
 .../rolling/action/ZipCompressActionTest.java      | 120 ++++++++++++++
 .../appender/rolling/DefaultRolloverStrategy.java  |  84 +++++++++-
 .../log4j/core/appender/rolling/FileExtension.java | 108 ++++++++++++-
 .../appender/rolling/action/AbstractAction.java    |  19 +++
 .../rolling/action/CommonsCompressAction.java      |  27 ++++
 .../appender/rolling/action/GzCompressAction.java  |  50 +++++-
 .../appender/rolling/action/ZipCompressAction.java |  47 +++++-
 .../core/appender/rolling/action/package-info.java |   2 +-
 .../log4j/core/appender/rolling/package-info.java  |   2 +-
 .../.2.x.x/4012_add_max_compression_delay.xml      |  14 ++
 .../ROOT/pages/manual/appenders/rolling-file.adoc  |   9 ++
 13 files changed, 758 insertions(+), 23 deletions(-)

diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/FileExtensionCompressDelayTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/FileExtensionCompressDelayTest.java
new file mode 100644
index 0000000000..98ebf8a691
--- /dev/null
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/FileExtensionCompressDelayTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import org.apache.logging.log4j.core.appender.rolling.action.Action;
+import org.apache.logging.log4j.core.appender.rolling.action.GzCompressAction;
+import org.apache.logging.log4j.core.appender.rolling.action.ZipCompressAction;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+/**
+ * Issue #4012 — verifies that FileExtension.GZ and FileExtension.ZIP 
correctly pass
+ * maxCompressionDelaySeconds through to the compression action.
+ *
+ * This was the root cause of the bug: the 5-argument createCompressAction() 
in GZ and ZIP
+ * fell back to the 4-argument version, silently dropping the delay value.
+ */
+class FileExtensionCompressDelayTest {
+
+    @Test
+    void testGzCreateCompressActionRejectsInvalidCompressionLevel(@TempDir 
File tempDir) {
+        File source = new File(tempDir, "invalid-level.log");
+        File dest = new File(tempDir, "invalid-level.log.gz");
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> FileExtension.GZ.createCompressAction(source.getPath(), 
dest.getPath(), true, -2, 0));
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> FileExtension.GZ.createCompressAction(source.getPath(), 
dest.getPath(), true, 10, 0));
+    }
+
+    @Test
+    void testZipCreateCompressActionRejectsInvalidCompressionLevel(@TempDir 
File tempDir) {
+        File source = new File(tempDir, "invalid-level.log");
+        File dest = new File(tempDir, "invalid-level.log.zip");
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> FileExtension.ZIP.createCompressAction(source.getPath(), 
dest.getPath(), true, -2, 0));
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> FileExtension.ZIP.createCompressAction(source.getPath(), 
dest.getPath(), true, 10, 0));
+    }
+
+    // ── GZ ────────────────────────────────────────────────────────────────
+
+    /**
+     * FileExtension.GZ.createCompressAction(5-args) must produce a 
GzCompressAction
+     * that applies the random delay — not fall back to 0.
+     */
+    @Test
+    void testGzCreateCompressActionWithDelay(@TempDir File tempDir) throws 
Exception {
+        File source = new File(tempDir, "app.log");
+        File dest = new File(tempDir, "app.log.gz");
+        writeContent(source, "gz test content");
+
+        int maxDelay = 2;
+        Action action = 
FileExtension.GZ.createCompressAction(source.getPath(), dest.getPath(), true, 
-1, maxDelay);
+
+        // Must return a GzCompressAction (not some other type)
+        assertInstanceOf(GzCompressAction.class, action, "Expected 
GzCompressAction");
+
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        // Must finish within maxDelay + margin (delay IS applied via 
FileExtension)
+        assertTrue(
+                elapsed <= (maxDelay * 1000L) + 500,
+                "GZ compress via FileExtension exceeded maxDelay=" + maxDelay 
+ "s: " + elapsed + "ms");
+        assertTrue(dest.exists(), "Compressed .gz file must exist");
+        assertFalse(source.exists(), "Source must be deleted after 
compression");
+    }
+
+    /**
+     * FileExtension.GZ.createCompressAction(5-args, delay=0) must behave 
identically
+     * to the 4-arg version — instant compression, no delay.
+     */
+    @Test
+    void testGzCreateCompressActionNoDelay(@TempDir File tempDir) throws 
Exception {
+        File source = new File(tempDir, "app-nodelay.log");
+        File dest = new File(tempDir, "app-nodelay.log.gz");
+        writeContent(source, "gz no-delay content");
+
+        Action action = 
FileExtension.GZ.createCompressAction(source.getPath(), dest.getPath(), true, 
-1, 0);
+
+        assertInstanceOf(GzCompressAction.class, action);
+
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        assertTrue(elapsed < 500, "GZ with delay=0 should be instant, took " + 
elapsed + "ms");
+        assertTrue(dest.exists(), "Compressed .gz file must exist");
+        assertFalse(source.exists(), "Source must be deleted");
+    }
+
+    // ── ZIP ───────────────────────────────────────────────────────────────
+
+    /**
+     * FileExtension.ZIP.createCompressAction(5-args) must produce a 
ZipCompressAction
+     * that applies the random delay — not fall back to 0.
+     */
+    @Test
+    void testZipCreateCompressActionWithDelay(@TempDir File tempDir) throws 
Exception {
+        File source = new File(tempDir, "app.log");
+        File dest = new File(tempDir, "app.log.zip");
+        writeContent(source, "zip test content");
+
+        int maxDelay = 2;
+        Action action = 
FileExtension.ZIP.createCompressAction(source.getPath(), dest.getPath(), true, 
0, maxDelay);
+
+        assertInstanceOf(ZipCompressAction.class, action, "Expected 
ZipCompressAction");
+
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        assertTrue(
+                elapsed <= (maxDelay * 1000L) + 500,
+                "ZIP compress via FileExtension exceeded maxDelay=" + maxDelay 
+ "s: " + elapsed + "ms");
+        assertTrue(dest.exists(), "Compressed .zip file must exist");
+        assertFalse(source.exists(), "Source must be deleted after 
compression");
+    }
+
+    /**
+     * FileExtension.ZIP.createCompressAction(5-args, delay=0) must behave 
identically
+     * to the 4-arg version — instant compression, no delay.
+     */
+    @Test
+    void testZipCreateCompressActionNoDelay(@TempDir File tempDir) throws 
Exception {
+        File source = new File(tempDir, "app-nodelay.log");
+        File dest = new File(tempDir, "app-nodelay.log.zip");
+        writeContent(source, "zip no-delay content");
+
+        Action action = 
FileExtension.ZIP.createCompressAction(source.getPath(), dest.getPath(), true, 
0, 0);
+
+        assertInstanceOf(ZipCompressAction.class, action);
+
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        assertTrue(elapsed < 500, "ZIP with delay=0 should be instant, took " 
+ elapsed + "ms");
+        assertTrue(dest.exists(), "Compressed .zip file must exist");
+        assertFalse(source.exists(), "Source must be deleted");
+    }
+
+    // ── helpers ───────────────────────────────────────────────────────────
+
+    private static void writeContent(final File file, final String content) 
throws IOException {
+        try (FileWriter writer = new FileWriter(file)) {
+            writer.write(content);
+        }
+    }
+}
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/GzCompressActionTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/GzCompressActionTest.java
new file mode 100644
index 0000000000..14d72c56dd
--- /dev/null
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/GzCompressActionTest.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 static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.zip.Deflater;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+class GzCompressActionTest {
+
+    @Test
+    void testRejectsCompressionLevelLowerThanDefault(@TempDir File tempDir) {
+        File source = new File(tempDir, "invalid-low.log");
+        File dest = new File(tempDir, "invalid-low.log.gz");
+
+        assertThrows(IllegalArgumentException.class, () -> new 
GzCompressAction(source, dest, true, -2, 0));
+    }
+
+    @Test
+    void testRejectsCompressionLevelHigherThanBest(@TempDir File tempDir) {
+        File source = new File(tempDir, "invalid-high.log");
+        File dest = new File(tempDir, "invalid-high.log.gz");
+
+        assertThrows(IllegalArgumentException.class, () -> new 
GzCompressAction(source, dest, true, 10, 0));
+    }
+
+    @Test
+    void testAcceptsDeflaterRangeBounds(@TempDir File tempDir) {
+        File source = new File(tempDir, "valid.log");
+        File dest = new File(tempDir, "valid.log.gz");
+
+        new GzCompressAction(source, dest, true, Deflater.DEFAULT_COMPRESSION, 
0);
+        new GzCompressAction(source, dest, true, Deflater.BEST_COMPRESSION, 0);
+    }
+
+    /** Issue #4012 — when maxDelaySeconds > 0, compression must be deferred 
by a random 0..max seconds. */
+    @Test
+    void testRandomDelayBeforeCompression(@TempDir File tempDir) throws 
IOException {
+        File source = new File(tempDir, "test.log");
+        File dest = new File(tempDir, "test.log.gz");
+        try (FileWriter writer = new FileWriter(source)) {
+            writer.write("test data");
+        }
+        int maxDelay = 2; // seconds
+        GzCompressAction action = new GzCompressAction(source, dest, true, 0, 
maxDelay);
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        // Must complete within maxDelay + small margin
+        assertTrue(
+                elapsed <= (maxDelay * 1000L) + 500,
+                "Compression should not exceed maxDelay=" + maxDelay + "s, but 
took " + elapsed + "ms");
+        // Destination must be created
+        assertTrue(dest.exists(), "Compressed file must exist after 
execute()");
+        // Source must be deleted (deleteSource=true)
+        assertFalse(source.exists(), "Source file must be deleted after 
compression");
+    }
+
+    /**
+     * Issue #4012 — when maxDelaySeconds=0, no delay is applied (backward 
compatibility).
+     * Compression must complete well under 500ms.
+     */
+    @Test
+    void testNoDelayWhenMaxDelayIsZero(@TempDir File tempDir) throws 
IOException {
+        File source = new File(tempDir, "test-nodelay.log");
+        File dest = new File(tempDir, "test-nodelay.log.gz");
+        try (FileWriter writer = new FileWriter(source)) {
+            writer.write("test data no delay");
+        }
+        GzCompressAction action = new GzCompressAction(source, dest, true, 0, 
0);
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        // No delay: must complete in well under 500ms
+        assertTrue(elapsed < 500, "Compression with maxDelay=0 should be 
instant, but took " + elapsed + "ms");
+        assertTrue(dest.exists(), "Compressed file must exist after 
execute()");
+        assertFalse(source.exists(), "Source file must be deleted after 
compression");
+    }
+
+    /** Legacy 4-arg constructor must still work with no delay (backward 
compatibility). */
+    @Test
+    void testLegacyConstructorNoDelay(@TempDir File tempDir) throws 
IOException {
+        File source = new File(tempDir, "test-legacy.log");
+        File dest = new File(tempDir, "test-legacy.log.gz");
+        try (FileWriter writer = new FileWriter(source)) {
+            writer.write("legacy test data");
+        }
+        GzCompressAction action = new GzCompressAction(source, dest, true, 0);
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        assertTrue(elapsed < 500, "Legacy constructor should have no delay, 
but took " + elapsed + "ms");
+        assertTrue(dest.exists(), "Compressed file must exist");
+        assertFalse(source.exists(), "Source file must be deleted");
+    }
+}
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ZipCompressActionTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ZipCompressActionTest.java
new file mode 100644
index 0000000000..b8bc76ce53
--- /dev/null
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/rolling/action/ZipCompressActionTest.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 static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+class ZipCompressActionTest {
+
+    @Test
+    void testRejectsCompressionLevelBelowRange(@TempDir File tempDir) {
+        File source = new File(tempDir, "invalid-low.log");
+        File dest = new File(tempDir, "invalid-low.log.zip");
+
+        assertThrows(IllegalArgumentException.class, () -> new 
ZipCompressAction(source, dest, true, -2, 0));
+    }
+
+    @Test
+    void testRejectsCompressionLevelAboveRange(@TempDir File tempDir) {
+        File source = new File(tempDir, "invalid-high.log");
+        File dest = new File(tempDir, "invalid-high.log.zip");
+
+        assertThrows(IllegalArgumentException.class, () -> new 
ZipCompressAction(source, dest, true, 10, 0));
+    }
+
+    @Test
+    void testAcceptsCompressionLevelRangeBounds(@TempDir File tempDir) {
+        File source = new File(tempDir, "valid.log");
+        File dest = new File(tempDir, "valid.log.zip");
+
+        new ZipCompressAction(source, dest, true, -1, 0);
+        new ZipCompressAction(source, dest, true, 0, 0);
+        new ZipCompressAction(source, dest, true, 9, 0);
+    }
+
+    /** Issue #4012 — when maxDelaySeconds > 0, compression must be deferred 
by a random 0..max seconds. */
+    @Test
+    void testRandomDelayBeforeCompression(@TempDir File tempDir) throws 
IOException {
+        File source = new File(tempDir, "test.log");
+        File dest = new File(tempDir, "test.log.zip");
+        try (FileWriter writer = new FileWriter(source)) {
+            writer.write("test data");
+        }
+        int maxDelay = 2; // seconds
+        ZipCompressAction action = new ZipCompressAction(source, dest, true, 
0, maxDelay);
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        // Must complete within maxDelay + small margin
+        assertTrue(
+                elapsed <= (maxDelay * 1000L) + 500,
+                "Compression should not exceed maxDelay=" + maxDelay + "s, but 
took " + elapsed + "ms");
+        // Destination must be created
+        assertTrue(dest.exists(), "Compressed file must exist after 
execute()");
+        // Source must be deleted (deleteSource=true)
+        assertFalse(source.exists(), "Source file must be deleted after 
compression");
+    }
+
+    /**
+     * Issue #4012 — when maxDelaySeconds=0, no delay is applied (backward 
compatibility).
+     * Compression must complete well under 500ms.
+     */
+    @Test
+    void testNoDelayWhenMaxDelayIsZero(@TempDir File tempDir) throws 
IOException {
+        File source = new File(tempDir, "test-nodelay.log");
+        File dest = new File(tempDir, "test-nodelay.log.zip");
+        try (FileWriter writer = new FileWriter(source)) {
+            writer.write("test data no delay");
+        }
+        ZipCompressAction action = new ZipCompressAction(source, dest, true, 
0, 0);
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        // No delay: must complete in well under 500ms
+        assertTrue(elapsed < 500, "Compression with maxDelay=0 should be 
instant, but took " + elapsed + "ms");
+        assertTrue(dest.exists(), "Compressed file must exist after 
execute()");
+        assertFalse(source.exists(), "Source file must be deleted after 
compression");
+    }
+
+    /** Legacy 4-arg constructor must still work with no delay (backward 
compatibility). */
+    @Test
+    void testLegacyConstructorNoDelay(@TempDir File tempDir) throws 
IOException {
+        File source = new File(tempDir, "test-legacy.log");
+        File dest = new File(tempDir, "test-legacy.log.zip");
+        try (FileWriter writer = new FileWriter(source)) {
+            writer.write("legacy test data");
+        }
+        ZipCompressAction action = new ZipCompressAction(source, dest, true, 
0);
+        long start = System.currentTimeMillis();
+        action.execute();
+        long elapsed = System.currentTimeMillis() - start;
+
+        assertTrue(elapsed < 500, "Legacy constructor should have no delay, 
but took " + elapsed + "ms");
+        assertTrue(dest.exists(), "Compressed file must exist");
+        assertFalse(source.exists(), "Source file must be deleted");
+    }
+}
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 ea1bae7669..74fbbf8359 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
@@ -109,6 +109,9 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
         @PluginBuilderAttribute(value = "tempCompressedFilePattern")
         private String tempCompressedFilePattern;
 
+        @PluginBuilderAttribute("maxCompressionDelaySeconds")
+        private int maxCompressionDelaySeconds = 0;
+
         @PluginConfiguration
         private Configuration config;
 
@@ -156,7 +159,8 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
                     nonNullStrSubstitutor,
                     customActions,
                     stopCustomActionsOnError,
-                    tempCompressedFilePattern);
+                    tempCompressedFilePattern,
+                    maxCompressionDelaySeconds);
         }
 
         public String getMax() {
@@ -359,6 +363,18 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
             this.config = config;
             return this;
         }
+
+        /**
+         * Defines maximum delay in seconds before compression.
+         *
+         * @param maxCompressionDelaySeconds maximum delay in seconds before 
compression.
+         * @return This builder for chaining convenience
+         * @since 2.27.0
+         */
+        public Builder setMaxCompressionDelaySeconds(final int 
maxCompressionDelaySeconds) {
+            this.maxCompressionDelaySeconds = maxCompressionDelaySeconds;
+            return this;
+        }
     }
 
     @PluginBuilderFactory
@@ -380,10 +396,14 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
      * @return A DefaultRolloverStrategy.
      * @deprecated Since 2.9 Usage of Builder API is preferable
      */
+
+    /**
+     * Legacy factory method for backward compatibility (no delay parameter).
+     * @deprecated Since 2.9 Usage of Builder API is preferable
+     */
     @PluginFactory
     @Deprecated
     public static DefaultRolloverStrategy createStrategy(
-            // @formatter:off
             @PluginAttribute("max") final String max,
             @PluginAttribute("min") final String min,
             @PluginAttribute("fileIndex") final String fileIndex,
@@ -401,7 +421,6 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
                 .setStopCustomActionsOnError(stopCustomActionsOnError)
                 .setConfig(config)
                 .build();
-        // @formatter:on
     }
 
     /**
@@ -419,6 +438,7 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
     private final List<Action> customActions;
     private final boolean stopCustomActionsOnError;
     private final PatternProcessor tempCompressedFilePattern;
+    private final int maxCompressionDelaySeconds;
 
     /**
      * Constructs a new instance.
@@ -446,7 +466,8 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
                 strSubstitutor,
                 customActions,
                 stopCustomActionsOnError,
-                null);
+                null,
+                0);
     }
 
     /**
@@ -468,6 +489,40 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
             final Action[] customActions,
             final boolean stopCustomActionsOnError,
             final String tempCompressedFilePatternString) {
+        this(
+                minIndex,
+                maxIndex,
+                useMax,
+                compressionLevel,
+                strSubstitutor,
+                customActions,
+                stopCustomActionsOnError,
+                tempCompressedFilePatternString,
+                0);
+    }
+
+    /**
+     * Constructs a new instance.
+     *
+     * @param minIndex The minimum index.
+     * @param maxIndex The maximum index.
+     * @param customActions custom actions to perform asynchronously after 
rollover
+     * @param stopCustomActionsOnError whether to stop executing asynchronous 
actions if an error occurs
+     * @param tempCompressedFilePatternString File pattern of the working file
+     *                                     used during compression, if null no 
temporary file are used
+     * @param maxCompressionDelaySeconds maximum delay in seconds before 
compression.
+     * @since 2.27.0
+     */
+    protected DefaultRolloverStrategy(
+            final int minIndex,
+            final int maxIndex,
+            final boolean useMax,
+            final int compressionLevel,
+            final StrSubstitutor strSubstitutor,
+            final Action[] customActions,
+            final boolean stopCustomActionsOnError,
+            final String tempCompressedFilePatternString,
+            final int maxCompressionDelaySeconds) {
         super(strSubstitutor);
         this.minIndex = minIndex;
         this.maxIndex = maxIndex;
@@ -477,6 +532,7 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
         this.customActions = customActions == null ? 
Collections.<Action>emptyList() : Arrays.asList(customActions);
         this.tempCompressedFilePattern =
                 tempCompressedFilePatternString != null ? new 
PatternProcessor(tempCompressedFilePatternString) : null;
+        this.maxCompressionDelaySeconds = maxCompressionDelaySeconds;
     }
 
     public int getCompressionLevel() {
@@ -507,6 +563,16 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
         return tempCompressedFilePattern;
     }
 
+    /**
+     * Returns the maximum delay in seconds before compression.
+     *
+     * @return maximum delay in seconds before compression.
+     * @since 2.27.0
+     */
+    public int getMaxCompressionDelaySeconds() {
+        return maxCompressionDelaySeconds;
+    }
+
     private int purge(final int lowIndex, final int highIndex, final 
RollingFileManager manager) {
         return useMax ? purgeAscending(lowIndex, highIndex, manager) : 
purgeDescending(lowIndex, highIndex, manager);
     }
@@ -680,11 +746,17 @@ public class DefaultRolloverStrategy extends 
AbstractRolloverStrategy {
                 }
                 compressAction = new CompositeAction(
                         Arrays.asList(
-                                fileExtension.createCompressAction(renameTo, 
tmpCompressedName, true, compressionLevel),
+                                fileExtension.createCompressAction(
+                                        renameTo,
+                                        tmpCompressedName,
+                                        true,
+                                        compressionLevel,
+                                        maxCompressionDelaySeconds),
                                 new FileRenameAction(tmpCompressedNameFile, 
renameToFile, true)),
                         true);
             } else {
-                compressAction = fileExtension.createCompressAction(renameTo, 
compressedName, true, compressionLevel);
+                compressAction = fileExtension.createCompressAction(
+                        renameTo, compressedName, true, compressionLevel, 
maxCompressionDelaySeconds);
             }
         }
 
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileExtension.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileExtension.java
index e62419b685..eb453628e8 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileExtension.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/FileExtension.java
@@ -35,7 +35,22 @@ public enum FileExtension {
                 final String compressedName,
                 final boolean deleteSource,
                 final int compressionLevel) {
-            return new ZipCompressAction(source(renameTo), 
target(compressedName), deleteSource, compressionLevel);
+            return createCompressAction(renameTo, compressedName, 
deleteSource, compressionLevel, 0);
+        }
+
+        @Override
+        public Action createCompressAction(
+                final String renameTo,
+                final String compressedName,
+                final boolean deleteSource,
+                final int compressionLevel,
+                final int maxCompressionDelaySeconds) {
+            return new ZipCompressAction(
+                    new File(renameTo),
+                    new File(compressedName),
+                    deleteSource,
+                    compressionLevel,
+                    maxCompressionDelaySeconds);
         }
     },
     GZ(".gz") {
@@ -45,7 +60,22 @@ public enum FileExtension {
                 final String compressedName,
                 final boolean deleteSource,
                 final int compressionLevel) {
-            return new GzCompressAction(source(renameTo), 
target(compressedName), deleteSource, compressionLevel);
+            return createCompressAction(renameTo, compressedName, 
deleteSource, compressionLevel, 0);
+        }
+
+        @Override
+        public Action createCompressAction(
+                final String renameTo,
+                final String compressedName,
+                final boolean deleteSource,
+                final int compressionLevel,
+                final int maxCompressionDelaySeconds) {
+            return new GzCompressAction(
+                    new File(renameTo),
+                    new File(compressedName),
+                    deleteSource,
+                    compressionLevel,
+                    maxCompressionDelaySeconds);
         }
     },
     BZIP2(".bz2") {
@@ -55,8 +85,19 @@ public enum FileExtension {
                 final String compressedName,
                 final boolean deleteSource,
                 final int compressionLevel) {
+            return createCompressAction(renameTo, compressedName, 
deleteSource, compressionLevel, 0);
+        }
+
+        @Override
+        public Action createCompressAction(
+                final String renameTo,
+                final String compressedName,
+                final boolean deleteSource,
+                final int compressionLevel,
+                final int maxCompressionDelaySeconds) {
             // One of "gz", "bzip2", "xz", "zst", "pack200", or "deflate".
-            return new CommonsCompressAction("bzip2", source(renameTo), 
target(compressedName), deleteSource);
+            return new CommonsCompressAction(
+                    "bzip2", source(renameTo), target(compressedName), 
deleteSource, maxCompressionDelaySeconds);
         }
     },
     DEFLATE(".deflate") {
@@ -66,8 +107,19 @@ public enum FileExtension {
                 final String compressedName,
                 final boolean deleteSource,
                 final int compressionLevel) {
+            return createCompressAction(renameTo, compressedName, 
deleteSource, compressionLevel, 0);
+        }
+
+        @Override
+        public Action createCompressAction(
+                final String renameTo,
+                final String compressedName,
+                final boolean deleteSource,
+                final int compressionLevel,
+                final int maxCompressionDelaySeconds) {
             // One of "gz", "bzip2", "xz", "zst", "pack200", or "deflate".
-            return new CommonsCompressAction("deflate", source(renameTo), 
target(compressedName), deleteSource);
+            return new CommonsCompressAction(
+                    "deflate", source(renameTo), target(compressedName), 
deleteSource, maxCompressionDelaySeconds);
         }
     },
     PACK200(".pack200") {
@@ -77,8 +129,19 @@ public enum FileExtension {
                 final String compressedName,
                 final boolean deleteSource,
                 final int compressionLevel) {
-            // One of "gz", "bzip2", "xz", "zst", "pack200", or "deflate".
-            return new CommonsCompressAction("pack200", source(renameTo), 
target(compressedName), deleteSource);
+            return createCompressAction(renameTo, compressedName, 
deleteSource, compressionLevel, 0);
+        }
+
+        @Override
+        public Action createCompressAction(
+                final String renameTo,
+                final String compressedName,
+                final boolean deleteSource,
+                final int compressionLevel,
+                final int maxCompressionDelaySeconds) {
+            // One of "gz", "bzip2", "xz", "zstd", "pack200", or "deflate".
+            return new CommonsCompressAction(
+                    "pack200", source(renameTo), target(compressedName), 
deleteSource, maxCompressionDelaySeconds);
         }
     },
     XZ(".xz") {
@@ -88,8 +151,19 @@ public enum FileExtension {
                 final String compressedName,
                 final boolean deleteSource,
                 final int compressionLevel) {
+            return createCompressAction(renameTo, compressedName, 
deleteSource, compressionLevel, 0);
+        }
+
+        @Override
+        public Action createCompressAction(
+                final String renameTo,
+                final String compressedName,
+                final boolean deleteSource,
+                final int compressionLevel,
+                final int maxCompressionDelaySeconds) {
             // One of "gz", "bzip2", "xz", "zstd", "pack200", or "deflate".
-            return new CommonsCompressAction("xz", source(renameTo), 
target(compressedName), deleteSource);
+            return new CommonsCompressAction(
+                    "xz", source(renameTo), target(compressedName), 
deleteSource, maxCompressionDelaySeconds);
         }
     },
     ZSTD(".zst") {
@@ -99,8 +173,19 @@ public enum FileExtension {
                 final String compressedName,
                 final boolean deleteSource,
                 final int compressionLevel) {
+            return createCompressAction(renameTo, compressedName, 
deleteSource, compressionLevel, 0);
+        }
+
+        @Override
+        public Action createCompressAction(
+                final String renameTo,
+                final String compressedName,
+                final boolean deleteSource,
+                final int compressionLevel,
+                final int maxCompressionDelaySeconds) {
             // One of "gz", "bzip2", "xz", "zstd", "pack200", or "deflate".
-            return new CommonsCompressAction("zstd", source(renameTo), 
target(compressedName), deleteSource);
+            return new CommonsCompressAction(
+                    "zstd", source(renameTo), target(compressedName), 
deleteSource, maxCompressionDelaySeconds);
         }
     };
 
@@ -132,6 +217,13 @@ public enum FileExtension {
     public abstract Action createCompressAction(
             String renameTo, String compressedName, boolean deleteSource, int 
compressionLevel);
 
+    public abstract Action createCompressAction(
+            String renameTo,
+            String compressedName,
+            boolean deleteSource,
+            int compressionLevel,
+            int maxCompressionDelaySeconds);
+
     public String getExtension() {
         return extension;
     }
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/AbstractAction.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/AbstractAction.java
index 2ca052835a..14258eec3f 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/AbstractAction.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/AbstractAction.java
@@ -82,6 +82,25 @@ public abstract class AbstractAction implements Action {
         interrupted = true;
     }
 
+    /**
+     * Blocks the current thread for a random delay up to {@code 
maxDelaySeconds}.
+     *
+     * @param maxDelaySeconds maximum delay in seconds before returning.
+     * @since 2.27.0
+     */
+    static void blockThread(final int maxDelaySeconds) {
+        if (maxDelaySeconds > 0) {
+            int delay = 
java.util.concurrent.ThreadLocalRandom.current().nextInt(maxDelaySeconds + 1);
+            if (delay > 0) {
+                try {
+                    Thread.sleep(delay * 1000L);
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+            }
+        }
+    }
+
     /**
      * Tests if the action is complete.
      *
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/CommonsCompressAction.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/CommonsCompressAction.java
index 1688969578..c01b2cb992 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/CommonsCompressAction.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/CommonsCompressAction.java
@@ -54,6 +54,11 @@ public final class CommonsCompressAction extends 
AbstractAction {
      */
     private final boolean deleteSource;
 
+    /**
+     * Maximum delay in seconds before compression.
+     */
+    private final int maxDelaySeconds;
+
     /**
      * Creates new instance of Bzip2CompressAction.
      *
@@ -65,12 +70,33 @@ public final class CommonsCompressAction extends 
AbstractAction {
      */
     public CommonsCompressAction(
             final String name, final File source, final File destination, 
final boolean deleteSource) {
+        this(name, source, destination, deleteSource, 0);
+    }
+
+    /**
+     * Creates new instance of Bzip2CompressAction.
+     *
+     * @param name the compressor name. One of "gz", "bzip2", "xz", "zst", 
"pack200", or "deflate".
+     * @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.
+     * @param maxDelaySeconds maximum delay in seconds before compression.
+     * @since 2.27.0
+     */
+    public CommonsCompressAction(
+            final String name,
+            final File source,
+            final File destination,
+            final boolean deleteSource,
+            final int maxDelaySeconds) {
         Objects.requireNonNull(source, "source");
         Objects.requireNonNull(destination, "destination");
         this.name = name;
         this.source = source;
         this.destination = destination;
         this.deleteSource = deleteSource;
+        this.maxDelaySeconds = maxDelaySeconds;
     }
 
     /**
@@ -81,6 +107,7 @@ public final class CommonsCompressAction extends 
AbstractAction {
      */
     @Override
     public boolean execute() throws IOException {
+        blockThread(maxDelaySeconds);
         return execute(name, source, destination, deleteSource);
     }
 
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/GzCompressAction.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/GzCompressAction.java
index acad1f5116..5747c638cd 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/GzCompressAction.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/GzCompressAction.java
@@ -55,6 +55,26 @@ public final class GzCompressAction extends AbstractAction {
      */
     private final int compressionLevel;
 
+    /**
+     * Maximum delay in seconds before compression.
+     */
+    private final int maxDelaySeconds;
+
+    private static int checkCompressionLevel(final int compressionLevel) {
+        final int minCompressionLevel = Deflater.DEFAULT_COMPRESSION;
+        final int maxCompressionLevel = Deflater.BEST_COMPRESSION;
+
+        if (compressionLevel < minCompressionLevel || compressionLevel > 
maxCompressionLevel) {
+            throw new IllegalArgumentException("GZIP compression level must be 
in the range ["
+                    + minCompressionLevel
+                    + ", "
+                    + maxCompressionLevel
+                    + "], got: "
+                    + compressionLevel);
+        }
+        return compressionLevel;
+    }
+
     /**
      * Create new instance of GzCompressAction.
      *
@@ -64,26 +84,46 @@ public final class GzCompressAction extends AbstractAction {
      *                     does not cause an exception to be thrown or affect 
return value.
      * @param compressionLevel
      *                     Gzip deflater compression level.
+     * @since 2.27.0
+     * @param maxDelaySeconds
+     *                     Maximum delay in seconds before compression.
      */
     public GzCompressAction(
-            final File source, final File destination, final boolean 
deleteSource, final int compressionLevel) {
+            final File source,
+            final File destination,
+            final boolean deleteSource,
+            final int compressionLevel,
+            final int maxDelaySeconds) {
         Objects.requireNonNull(source, "source");
         Objects.requireNonNull(destination, "destination");
 
         this.source = source;
         this.destination = destination;
         this.deleteSource = deleteSource;
-        this.compressionLevel = compressionLevel;
+        this.compressionLevel = checkCompressionLevel(compressionLevel);
+        this.maxDelaySeconds = maxDelaySeconds;
+    }
+
+    /**
+     * Creates a new instance.
+     * @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.
+     * @param compressionLevel Gzip deflater compression level.
+     */
+    public GzCompressAction(
+            final File source, final File destination, final boolean 
deleteSource, final int compressionLevel) {
+        this(source, destination, deleteSource, compressionLevel, 0);
     }
 
     /**
      * Prefer the constructor with compression level.
      *
-     * @deprecated Prefer {@link GzCompressAction#GzCompressAction(File, File, 
boolean, int)}.
+     * @deprecated Prefer {@link GzCompressAction#GzCompressAction(File, File, 
boolean, int, int)}.
      */
     @Deprecated
     public GzCompressAction(final File source, final File destination, final 
boolean deleteSource) {
-        this(source, destination, deleteSource, Deflater.DEFAULT_COMPRESSION);
+        this(source, destination, deleteSource, Deflater.DEFAULT_COMPRESSION, 
0);
     }
 
     /**
@@ -94,6 +134,7 @@ public final class GzCompressAction extends AbstractAction {
      */
     @Override
     public boolean execute() throws IOException {
+        blockThread(maxDelaySeconds);
         return execute(source, destination, deleteSource, compressionLevel);
     }
 
@@ -129,6 +170,7 @@ public final class GzCompressAction extends AbstractAction {
     public static boolean execute(
             final File source, final File destination, final boolean 
deleteSource, final int compressionLevel)
             throws IOException {
+        checkCompressionLevel(compressionLevel);
         if (source.exists()) {
             try (final FileInputStream fis = new FileInputStream(source);
                     final OutputStream fos = new FileOutputStream(destination);
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ZipCompressAction.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ZipCompressAction.java
index f29a7391ce..d8e7c39738 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ZipCompressAction.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/ZipCompressAction.java
@@ -51,6 +51,25 @@ public final class ZipCompressAction extends AbstractAction {
      */
     private final int level;
 
+    /**
+     * Maximum delay in seconds before compression.
+     */
+    private final int maxDelaySeconds;
+
+    /**
+     * Validates that the compression level is in the valid range [-1, 9].
+     *
+     * @param level the compression level to validate
+     * @return the level if valid
+     * @throws IllegalArgumentException if level is not in the range [-1, 9]
+     */
+    private static int checkLevel(final int level) {
+        if (level < java.util.zip.Deflater.DEFAULT_COMPRESSION || level > 9) {
+            throw new IllegalArgumentException("Compression level must be in 
the range [-1, 9], got: " + level);
+        }
+        return level;
+    }
+
     /**
      * Creates new instance of GzCompressAction.
      *
@@ -58,16 +77,37 @@ public final class ZipCompressAction extends AbstractAction 
{
      * @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.
-     * @param level TODO
+     * @param level the compression level
+     * @param maxDelaySeconds maximum delay in seconds before compression.
+     * @since 2.27.0
      */
-    public ZipCompressAction(final File source, final File destination, final 
boolean deleteSource, final int level) {
+    public ZipCompressAction(
+            final File source,
+            final File destination,
+            final boolean deleteSource,
+            final int level,
+            final int maxDelaySeconds) {
         Objects.requireNonNull(source, "source");
         Objects.requireNonNull(destination, "destination");
 
         this.source = source;
         this.destination = destination;
         this.deleteSource = deleteSource;
-        this.level = level;
+        this.level = checkLevel(level);
+        this.maxDelaySeconds = maxDelaySeconds;
+    }
+
+    /**
+     * Creates new instance.
+     *
+     * @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.
+     * @param level the compression level
+     */
+    public ZipCompressAction(final File source, final File destination, final 
boolean deleteSource, final int level) {
+        this(source, destination, deleteSource, level, 0);
     }
 
     /**
@@ -78,6 +118,7 @@ public final class ZipCompressAction extends AbstractAction {
      */
     @Override
     public boolean execute() throws IOException {
+        blockThread(maxDelaySeconds);
         return execute(source, destination, deleteSource, level);
     }
 
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/package-info.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/package-info.java
index 3737053030..85222541ad 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/package-info.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/action/package-info.java
@@ -18,7 +18,7 @@
  * Support classes for the Rolling File Appender.
  */
 @Export
-@Version("2.26.0")
+@Version("2.27.0")
 package org.apache.logging.log4j.core.appender.rolling.action;
 
 import org.osgi.annotation.bundle.Export;
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/package-info.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/package-info.java
index 9f4ea07804..21a4fd72e4 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/package-info.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/package-info.java
@@ -18,7 +18,7 @@
  * Rolling File Appender and support classes.
  */
 @Export
-@Version("2.26.0")
+@Version("2.27.0")
 package org.apache.logging.log4j.core.appender.rolling;
 
 import org.osgi.annotation.bundle.Export;
diff --git a/src/changelog/.2.x.x/4012_add_max_compression_delay.xml 
b/src/changelog/.2.x.x/4012_add_max_compression_delay.xml
new file mode 100644
index 0000000000..39cc883a15
--- /dev/null
+++ b/src/changelog/.2.x.x/4012_add_max_compression_delay.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="https://logging.apache.org/xml/ns";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+           https://logging.apache.org/xml/ns
+           https://logging.apache.org/xml/ns/log4j-changelog-0.xsd";
+       type="added">
+    <issue id="4012" 
link="https://github.com/apache/logging-log4j2/issues/4012"/>
+    <issue id="4071" 
link="https://github.com/apache/logging-log4j2/pull/4071"/>
+    <description format="asciidoc">
+        Added support for `maxCompressionDelaySeconds` in compression actions 
to proactively defer compression and reduce disk I/O pressure during rollover.
+    </description>
+</entry>
+
diff --git 
a/src/site/antora/modules/ROOT/pages/manual/appenders/rolling-file.adoc 
b/src/site/antora/modules/ROOT/pages/manual/appenders/rolling-file.adoc
index 1982182fd2..8dd9c91c0c 100644
--- a/src/site/antora/modules/ROOT/pages/manual/appenders/rolling-file.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/appenders/rolling-file.adoc
@@ -713,6 +713,15 @@ Minimum value for the <<conversion-pattern-integer,`%i`>> 
conversion pattern.
 Maximum value for the <<conversion-pattern-integer,`%i`>> conversion pattern.
 
 This attribute is **ignored** if 
<<DefaultRolloverStrategy-attr-fileIndex,`fileIndex`>> is set to `nomax`.
+
+| 
[[DefaultRolloverStrategy-attr-maxCompressionDelaySeconds]]maxCompressionDelaySeconds
+| `int`
+| `0`
+|
+Maximum random delay, in seconds, before compressing archived log files.
+
+Use this attribute to spread compression workload when many applications roll 
over at the same time.
+A value of `0` disables the delay and starts compression immediately.
 |===
 
 
xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-DefaultRolloverStrategy[{plugin-reference-marker}
 Plugin reference for `DefaultRolloverStrategy`]

Reply via email to