You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by pk...@apache.org on 2024/07/22 15:02:57 UTC
(logging-log4j2) branch doc/2.x/rolling-file updated (6a3e1ebe1c -> 18eb77d248)
This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a change to branch doc/2.x/rolling-file
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
discard 6a3e1ebe1c Revamp rolling file appender documentation
discard ccef35b8fa Tmp
new 18eb77d248 Revamp rolling file appender documentation
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (6a3e1ebe1c)
\
N -- N -- N refs/heads/doc/2.x/rolling-file (18eb77d248)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
(logging-log4j2) 01/01: Revamp rolling file appender documentation
Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a commit to branch doc/2.x/rolling-file
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 18eb77d248282c22000b4be26b36d9662c56fa52
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Thu Jul 11 13:27:14 2024 +0200
Revamp rolling file appender documentation
We split the documentation of rolling file appenders and minimize the repetition of configuration option descriptions and examples.
---
pom.xml | 7 +
src/site/antora/antora.tmpl.yml | 1 +
src/site/antora/antora.yml | 1 +
.../examples/manual/rolling-file/logrotate.json | 33 +
.../manual/rolling-file/logrotate.properties | 41 +
.../examples/manual/rolling-file/logrotate.xml | 42 +
.../examples/manual/rolling-file/logrotate.yaml | 37 +
.../examples/manual/rolling-file/per-month.json | 34 +
.../manual/rolling-file/per-month.properties | 40 +
.../examples/manual/rolling-file/per-month.xml | 44 +
.../examples/manual/rolling-file/per-month.yaml | 38 +
.../examples/manual/rolling-file/policies.json | 27 +
.../manual/rolling-file/policies.properties | 33 +
.../ROOT/examples/manual/rolling-file/policies.xml | 42 +
.../examples/manual/rolling-file/policies.yaml | 34 +
.../examples/manual/rolling-file/timestamped.json | 33 +
.../manual/rolling-file/timestamped.properties | 39 +
.../examples/manual/rolling-file/timestamped.xml | 43 +
.../examples/manual/rolling-file/timestamped.yaml | 37 +
src/site/antora/modules/ROOT/nav.adoc | 1 +
.../modules/ROOT/pages/manual/appenders.adoc | 1240 +--------------
.../modules/ROOT/pages/manual/pattern-layout.adoc | 4 +-
.../modules/ROOT/pages/manual/rolling-file.adoc | 1651 ++++++++++++++++++++
23 files changed, 2336 insertions(+), 1166 deletions(-)
diff --git a/pom.xml b/pom.xml
index ebafcd646e..f454a451b3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -331,6 +331,7 @@
<!-- Skipping `maven-site-plugin` globally. -->
<maven.site.skip>true</maven.site.skip>
<maven.site.deploy.skip>true</maven.site.deploy.skip>
+ <site-commons-compress.version>1.26.2</site-commons-compress.version>
<site-commons-csv.version>1.11.0</site-commons-csv.version>
<site-commons-logging.version>1.3.3</site-commons-logging.version>
<site-disruptor.version>4.0.0</site-disruptor.version>
@@ -728,6 +729,12 @@
<!-- Other dependencies -->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ <version>${site-commons-compress.version}</version>
+ </dependency>
+
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
diff --git a/src/site/antora/antora.tmpl.yml b/src/site/antora/antora.tmpl.yml
index f4d949bb08..bebb37808c 100644
--- a/src/site/antora/antora.tmpl.yml
+++ b/src/site/antora/antora.tmpl.yml
@@ -51,6 +51,7 @@ asciidoc:
lmax-disruptor-url: "https://lmax-exchange.github.io/disruptor/"
slf4j-url: "https://www.slf4j.org"
# Dependency versions
+ commons-compress-version: "${site-commons-compress.version}"
commons-csv-version: "${site-commons-csv.version}"
commons-logging-version: "${site-commons-logging.version}"
disruptor-version: "${site-disruptor.version}"
diff --git a/src/site/antora/antora.yml b/src/site/antora/antora.yml
index 7011915af0..5e39f80906 100644
--- a/src/site/antora/antora.yml
+++ b/src/site/antora/antora.yml
@@ -51,6 +51,7 @@ asciidoc:
lmax-disruptor-url: "https://lmax-exchange.github.io/disruptor/"
slf4j-url: "https://www.slf4j.org"
# Dependency versions
+ commons-compress-version: "1.2.3-commons-compress"
commons-csv-version: "1.2.3-commons-csv"
commons-logging-version: "1.2.3-commons-logging"
disruptor-version: "1.2.3-disruptor"
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.json b/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.json
new file mode 100644
index 0000000000..bf958940f3
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.json
@@ -0,0 +1,33 @@
+{
+ "Configuration": {
+ "Appenders": {
+ // tag::appender[]
+ "RollingFile": {
+ "name": "FILE",
+ "fileName": "/var/log/app.log",
+ "filePattern": "/var/log/app.log.%i.gz", // <1>
+ "JsonTemplateLayout": {},
+ "DefaultRolloverStrategy": {
+ "max": 15 // <2>
+ },
+ "Policies": {
+ "CronTriggeringPolicy": {
+ "schedule": "0 0 0 * * ?" // <3>
+ },
+ "SizeBasedTriggeringPolicy": {
+ "size": "100k" // <4>
+ }
+ }
+ }
+ // end::appender[]
+ },
+ "Loggers": {
+ "Root": {
+ "level": "INFO",
+ "AppenderRef": {
+ "ref": "FILE"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.properties b/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.properties
new file mode 100644
index 0000000000..fe9ebaefd2
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.properties
@@ -0,0 +1,41 @@
+#
+# 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.
+#
+##
+# tag::appender[]
+appender.0.type = RollingFile
+appender.0.name = FILE
+appender.0.fileName = /var/log/app.log
+# <1>
+appender.0.filePattern = /var/log/app.log.%i.gz
+
+appender.0.layout.type = JsonTemplateLayout
+
+appender.0.strategy.type = DefaultRolloveStrategy
+# <2>
+appender.0.strategy.max = 15
+
+appender.0.policy.type = Policies
+appender.0.policy.0.type = CronTriggeringPolicy
+# <3>
+appender.0.policy.0.schedule = 0 0 0 * * ?
+appender.0.policy.1.type = SizeBasedTriggeringPolicy
+# <4>
+appender.0.policy.1.size = 100k
+# end::appender[]
+
+rootLogger.level = INFO
+rootLogger.appenderRef.0.ref = FILE
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.xml b/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.xml
new file mode 100644
index 0000000000..a31cc80635
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.xml
@@ -0,0 +1,42 @@
+<?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 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-config-2.xsd">
+ <Appenders>
+ <!-- tag::appender[] -->
+ <RollingFile name="FILE"
+ fileName="/var/log/app.log"
+ filePattern="/var/log/app.log.%i.gz"> <!--1-->
+ <JsonTemplateLayout/>
+ <DefaultRolloverStrategy max="15"/> <!--2-->
+ <Policies>
+ <CronTriggeringPolicy schedule="0 0 0 * * ?"/> <!--3-->
+ <SizeBasedTriggeringPolicy size="100k"/> <!--4-->
+ </Policies>
+ </RollingFile>
+ <!-- end::appender[] -->
+ </Appenders>
+ <Loggers>
+ <Root level="INFO">
+ <AppenderRef ref="FILE"/>
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.yaml b/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.yaml
new file mode 100644
index 0000000000..4c1cd22456
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.yaml
@@ -0,0 +1,37 @@
+#
+# 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:
+ Appenders:
+ # tag::appender[]
+ RollingFile:
+ name: "FILE"
+ fileName: "/var/log/app.log"
+ filePattern: "/var/log/app.log.%i.gz" # <1>
+ JsonTemplateLayout: {}
+ DefaultRolloverStrategy:
+ max: 15 # <2>
+ Policies:
+ CronTriggeringPolicy:
+ schedule: "0 0 0 * * ?" # <3>
+ SizeBasedTriggeringPolicy:
+ size: "100k" # <4>
+ # end::appender[]
+ Loggers:
+ Root:
+ level: "INFO"
+ AppenderRef:
+ ref: "FILE"
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.json b/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.json
new file mode 100644
index 0000000000..90ff67f726
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.json
@@ -0,0 +1,34 @@
+{
+ "Configuration": {
+ "Appenders": {
+ // tag::appender[]
+ "RollingFile": {
+ "name": "FILE",
+ "filePattern": "/var/log/app-%{yyyy-MM}/%d{yyyy-MM-dd}.log.gz", // <1>
+ "JsonTemplateLayout": {},
+ "DirectWriteRolloverStrategy": {
+ "Delete": {
+ "basePath": "/var/log",
+ "maxDepth": 2, // <2>
+ "IfFileName": {
+ "glob": "app-*/*.log.gz"
+ },
+ "IfLastModified": {
+ "age": "P90D"
+ }
+ }
+ },
+ "TimeBasedTriggeringPolicy": {}
+ }
+ // end::appender[]
+ },
+ "Loggers": {
+ "Root": {
+ "level": "INFO",
+ "AppenderRef": {
+ "ref": "FILE"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.properties b/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.properties
new file mode 100644
index 0000000000..89d6e76843
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.properties
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+##
+# tag::appender[]
+appender.0.type = RollingFile
+appender.0.name = FILE
+# <1>
+appender.0.filePattern = /var/log/app-%d{yyyy-MM]/%d{yyyy-MM-dd}.log.gz
+
+appender.0.layout.type = JsonTemplateLayout
+
+appender.0.strategy.type = DirectWriteRolloverStrategy
+appender.0.strategy.delete.type = Delete
+appender.0.strategy.delete.basePath = /var/log
+# <2>
+appender.0.strategy.delete.maxDepth = 2
+appender.0.strategy.delete.0.type = IfFileName
+appender.0.strategy.delete.0.glob = app-*/*.log.gz
+appender.0.strategy.delete.1.type = IfLastModified
+appender.0.strategy.delete.1.age = P90D
+
+appender.0.policy.type = TimeBaseTriggeringPolicy
+# end::appender[]
+
+rootLogger.level = INFO
+rootLogger.appenderRef.0.ref = FILE
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.xml b/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.xml
new file mode 100644
index 0000000000..551186ade7
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.xml
@@ -0,0 +1,44 @@
+<?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 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-config-2.xsd">
+ <Appenders>
+ <!-- tag::appender[] -->
+ <RollingFile name="FILE"
+ filePattern="/var/log/app-%d{yyyy-MM}/%d{yyyy-MM-dd}.log.gz"> <!--1-->
+ <JsonTemplateLayout/>
+ <DirectWriteRolloverStrategy>
+ <Delete basePath="/var/log"
+ maxDepth="2"> <!--2-->
+ <IfFileName glob="app-*/*.log.gz"/>
+ <IfLastModified age="P90D"/>
+ </Delete>
+ </DirectWriteRolloverStrategy>
+ <TimeBasedTriggeringPolicy/>
+ </RollingFile>
+ <!-- end::appender[] -->
+ </Appenders>
+ <Loggers>
+ <Root level="INFO">
+ <AppenderRef ref="FILE"/>
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.yaml b/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.yaml
new file mode 100644
index 0000000000..4a760a7abf
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.yaml
@@ -0,0 +1,38 @@
+#
+# 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:
+ Appenders:
+ # tag::appender[]
+ RollingFile:
+ name: "FILE"
+ filePattern: "/var/log/app-%d{yyyy-MM}/%d{yyyy-MM-dd}.log.gz" # <1>
+ JsonTemplateLayout: {}
+ DirectWriteRolloverStrategy:
+ Delete:
+ basePath: "/var/log"
+ maxDepth: 2 # <2>
+ IfFileName:
+ glob: "app-*/*.log.gz"
+ IfLatModified:
+ age: "P90D"
+ TimeBasedTriggeringPolicy: {}
+ # end::appender[]
+ Loggers:
+ Root:
+ level: "INFO"
+ AppenderRef:
+ ref: "FILE"
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.json b/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.json
new file mode 100644
index 0000000000..8152e5c10e
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.json
@@ -0,0 +1,27 @@
+{
+ "Configuration": {
+ "Appenders": {
+ // tag::appender[]
+ "RollingFile": {
+ "name": "FILE",
+ "fileName": "app.log",
+ "filePattern": "app.%d{yyyy-MM-dd}.%i.log",
+ "JsonTemplateLayout": {},
+ "Policies": {
+ "OnStartupTriggeringPolicy": {},
+ "SizeBasedTriggeringPolicy": {},
+ "TimeBasedTriggeringPolicy": {}
+ }
+ }
+ // end::appender[]
+ },
+ "Loggers": {
+ "Root": {
+ "level": "INFO",
+ "AppenderRef": {
+ "ref": "FILE"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.properties b/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.properties
new file mode 100644
index 0000000000..dd1587c0ce
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.properties
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+##
+# tag::appender[]
+appender.0.type = RollingFile
+appender.0.name = FILE
+appender.0.fileName = app.log
+appender.0.filePattern = app.%d{yyyy-MM-dd}.%i.log
+
+appender.0.layout.type = JsonTemplateLayout
+
+appender.0.policy.type = Policies
+appender.0.policy.0.type = OnStartupTriggeringPolicy
+appender.0.policy.1.type = SizeBasedTriggeringPolicy
+appender.0.policy.2.type = TimeBasedTriggeringPolicy
+# end::appender[]
+
+rootLogger.level = INFO
+rootLogger.appenderRef.0.ref = FILE
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.xml b/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.xml
new file mode 100644
index 0000000000..7cdadd27c7
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.xml
@@ -0,0 +1,42 @@
+<?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 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-config-2.xsd">
+ <Appenders>
+ <!-- tag::appender[] -->
+ <RollingFile name="FILE"
+ fileName="app.log"
+ filePattern="app.%d{yyyy-MM-dd}.%i.log">
+ <JsonTemplateLayout/>
+ <Policies>
+ <OnStartupTriggeringPolicy/>
+ <SizeBasedTriggeringPolicy/>
+ <TimeBasedTriggeringPolicy/>
+ </Policies>
+ </RollingFile>
+ <!-- end::appender[] -->
+ </Appenders>
+ <Loggers>
+ <Root level="INFO">
+ <AppenderRef ref="FILE"/>
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.yaml b/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.yaml
new file mode 100644
index 0000000000..f40409e336
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.yaml
@@ -0,0 +1,34 @@
+#
+# 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:
+ Appenders:
+ # tag::appender[]
+ RollingFile:
+ name: "FILE"
+ fileName: "app.log"
+ filePattern: "app.%d{yyyy-MM-dd}.%i.log"
+ JsonTemplateLayout: {}
+ Policies:
+ OnStartupTriggeringPolicy: {}
+ SizeBasedTriggeringPolicy: {}
+ TimeBasedTriggeringPolicy: {}
+ # end::appender[]
+ Loggers:
+ Root:
+ level: "INFO"
+ AppenderRef:
+ ref: "FILE"
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.json b/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.json
new file mode 100644
index 0000000000..727a346a5e
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.json
@@ -0,0 +1,33 @@
+{
+ "Configuration": {
+ "Appenders": {
+ // tag::appender[]
+ "RollingFile": {
+ "name": "FILE",
+ "filePattern": "/var/log/app.%d{yyyy-MM-dd}.log.gz", // <1>
+ "JsonTemplateLayout": {},
+ "DirectWriteRolloverStrategy": {
+ "Delete": { // <2>
+ "basePath": "/var/log",
+ "IfFileName": {
+ "regex": "app\\.\\d{4}-\\d{2}-\\d{2}\\.log\\.gz"
+ },
+ "IfLastModified": {
+ "age": "P15D"
+ }
+ }
+ },
+ "TimeBasedTriggeringPolicy": {}
+ }
+ // end::appender[]
+ },
+ "Loggers": {
+ "Root": {
+ "level": "INFO",
+ "AppenderRef": {
+ "ref": "FILE"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.properties b/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.properties
new file mode 100644
index 0000000000..8d028a2e6c
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.properties
@@ -0,0 +1,39 @@
+#
+# 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.
+#
+##
+# tag::appender[]
+appender.0.type = RollingFile
+appender.0.name = FILE
+# <1>
+appender.0.filePattern = /var/log/app.%d{yyyy-MM-dd}.log.gz
+
+appender.0.layout.type = JsonTemplateLayout
+
+appender.0.strategy.type = DirectWriteRolloverStrategy
+# <2>
+appender.0.strategy.delete.type = Delete
+appender.0.strategy.delete.basePath = /var/log
+appender.0.strategy.delete.0.type = IfFileName
+appender.0.strategy.delete.0.regex = app\\.\\d{4}-\\d{2}-\\d{2}\\.log\\.gz
+appender.0.strategy.delete.1.type = IfLastModified
+appender.0.strategy.delete.1.age = P15D
+
+appender.0.policy.type = TimeBaseTriggeringPolicy
+# end::appender[]
+
+rootLogger.level = INFO
+rootLogger.appenderRef.0.ref = FILE
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.xml b/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.xml
new file mode 100644
index 0000000000..5dd9dfa148
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.xml
@@ -0,0 +1,43 @@
+<?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 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-config-2.xsd">
+ <Appenders>
+ <!-- tag::appender[] -->
+ <RollingFile name="FILE"
+ filePattern="/var/log/app.%d{yyyy-MM-dd}.log.gz"> <!--1-->
+ <JsonTemplateLayout/>
+ <DirectWriteRolloverStrategy>
+ <Delete basePath="/var/log"> <!--2-->
+ <IfFileName regex="app\.\d{4}-\d{2}-\d{2}\.log\.gz"/>
+ <IfLastModified age="P15D"/>
+ </Delete>
+ </DirectWriteRolloverStrategy>
+ <TimeBasedTriggeringPolicy/>
+ </RollingFile>
+ <!-- end::appender[] -->
+ </Appenders>
+ <Loggers>
+ <Root level="INFO">
+ <AppenderRef ref="FILE"/>
+ </Root>
+ </Loggers>
+</Configuration>
diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.yaml b/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.yaml
new file mode 100644
index 0000000000..dff185ed87
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.yaml
@@ -0,0 +1,37 @@
+#
+# 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:
+ Appenders:
+ # tag::appender[]
+ RollingFile:
+ name: "FILE"
+ filePattern: "/var/log/app.%d{yyyy-MM-dd}.log.gz" # <1>
+ JsonTemplateLayout: {}
+ DirectWriteRolloverStrategy:
+ Delete: # <2>
+ basePath: "/var/log"
+ IfFileName:
+ regex: "app\\.\\d{4}-\\d{2}-\\d{2}\\.log\\.gz"
+ IfLatModified:
+ age: "P15D"
+ TimeBasedTriggeringPolicy: {}
+ # end::appender[]
+ Loggers:
+ Root:
+ level: "INFO"
+ AppenderRef:
+ ref: "FILE"
diff --git a/src/site/antora/modules/ROOT/nav.adoc b/src/site/antora/modules/ROOT/nav.adoc
index 3362e67af0..820ee2380f 100644
--- a/src/site/antora/modules/ROOT/nav.adoc
+++ b/src/site/antora/modules/ROOT/nav.adoc
@@ -43,6 +43,7 @@
** xref:manual/systemproperties.adoc[]
** xref:manual/customconfig.adoc[]
** xref:manual/appenders.adoc[]
+*** xref:manual/rolling-file.adoc[]
** xref:manual/layouts.adoc[]
*** xref:manual/json-template-layout.adoc[]
*** xref:manual/pattern-layout.adoc[]
diff --git a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
index 12b25a09fa..5689bd36d5 100644
--- a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
@@ -42,11 +42,60 @@ For non-JDK classes, these should usually be in link:../javadoc/log4j-core/index
[#commons-concerns]
== Common concerns
-[#common-properties]
-=== Common properties
+[#buffering]
+=== Buffering
+
+Appenders that use stream-like resources (such as files, TCP connections) have an internal
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/ByteBuffer.html[`ByteBuffer`]
+that can be used to format each log event, before sending it to the underlying resource.
+The buffer is used if:
+
+* the
+xref:manual/systemproperties.adoc#log4j2.enableDirectEncoders[`log4j2.enableDirectEncoders`]
+configuration property is enabled,
+* or the <<bufferedIo,`bufferedIo`>> configuration attribute is enabled.
+
+The buffer is flushed to the underlying resource on three occasions:
+
+* if the buffer is full.
+* at the end of each log event batch, if
+xref:manual/async.adoc[asynchronous loggers]
+or
+<<AsyncAppender,appenders>>
+are used.
+* at the end of each log event, if the
+<<immediateFlush,`immediateFlush`>>
+configuration attribute is `true`.
These configuration attributes are shared by multiple appenders:
+[#bufferSize]
+==== `bufferSize`
+
+[cols="1h,5"]
+|===
+| Type
+| `int`
+
+| Default value
+| xref:manual/systemproperties.adoc#log4j2.encoderByteBufferSize[`log4j2.encoderByteBufferSize`]
+|===
+
+This configuration attribute specifies the size of the `ByteBuffer` used by the appender.
+
+[#bufferedIo]
+==== `bufferedIo`
+
+[cols="1h,5"]
+|===
+| Type | `boolean`
+| Default value | `true`
+|===
+
+If set to `true`, Log4j Core will use an internal `ByteBuffer` to store log events before sending them.
+
+If the xref:manual/systemproperties.adoc#log4j2.enableDirectEncoders[`log4j2.enableDirectEncoders`] configuration property is set to `true`, the internal `ByteBuffer` will always be used.
+
[#immediateFlush]
==== `immediateFlush`
@@ -56,15 +105,12 @@ These configuration attributes are shared by multiple appenders:
| Default value | `true`
|===
-If set to `true`, Log4j will flush all Java buffers at the end of each event:
+If set to `true`, Log4j will flush Log4j Core and Java buffers at the end of each event:
+* the internal `ByteBuffer` of the appender will be flushed.
* for appenders based on Java's
https://docs.oracle.com/javase/{java-target-version}/docs/api/java/io/OutputStream.html[`OutputStream`]
-a call to the `OutputStream.flush()` method is performed.
-* if xref:manual/systemproperties.adoc#log4j2.enableDirectEncoders[`log4j2.enableDirectEncoders`] is set to `true`, many Log4j appenders use a
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/ByteBuffer.html[`ByteBuffer`]
-to format log events before sending them to the underlying resource.
-Setting `immediateFlush` to `true` flushes these buffers at each event.
+a call to the `OutputStream.flush()` method will be performed.
[IMPORTANT]
====
@@ -72,11 +118,16 @@ This setting only guarantees that a byte representation of the log event is pass
It does not ensure that the operating system writes the event to the underlying storage.
====
+[TIP]
+====
+If you are using xref:manual/async.adoc[asynchronous loggers] or <<AsyncAppender,appenders>>, you can set this attribute to `false`.
+Log4j Core will still flush the internal buffer, whenever the log event queue becomes empty.
+====
+
[#runtime-evaluation]
=== Runtime evaluation of attributes
-The following configuration attributes are also evaluated at runtime,
-so can contain escaped `$$+{...}+` expressions.
+The following configuration attributes are also evaluated at runtime, so can contain escaped `$$+{...}+` expressions.
.List of attributes evaluated at runtime
[cols="1,1,1,1"]
@@ -103,20 +154,19 @@ so can contain escaped `$$+{...}+` expressions.
| Log event
| xref:manual/lookups.adoc#global-context[_global_]
-| <<RollingFileAppender,`RollingFileAppender`>>
-| <<RollingFileAppender-attr-filePattern,`filePattern`>>
+| xref:manual/rolling-file.adoc[`RollingFileAppender`]
+| xref:manual/rolling-file.adoc#attr-filePattern[`filePattern`]
| Rollover
| xref:manual/lookups.adoc#global-context[_global_]
-| <<CustomDeleteOnRollover,All `Delete` actions>>
+| xref:manual/rolling-file.adoc#CustomDeleteOnRollover[All `Delete` actions]
| `basePath`
| Rollover
| xref:manual/lookups.adoc#global-context[_global_]
|===
-The <<Routes,`Route`>> component of the <<RoutingAppender,`RoutingAppender`>> is special: its children are evaluated at runtime,
-but they are **not** evaluated at configuration time.
+The <<Routes,`Route`>> component of the <<RoutingAppender,`RoutingAppender`>> is special: its children are evaluated at runtime, but they are **not** evaluated at configuration time.
Inside the `Route` component you **should not** use escaped `$$+{...}+` expressions, but only unescaped `$+{...}+` expressions.
See xref:manual/configuration.adoc#lazy-property-substitution[runtime property substitution] for more details.
@@ -563,6 +613,16 @@ The FileAppender uses a FileManager (which extends OutputStreamManager) to perfo
While FileAppenders from different Configurations cannot be shared, the FileManagers can be if the Manager is accessible.
For example, two web applications in a servlet container can have their configuration and safely write to the same file if Log4j is in a ClassLoader that is common to both of them.
+[NOTE]
+====
+The xref:manual/appenders.adoc#FileAppender[FileAppender] does not offer a mechanism for external applications to force it to reopen the log file.
+External tools such as
+https://github.com/logrotate/logrotate[`logrotate`]
+cannot rotate log files without losing log events.
+
+If you want to rotate your log files, use xref:manual/rolling-file.adoc[a rolling file appender].
+====
+
.FileAppender Parameters
[width="100%",cols="20%,20%,60%",options="header",]
|=======================================================================
@@ -2326,8 +2386,7 @@ The OutputStreamAppender uses an OutputStreamManager to handle the actual I/O, a
The RandomAccessFileAppender is similar to the standard
<<FileAppender>> except it is always buffered (this cannot be switched off) and internally it uses a
`ByteBuffer + RandomAccessFile` instead of a `BufferedOutputStream`.
-We saw a 20-200% performance improvement compared to FileAppender with "bufferedIO=true" in our
-measurements.
+We saw a 20-200% performance improvement compared to FileAppender with "bufferedIO=true" in our measurements.
Similar to the FileAppender, RandomAccessFileAppender uses a RandomAccessFileManager to perform the file I/O. While RandomAccessFileAppender from different Configurations cannot be shared, the RandomAccessFileManagers can be if the Manager is accessible.
For example, two web applications in a servlet container can have their configuration and safely write to the same file if Log4j is in a ClassLoader that is common to both of them.
@@ -2564,1153 +2623,6 @@ The following configuration shows a RewriteAppender configured to map level INFO
</Configuration>
----
-[id=rollingfileappender]
-=== [[RollingFileAppender]] RollingFileAppender
-
-The RollingFileAppender is an OutputStreamAppender that writes to the file named in the fileName parameter and rolls the file over according to the `TriggeringPolicy` and the `RolloverPolicy`.
-The `RollingFileAppender`
-uses a `RollingFileManager` (which extends `OutputStreamManager`) to perform the file I/O and perform the rollover.
-While `RolloverFileAppenders` from different Configurations cannot be shared, the `RollingFileManagers` can be if the Manager is accessible.
-For example, two web applications in a servlet container can have their configuration and safely write to the same file if Log4j is in a
-`ClassLoader` that is common to both of them.
-
-A RollingFileAppender requires a <<TriggeringPolicy>> and a <<RolloverStrategies>>.
-The triggering policy determines if a rollover should be performed while the `RolloverStrategy`
-defines how the rollover should be done.
-If no `RolloverStrategy` is configured, `RollingFileAppender` will use the
-<<DefaultRolloverStrategy>>.
-Since log4j-2.5, a <<CustomDeleteOnRollover,custom delete action>> can be configured in the DefaultRolloverStrategy to run at rollover.
-Since 2.8 if no file name is configured then
-<<DirectWriteRolloverStrategy>> will be used instead of DefaultRolloverStrategy.
-Since log4j-2.9, a
-<<CustomPosixViewAttributeOnRollover,custom POSIX file attribute view action>> can be configured in the DefaultRolloverStrategy to run at rollover, if not defined, the inherited POSIX file attribute view from the RollingFileAppender will be applied.
-
-File locking is not supported by the RollingFileAppender.
-
-.RollingFileAppender Parameters
-[width="100%",cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|append |boolean |When true - the default, records will be appended to
-the end of the file. When set to false, the file will be cleared before
-new records are written.
-
-|bufferedIO |boolean |When true - the default, records will be written
-to a buffer and the data will be written to disk when the buffer is full
-or, if immediateFlush is set, when the record is written. File locking
-cannot be used with bufferedIO. Performance tests have shown that using
-buffered I/O significantly improves performance, even if immediateFlush
-is enabled.
-
-|bufferSize |int |When bufferedIO is true, this is the buffer size, the
-default is 8192 bytes.
-
-|createOnDemand |boolean |The appender creates the file on-demand. The
-appender only creates the file when a log event passes all filters and
-is routed to this appender. Defaults to false.
-
-|filter |Filter |A Filter to determine if the event should be handled by
-this Appender. More than one Filter may be used by using a
-CompositeFilter.
-
-|fileName |String |The name of the file to write to. If the file, or any
-of its parent directories, do not exist, they will be created.
-
-| [[RollingFileAppender-attr-filePattern]]filePattern
-| String
-a| The pattern of the archived log filename.
-
-The format of the pattern is dependent on the `RolloverStrategy` that is used.
-The standard rollover strategies accept:
-
-* xref:manual/configuration.adoc#lazy-property-substitution[runtime lookups],
-which are evaluated in
-xref:manual/lookups.adoc#global-context[a global context].
-* a `%d++{...}++` pattern, functionally identical to the
-xref:manual/pattern-layout.adoc#converter-date[homonymous `PatternLayout` pattern]
-except it uses the actual or inferred timestamp of the **previous** rollover.
-* a `%i` pattern that expands to the computed index for the archived file.
-
-All patterns accept also format specifiers, e.g. `%03i` prints the index as zero-padded number with 3 digits.
-
-will accept both a date/time pattern
-compatible with
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/text/SimpleDateFormat.html[`SimpleDateFormat`]
-and/or a %i which represents an integer counter.
-The integer counter
-allows specifying a padding, like %3i for space-padding the counter to
-3 digits or (usually more useful) %03i for zero-padding the counter to
-3 digits.
-The pattern also
-supports interpolation at runtime so any of the Lookups (such as the
-xref:manual/lookups.adoc#DateLookup[DateLookup]) can be included in the
-pattern.
-
-|immediateFlush |boolean a|
-When set to true - the default, each write will be followed by a flush.
-This will guarantee that the data is passed to the operating system for writing;
-it does not guarantee that the data is written to a physical device
-such as a disk drive.
-
-Note that if this flag is set to false, and the logging activity is sparse,
-there may be an indefinite delay in the data eventually making it to the
-operating system, because it is held up in a buffer.
-This can cause surprising effects such as the logs not
-appearing in the tail output of a file immediately after writing to the log.
-
-Flushing after every write is only useful when using this appender with
-synchronous loggers. Asynchronous loggers and appenders will
-automatically flush at the end of a batch of events, even if
-immediateFlush is set to false. This also guarantees the data is passed
-to the operating system but is more efficient.
-
-|layout |Layout |The Layout to use to format the LogEvent. If no layout
-is supplied the default pattern layout of "%m%n" will be used.
-
-|name |String |The name of the Appender.
-
-|policy |TriggeringPolicy |The policy to use to determine if a rollover
-should occur.
-
-|strategy |RolloverStrategy |The strategy to use to determine the name
-and the location of the archive file.
-
-|ignoreExceptions |boolean |The default is `true`, causing exceptions
-encountered while appending events to be internally logged and then
-ignored. When set to `false` exceptions will be propagated to the
-caller, instead. You must set this to `false` when wrapping this
-Appender in a <<FailoverAppender>>.
-
-|filePermissions |String a|
-File attribute permissions in POSIX format to apply whenever the file is
-created.
-
-The underlying files system shall support
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[POSIX]
-file attribute view.
-
-Examples: rw------- or rw-rw-rw- etc...
-
-|fileOwner |String a|
-File owner to define whenever the file is created.
-
-Changing the file's owner may be restricted for security reasons and
-Operation not permitted IOException thrown. Only processes with an
-effective user ID equal to the user ID of the file or with appropriate
-privileges may change the ownership of a file if
-http://www.gnu.org/software/libc/manual/html_node/Options-for-Files.html[_POSIX_CHOWN_RESTRICTED]
-is in effect for path.
-
-The underlying files system shall support file
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/FileOwnerAttributeView.html[owner]
-attribute view.
-
-|fileGroup |String a|
-File group to define whenever the file is created.
-
-The underlying files system shall support
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[POSIX]
-file attribute view.
-
-|=======================================================================
-
-[#TriggeringPolicies]
-=== TriggeringPolicies
-
-==== Composite Triggering Policy
-
-The `CompositeTriggeringPolicy` combines multiple triggering policies and returns true if any of the configured policies return true.
-The
-`CompositeTriggeringPolicy` is configured simply by wrapping other policies in a `Policies` element.
-
-For example, the following XML fragment defines policies that rollover the log when the JVM starts when the log size reaches twenty megabytes, and when the current date no longer matches the log's start date.
-
-[source,xml]
-----
-<Policies>
- <OnStartupTriggeringPolicy />
- <SizeBasedTriggeringPolicy size="20 MB" />
- <TimeBasedTriggeringPolicy />
-</Policies>
-----
-
-==== Cron Triggering Policy
-
-The `CronTriggeringPolicy` triggers rollover based on a cron expression.
-This policy is controlled by a timer and is asynchronous in processing log events, so it is possible that log events from the previous or next period may appear at the beginning or end of the log file.
-The `filePattern` attribute of the Appender should contain a timestamp otherwise the target file will be overwritten on each rollover.
-
-.CronTriggeringPolicy Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|schedule |String |The cron expression. The expression is the same as
-what is allowed in the Quartz scheduler. See
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/util/CronExpression.html[`CronExpression`]
-for a full description of the expression.
-
-|evaluateOnStartup |boolean |On startup the cron expression will be
-evaluated against the file's last modification timestamp. If the cron
-expression indicates a rollover should have occurred between that time
-and the current time the file will be immediately rolled over.
-|=======================================================================
-
-==== OnStartup Triggering Policy
-
-The `OnStartupTriggeringPolicy` policy causes a rollover if the log file is older than the current JVM's start time and the minimum file size is met or exceeded.
-
-.OnStartupTriggeringPolicy Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|minSize |long |The minimum size the file must have to roll over. A size
-of zero will cause a rollover no matter what the file size is. The
-default value is 1, which will prevent rolling over an empty file.
-|=======================================================================
-
-_Google App Engine note:_ +
-When running in Google App Engine, the OnStartup policy causes a rollover if the log file is older than _the time when Log4J initialized_.
-(Google App Engine restricts access to certain classes so Log4J cannot determine JVM start time with
-`java.lang.management.ManagementFactory.getRuntimeMXBean().getStartTime()`
-and falls back to Log4J initialization time instead.)
-
-[#sizebased-triggering-policy]
-==== SizeBased Triggering Policy
-
-The `SizeBasedTriggeringPolicy` causes a rollover once the file has reached the specified size.
-The size can be specified in bytes, with the suffix KB, MB, GB, or TB for example `20MB`.
-size.
-The size may also contain a fractional value such as `1.5 MB`.
-The size is evaluated using the Java root Locale so a period must always be used for the fractional unit.
-When combined with a time-based triggering policy the file pattern must contain a `%i`.
-Otherwise, the target file will be overwritten on every rollover as the SizeBased Triggering Policy will not cause the timestamp value in the file name to change.
-When used without a time-based triggering policy the SizeBased Triggering Policy will cause the timestamp value to change.
-
-[#timebased-triggering-policy]
-==== TimeBased Triggering Policy
-
-The `TimeBasedTriggeringPolicy` causes a rollover once the date/time pattern no longer applies to the active file.
-This policy accepts an
-`interval` attribute which indicates how frequently the rollover should occur based on the time pattern and a `modulate` boolean attribute.
-
-.TimeBasedTriggeringPolicy Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|interval |integer |How often a rollover should occur based on the most
-specific time unit in the date pattern. For example, with a date pattern
-with hours as the most specific item, an increment of 4 rollovers
-would occur every 4 hours. The default value is 1.
-
-|modulate |boolean |Indicates whether the interval should be adjusted to
-cause the next rollover to occur on the interval boundary. For example,
-if the item is hours, the current hour is 3 am and the interval is 4
-then the first rollover will occur at 4 am and then the next ones will occur
-at 8 am, noon, 4 pm, etc. The default value is false.
-
-|maxRandomDelay |integer |Indicates the maximum number of seconds to
-randomly delay a rollover. By default, this is 0 which indicates no
-delay. This setting is useful on servers where multiple applications are
-configured to roll over logfiles at the same time and can spread the
-load of doing so across time.
-|=======================================================================
-
-[#RolloverStrategies]
-=== RolloverStrategies
-
-[#DefaultRolloverStrategy]
-==== DefaultRolloverStrategy
-
-Default Rollover Strategy
-
-The default rollover strategy accepts both a date/time pattern and an integer from the `filePattern` attribute specified on the RollingFileAppender itself.
-If the date/time pattern 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", ".zip", ".bz2", ".deflate", ".pack200", or ".xz" the resulting archive will be compressed using the compression scheme that matches the suffix.
-The formats bzip2, Deflate, Pack200 and XZ require
-https://commons.apache.org/proper/commons-compress/index.html[Apache Commons Compress].
-In addition, XZ requires
-https://www.tukaani.org/xz/java.html[XZ for Java].
-The pattern may also contain lookup references that can be resolved at runtime such as shown in the example below.
-
-The default rollover strategy supports three variations for incrementing the counter.
-To illustrate how it works, suppose that the min attribute is set to 1, the max attribute is set to 3, the file name is "foo.log", and the file name pattern is "foo-%i.log".
-
-[cols="15%,15%,15%,55%",options="header",]
-|=======================================================================
-|Number of rollovers |Active output target |Archived log files
-|Description
-|0 |foo.log |- |All logging is going to the initial file.
-
-|1 |foo.log |foo-1.log |During the first rollover foo.log is renamed to
-foo-1.log. A new foo.log file is created and starts being written to.
-
-|2 |foo.log |foo-2.log, foo-1.log |During the second rollover foo.log is
-renamed to foo-2.log. A new foo.log file is created and starts being
-written to.
-
-|3 |foo.log |foo-3.log, foo-2.log, foo-1.log |During the third rollover
-foo.log is renamed to foo-3.log. A new foo.log file is created and
-starts being written to.
-
-|4 |foo.log |foo-3.log, foo-2.log, foo-1.log |In the fourth and
-subsequent rollovers, foo-1.log is deleted, foo-2.log is renamed to
-foo-1.log, foo-3.log is renamed to foo-2.log and foo.log is renamed to
-foo-3.log. A new foo.log file is created and starts being written to.
-|=======================================================================
-
-By way of contrast, when the `fileIndex` attribute is set to "min" all the other settings are the same the "fixed window" strategy will be performed.
-
-[cols="15%,15%,15%,55%",options="header",]
-|=======================================================================
-|Number of rollovers |Active output target |Archived log files
-|Description
-|0 |foo.log |- |All logging is going to the initial file.
-
-|1 |foo.log |foo-1.log |During the first rollover foo.log is renamed to
-foo-1.log. A new foo.log file is created and starts being written to.
-
-|2 |foo.log |foo-1.log, foo-2.log |During the second rollover foo-1.log
-is renamed to foo-2.log and foo.log is renamed to foo-1.log. A new
-foo.log file is created and starts being written to.
-
-|3 |foo.log |foo-1.log, foo-2.log, foo-3.log |During the third rollover
-foo-2.log is renamed to foo-3.log, foo-1.log is renamed to foo-2.log and
-foo.log is renamed to foo-1.log. A new foo.log file is created and
-starts being written to.
-
-|4 |foo.log |foo-1.log, foo-2.log, foo-3.log |In the fourth and
-subsequent rollovers, foo-3.log is deleted, foo-2.log is renamed to
-foo-3.log, foo-1.log is renamed to foo-2.log and foo.log is renamed to
-foo-1.log. A new foo.log file is created and starts being written to.
-|=======================================================================
-
-Finally, as of release 2.8, if the `fileIndex` attribute is set to `nomax`
-then the min and max values will be ignored and file numbering will increment by 1 and each rollover will have an incrementally higher value with no maximum number of files.
-
-.DefaultRolloverStrategy Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|fileIndex |String |If set to "max" (the default), files with a higher
-index will be newer than files with a smaller index. If set to "min",
-file renaming and the counter will follow the Fixed Window strategy
-described above.
-
-|min |integer |The minimum value of the counter. The default value is 1.
-
-|max |integer |The maximum value of the counter. Once this value is
-reached older archives will be deleted on subsequent rollovers. The
-default value is 7.
-
-|compressionLevel |integer |Sets the compression level, 0-9, where 0 =
-none, 1 = best speed, through 9 = best compression. Only implemented for
-ZIP files.
-
-|tempCompressedFilePattern |String |The pattern of the file name of the
-archived log file during compression.
-|=======================================================================
-
-[#DirectWriteRolloverStrategy]
-==== DirectWriteRolloverStrategy
-
-DirectWrite Rollover Strategy
-
-The DirectWriteRolloverStrategy causes log events to be written directly to files represented by the file pattern.
-With this strategy file renames are not performed.
-If the size-based triggering policy causes multiple files to be written during the specified period they will be numbered starting at one and continually incremented until a time-based rollover occurs.
-
-Warning: If the file pattern has a suffix indicating compression should take place the current file will not be compressed when the application is shut down.
-Furthermore, if the time changes such that the file pattern no longer matches the current file it will not be compressed at startup either.
-
-.DirectWriteRolloverStrategy Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|maxFiles |String |The maximum number of files to allow in the period matching
-the file pattern. If the number of files is exceeded the
-oldest file will be deleted. If specified, the value must be greater
-than 1. If the value is less than zero or omitted then the number of
-files will not be limited.
-
-|compressionLevel |integer |Sets the compression level, 0-9, where 0 =
-none, 1 = best speed, through 9 = best compression. Only implemented for
-ZIP files.
-
-|tempCompressedFilePattern |String |The pattern of the file name of the
-archived log file during compression.
-|=======================================================================
-
-Below is a sample configuration that uses a RollingFileAppender with both the time and size-based triggering policies will create up to 7 archives on the same day (1-7) that are stored in a directory based on the current year and month, and will compress each archive using gzip:
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Appenders>
- <RollingFile name="RollingFile" fileName="logs/app.log"
- filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy />
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- </RollingFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-This second example shows a rollover strategy that will keep up to 20 files before removing them.
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Appenders>
- <RollingFile name="RollingFile" fileName="logs/app.log"
- filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy />
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- <DefaultRolloverStrategy max="20"/>
- </RollingFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-Below is a sample configuration that uses a RollingFileAppender with both the time and size-based triggering policies will create up to 7 archives on the same day (1-7) that are stored in a directory based on the current year and month, and will compress each archive using gzip and will roll every 6 hours when the hour is divisible by 6:
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Appenders>
- <RollingFile name="RollingFile" fileName="logs/app.log"
- filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- </RollingFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-This sample configuration uses a RollingFileAppender with both the cron and size-based triggering policies, and writes directly to an unlimited number of archive files.
-The cron trigger causes a rollover every hour while the file size is limited to 250MB:
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Appenders>
- <RollingFile name="RollingFile" filePattern="logs/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
- </PatternLayout>
- <Policies>
- <CronTriggeringPolicy schedule="0 0 * * * ?"/>
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- </RollingFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-This sample configuration is the same as the previous one but limits the number of files saved each hour to 10:
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Appenders>
- <RollingFile name="RollingFile" filePattern="logs/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
- </PatternLayout>
- <Policies>
- <CronTriggeringPolicy schedule="0 0 * * * ?"/>
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- <DirectWriteRolloverStrategy maxFiles="10"/>
- </RollingFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-[#CustomDeleteOnRollover]
-==== CustomDeleteOnRollover
-
-Log Archive Retention Policy: Delete on Rollover
-
-Log4j-2.5 introduces a `Delete` action that gives users more control over what files are deleted at rollover time than what was possible with the DefaultRolloverStrategy `max` attribute.
-The Delete action lets users configure one or more conditions that select the files to delete relative to a base directory.
-
-Note that it is possible to delete any file, not just rolled-over log files, so use this action with care!
-With the `testMode` parameter you can test your configuration without accidentally deleting the wrong files.
-
-.Delete Parameters
-[width="100%",cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|basePath |String |_Required._ Base path from where to start scanning
-for files to delete.
-
-|maxDepth |int |The maximum number of levels of directories to visit. A
-value of 0 means that only the starting file (the base path itself) is
-visited unless denied by the security manager. A value of
-Integer.MAX_VALUE indicates that all levels should be visited. The
-default is 1, meaning only the files in the specified base directory.
-
-|followLinks |boolean |Whether to follow symbolic links. Default is
-false.
-
-|testMode |boolean |If true, files are not deleted but instead a message
-is printed to the xref:manual/status-logger.adoc[]
-at INFO level. Use this to do a dry run to test if the configuration
-works as expected. The default is false.
-
-|pathSorter |PathSorter |A plugin implementing the
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathSorter.html[`PathSorter`]
-interface to sort the files before selecting the files to delete. The
-default is to sort the most recently modified files first.
-
-|pathConditions [[DeletePathCondition]] |PathCondition[] a|
-_Required if no ScriptCondition is specified._ One or more PathCondition
-elements.
-
-If more than one condition is specified, they all need to accept a path
-before it is deleted. Conditions can be nested, in which case the inner
-condition(s) are evaluated only if the outer condition accepts the path.
-If conditions are not nested they may be evaluated in any order.
-
-Conditions can also be combined with the logical operators AND, OR and
-NOT by using the `IfAll`, `IfAny` and `IfNot` composite conditions.
-
-Users can create custom conditions or use the built-in conditions:
-
-* <<DeleteIfFileName,`IfFileName`>> - accepts files whose path
-(relative to the base path) matches a
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/regex/Pattern.html[regular
-expression] or a
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)[glob].
-* <<DeleteIfLastModified,`IfLastModified`>> - accepts files that are as
-old as or older than the specified
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/Duration.html#parse(CharSequence)[duration].
-* <<DeleteIfAccumulatedFileCount,`IfAccumulatedFileCount`>> - accepts
-paths after some count threshold is exceeded during the file tree walk.
-* <<DeleteIfAccumulatedFileSize,`IfAccumulatedFileSize`>> - accepts
-paths after the accumulated file size threshold is exceeded during the
-file tree walk.
-* IfAll - accepts a path if all nested conditions accept it (logical
-AND). Nested conditions may be evaluated in any order.
-* IfAny - accepts a path if one of the nested conditions accepts it
-(logical OR). Nested conditions may be evaluated in any order.
-* IfNot - accepts a path if the nested condition does not accept it
-(logical NOT).
-
-|scriptCondition [[DeleteScriptCondition]] |ScriptCondition a|
-_Required if no PathConditions are specified._ A ScriptCondition element
-specifying a script.
-
-The ScriptCondition should contain a <<ScriptCondition,`Script`, `ScriptRef`, or `ScriptFile`>> element that specifies the logic to be
-executed. (See also the xref:manual/filters.adoc#Script[ScriptFilter]
-documentation for more examples of configuring ScriptFiles and
-ScriptRefs.)
-
-The script is passed several <<ScriptParameters,parameters>>,
-including a list of paths found under the base path (up to `maxDepth`)
-and must return a list with the paths to delete.
-
-|=======================================================================
-
-[#DeleteIfFileName]
-=== DeleteIfFileName
-
-.IfFileName Condition Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|glob |String |_Required if regex is not specified._ Matches the relative
-path (relative to the base path) using a limited pattern language that
-resembles regular expressions but with a
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)[simpler
-syntax].
-
-|regex |String |_Required if glob not specified._ Matches the relative
-path (relative to the base path) using a regular expression as defined
-by the
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/regex/Pattern.html[`Pattern`]
-class.
-
-|nestedConditions |PathCondition[] |An optional set of nested
-<<DeletePathCondition,`PathCondition`>>s. If any nested conditions
-exist they all need to accept the file before it is deleted. Nested
-conditions are only evaluated if the outer condition accepts a file (if
-the path name matches).
-|=======================================================================
-
-[#DeleteIfLastModified]
-=== DeleteIfLastModified
-
-.IfLastModified Condition Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|age |String |_Required._ Specifies a
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/Duration.html#parse(CharSequence)[`duration`].
-The condition accepts files that are as old or older than the specified
-duration.
-
-|nestedConditions |PathCondition[] |An optional set of nested
-<<DeletePathCondition,`PathCondition`>>s. If any nested conditions
-exist they all need to accept the file before it is deleted. Nested
-conditions are only evaluated if the outer condition accepts a file (if
-the file is old enough).
-|=======================================================================
-
-[#DeleteIfAccumulatedFileCount]
-=== DeleteIfAccumulatedFileCount
-
-.IfAccumulatedFileCount Condition Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|exceeds |int |_Required._ The threshold count from which files will be
-deleted.
-
-|nestedConditions |PathCondition[] |An optional set of nested
-<<DeletePathCondition,`PathCondition`>>s. If any nested conditions
-exist they all need to accept the file before it is deleted. Nested
-conditions are only evaluated if the outer condition accepts a file (if
-the threshold count has been exceeded).
-|=======================================================================
-
-[#DeleteIfAccumulatedFileSize]
-=== DeleteIfAccumulatedFileSize
-
-.IfAccumulatedFileSize Condition Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|exceeds |String |_Required._ The threshold accumulated file size from
-which files will be deleted. The size can be specified in bytes, with
-the suffix KB, MB, GB, or TB, for example `20MB`.
-
-|nestedConditions |PathCondition[] |An optional set of nested
-<<DeletePathCondition,`PathCondition`>>s. If any nested conditions
-exist they all need to accept the file before it is deleted. Nested
-conditions are only evaluated if the outer condition accepts a file (if
-the threshold accumulated file size has been exceeded).
-|=======================================================================
-
-Below is a sample configuration that uses a RollingFileAppender with the cron triggering policy configured to trigger every day at midnight.
-Archives are stored in a directory based on the current year and month.
-All files under the base directory that match the "*/app-*.log.gz" glob and are 60 days old or older are deleted at rollover time.
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Properties>
- <Property name="baseDir">logs</Property>
- </Properties>
- <Appenders>
- <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
- filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd}.log.gz">
- <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
- <CronTriggeringPolicy schedule="0 0 0 * * ?"/>
- <DefaultRolloverStrategy>
- <Delete basePath="${baseDir}" maxDepth="2">
- <IfFileName glob="*/app-*.log.gz" />
- <IfLastModified age="60d" />
- </Delete>
- </DefaultRolloverStrategy>
- </RollingFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-Below is a sample configuration that uses a RollingFileAppender with both the time and size-based triggering policies will create up to 100 archives on the same day (1-100) that are stored in a directory based on the current year and month, and will compress each archive using gzip and will roll every hour.
-During every rollover, this configuration will delete files that match "*/app-*.log.gz" and are 30 days old or older, but keep the most recent 100 GB or the most recent 10 files, whichever comes first.
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Properties>
- <Property name="baseDir">logs</Property>
- </Properties>
- <Appenders>
- <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
- filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
- <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
- <Policies>
- <TimeBasedTriggeringPolicy />
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- <DefaultRolloverStrategy max="100">
- <!--
- Nested conditions: the inner condition is only evaluated on files
- for which the outer conditions are true.
- -->
- <Delete basePath="${baseDir}" maxDepth="2">
- <IfFileName glob="*/app-*.log.gz">
- <IfLastModified age="30d">
- <IfAny>
- <IfAccumulatedFileSize exceeds="100 GB" />
- <IfAccumulatedFileCount exceeds="10" />
- </IfAny>
- </IfLastModified>
- </IfFileName>
- </Delete>
- </DefaultRolloverStrategy>
- </RollingFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-[#ScriptCondition]
-=== ScriptCondition
-
-.ScriptCondition Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|script |Script, ScriptFile or ScriptRef |The Script element that
-specifies the logic to be executed. The script passes a list of paths
-found under the base path and must return the paths to delete as a
-`java.util.List<PathWithAttributes>`. See also the
-xref:manual/filters.adoc#Script[ScriptFilter] documentation for an example of
-how ScriptFiles and ScriptRefs can be configured.
-|=======================================================================
-
-[#ScriptParameters]
-=== ScriptParameters
-
-.Script Parameters
-[cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|basePath |`java.nio.file.Path` |The directory from where the Delete
-action started scanning for files to delete. Can be used to relativize
-the paths in the `pathList`.
-
-|pathList |`java.util.List<PathWithAttributes>` |The list of paths found
-under the base path up to the specified max depth, sorted most recently
-modified files first. The script is free to modify and return this list.
-
-|statusLogger |StatusLogger |The xref:manual/status-logger.adoc[] that can be used to log
-internal events during script execution.
-
-|configuration |Configuration |The Configuration that owns this
-ScriptCondition.
-
-|substitutor |StrSubstitutor |The StrSubstitutor used to replace lookup
-variables.
-
-|? |String |Any properties declared in the configuration.
-|=======================================================================
-
-Below is a sample configuration that uses a RollingFileAppender with the cron triggering policy configured to trigger every day at midnight.
-Archives are stored in a directory based on the current year and month.
-The script returns a list of rolled-over files under the base directory dated Friday the 13th.
-The Delete action will delete all files returned by the script.
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="trace" name="MyApp">
- <Properties>
- <Property name="baseDir">logs</Property>
- </Properties>
- <Appenders>
- <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
- filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyyMMdd}.log.gz">
- <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
- <CronTriggeringPolicy schedule="0 0 0 * * ?"/>
- <DefaultRolloverStrategy>
- <Delete basePath="${baseDir}" maxDepth="2">
- <ScriptCondition>
- <Script name="superstitious" language="groovy"><![CDATA[
- import java.nio.file.*;
-
- def result = [];
- def pattern = ~/\d*\/app-(\d*)\.log\.gz/;
-
- pathList.each { pathWithAttributes ->
- def relative = basePath.relativize pathWithAttributes.path
- statusLogger.trace 'SCRIPT: relative path=' + relative + " (base=$basePath)";
-
- // remove files dated Friday the 13th
-
- def matcher = pattern.matcher(relative.toString());
- if (matcher.find()) {
- def dateString = matcher.group(1);
- def calendar = Date.parse("yyyyMMdd", dateString).toCalendar();
- def friday13th = calendar.get(Calendar.DAY_OF_MONTH) [#13]
-== 13 \
- && calendar.get(Calendar.DAY_OF_WEEK) [#Calendar]
-== Calendar.FRIDAY;
- if (friday13th) {
- result.add pathWithAttributes;
- statusLogger.trace 'SCRIPT: deleting path ' + pathWithAttributes;
- }
- }
- }
- statusLogger.trace 'SCRIPT: returning ' + result;
- result;
- ]]>
- </Script>
- </ScriptCondition>
- </Delete>
- </DefaultRolloverStrategy>
- </RollingFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-[#CustomPosixViewAttributeOnRollover]
-=== CustomPosixViewAttributeOnRollover
-
-Log Archive File Attribute View Policy: Custom file attribute on Rollover
-
-Log4j-2.9 introduces a `PosixViewAttribute` action that gives users more control over which file attribute permissions, owner and group should be applied.
-The PosixViewAttribute action lets users configure one or more conditions that select the eligible files relative to a base directory.
-
-.PosixViewAttribute Parameters
-[width="100%",cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|basePath |String |_Required._ Base path from where to start scanning
-for files to apply attributes.
-
-|maxDepth |int |The maximum number of levels of directories to visit. A
-value of 0 means that only the starting file (the base path itself) is
-visited unless denied by the security manager. A value of
-Integer.MAX_VALUE indicates that all levels should be visited. The
-default is 1, meaning only the files in the specified base directory.
-
-|followLinks |boolean |Whether to follow symbolic links. Default is
-false.
-
-|pathConditions |PathCondition[] |see <<DeletePathCondition>>
-
-|filePermissions |String a|
-File attribute permissions in POSIX format to apply when action is
-executed.
-
-The underlying files system shall support
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[`POSIX`]
-file attribute view.
-
-Examples: rw------- or rw-rw-rw- etc...
-
-|fileOwner |String a|
-File owner to define when action is executed.
-
-Changing the file's owner may be restricted for security reasons and
-Operation not permitted IOException thrown. Only processes with an
-effective user ID equal to the user ID of the file or with appropriate
-privileges may change the ownership of a file if
-http://www.gnu.org/software/libc/manual/html_node/Options-for-Files.html[_POSIX_CHOWN_RESTRICTED]
-is in effect for path.
-
-The underlying files system shall support file
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/FileOwnerAttributeView.html[`owner`]
-attribute view.
-
-|fileGroup |String a|
-File group to define when action is executed.
-
-The underlying files system shall support
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[`POSIX`]
-file attribute view.
-
-|=======================================================================
-
-Below is a sample configuration that uses a RollingFileAppender and defines different POSIX file attribute views for current and rolled log files.
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="trace" name="MyApp">
- <Properties>
- <Property name="baseDir">logs</Property>
- </Properties>
- <Appenders>
- <RollingFile name="RollingFile" fileName="${baseDir}/app.log"
- filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyyMMdd}.log.gz"
- filePermissions="rw-------">
- <PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
- <CronTriggeringPolicy schedule="0 0 0 * * ?"/>
- <DefaultRolloverStrategy stopCustomActionsOnError="true">
- <PosixViewAttribute basePath="${baseDir}/$${date:yyyy-MM}" filePermissions="r--r--r--">
- <IfFileName glob="*.gz" />
- </PosixViewAttribute>
- </DefaultRolloverStrategy>
- </RollingFile>
- </Appenders>
-
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingFile"/>
- </Root>
- </Loggers>
-
-</Configuration>
-----
-
-[#RollingRandomAccessFileAppender]
-=== RollingRandomAccessFileAppender
-
-The RollingRandomAccessFileAppender is similar to the standard
-<<RollingFileAppender>> except it is always buffered (this cannot be switched off) and internally it uses a
-`ByteBuffer + RandomAccessFile` instead of a `BufferedOutputStream`.
-We saw a 20-200% performance improvement compared to RollingFileAppender with "bufferedIO=true" in our measurements.
-The
-`RollingRandomAccessFileAppender` writes to the file named in the fileName parameter and rolls the file over according to the TriggeringPolicy and the RolloverPolicy.
-Similar to the RollingFileAppender, RollingRandomAccessFileAppender uses a RollingRandomAccessFileManager to perform the file I/O and perform the rollover.
-While RollingRandomAccessFileAppender from different Configurations cannot be shared, the RollingRandomAccessFileManagers can be if the Manager is accessible.
-For example, two web applications in a servlet container can have their configuration and safely write to the same file if Log4j is in a ClassLoader that is common to both of them.
-
-A RollingRandomAccessFileAppender requires a
-<<TriggeringPolicies,triggering policy>> and a
-<<RolloverStrategies,rollover strategy>>.
-The triggering policy determines if a rollover should be performed while the `RolloverStrategy`
-defines how the rollover should be done.
-If no RolloverStrategy is configured, RollingRandomAccessFileAppender will use the
-<<DefaultRolloverStrategy>>.
-Since log4j-2.5, a <<CustomDeleteOnRollover,custom delete action>> can be configured in the DefaultRolloverStrategy to run at rollover.
-
-File locking is not supported by the RollingRandomAccessFileAppender.
-
-.RollingRandomAccessFileAppender Parameters
-[width="100%",cols="20%,20%,60%",options="header",]
-|=======================================================================
-|Parameter Name |Type |Description
-|append |boolean |When true - the default, records will be appended to
-the end of the file. When set to false, the file will be cleared before
-new records are written.
-
-|filter |Filter |A Filter to determine if the event should be handled by
-this Appender. More than one Filter may be used by using a
-CompositeFilter.
-
-|fileName |String |The name of the file to write to. If the file, or any
-of its parent directories, do not exist, they will be created.
-
-|filePattern |String |The pattern of the file name of the archived log
-file. The format of the pattern should is dependent on the
-RolloverPolicy that is used. The DefaultRolloverPolicy will accept both
-a date/time pattern compatible with
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/text/SimpleDateFormat.html[`SimpleDateFormat`]
-and/or a %i which represents an integer counter. The pattern also
-supports interpolation at runtime so any of the Lookups (such as the
-xref:manual/lookups.adoc#DateLookup[DateLookup] can be included in the
-pattern.
-
-|immediateFlush |boolean a|
-When set to true - the default, each write will be followed by a flush.
-This will guarantee the data is written to disk but could impact
-performance.
-
-Flushing after every write is only useful when using this appender with
-synchronous loggers. Asynchronous loggers and appenders will
-automatically flush at the end of a batch of events, even if
-immediateFlush is set to false. This also guarantees the data is written
-to disk but is more efficient.
-
-|bufferSize |int |The buffer size, defaults to 262,144 bytes (256 *
-1024).
-
-|layout |Layout |The Layout to use to format the LogEvent. If no layout
-is supplied the default pattern layout of "%m%n" will be used.
-
-|name |String |The name of the Appender.
-
-|policy |TriggeringPolicy |The policy to use to determine if a rollover
-should occur.
-
-|strategy |RolloverStrategy |The strategy to use to determine the name
-and the location of the archive file.
-
-|ignoreExceptions |boolean |The default is `true`, causing exceptions
-encountered while appending events to be internally logged and then
-ignored. When set to `false` exceptions will be propagated to the
-caller, instead. You must set this to `false` when wrapping this
-Appender in a <<FailoverAppender>>.
-
-|filePermissions |String a|
-File attribute permissions in POSIX format to apply whenever the file is
-created.
-
-The underlying files system shall support
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[`POSIX`]
-file attribute view.
-
-Examples: `rw-------` or `rw-rw-rw-` etc...
-
-|fileOwner |String a|
-File owner to define whenever the file is created.
-
-Changing the file's owner may be restricted for security reasons and
-Operation not permitted IOException thrown. Only processes with an
-effective user ID equal to the user ID of the file or with appropriate
-privileges may change the ownership of a file if
-http://www.gnu.org/software/libc/manual/html_node/Options-for-Files.html[_POSIX_CHOWN_RESTRICTED]
-is in effect for path.
-
-The underlying file system shall support file
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/FileOwnerAttributeView.html[`owner`]
-attribute view.
-
-|fileGroup |String a|
-File group to define whenever the file is created.
-
-The underlying files system shall support
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[`POSIX`]
-file attribute view.
-
-|=======================================================================
-
-==== Triggering Policies
-
-See <<TriggeringPolicies,RollingFileAppender Triggering Policies>>.
-
-==== Rollover Strategies
-
-See <<RolloverStrategies,`RollingFileAppender` rollover strategies>>.
-
-Below is a sample configuration that uses a RollingRandomAccessFileAppender with both the time and size-based triggering policies will create up to 7 archives on the same day (1-7) that are stored in a directory based on the current year and month, and will compress each archive using gzip:
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Appenders>
- <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log"
- filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy />
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- </RollingRandomAccessFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingRandomAccessFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-This second example shows a rollover strategy that will keep up to 20 files before removing them.
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Appenders>
- <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log"
- filePattern="logs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy />
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- <DefaultRolloverStrategy max="20"/>
- </RollingRandomAccessFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingRandomAccessFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
-Below is a sample configuration that uses a RollingRandomAccessFileAppender with both the time and size-based triggering policies will create up to 7 archives on the same day (1-7) that are stored in a directory based on the current year and month, and will compress each archive using gzip and will roll every 6 hours when the hour is divisible by 6:
-
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration status="warn" name="MyApp">
- <Appenders>
- <RollingRandomAccessFile name="RollingRandomAccessFile" fileName="logs/app.log"
- filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
- <PatternLayout>
- <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
- </PatternLayout>
- <Policies>
- <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
- <SizeBasedTriggeringPolicy size="250 MB"/>
- </Policies>
- </RollingRandomAccessFile>
- </Appenders>
- <Loggers>
- <Root level="error">
- <AppenderRef ref="RollingRandomAccessFile"/>
- </Root>
- </Loggers>
-</Configuration>
-----
-
[#RoutingAppender]
=== RoutingAppender
diff --git a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
index 3304ab8bec..f873e0b2f9 100644
--- a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
@@ -390,8 +390,8 @@ Outputs the date of the log event
.link:../javadoc/log4j-core/org/apache/logging/log4j/core/pattern/DatePatternConverter.html[`DatePatternConverter`] specifier grammar
[source,text]
----
-d{pattern}
-date{pattern}
+d{pattern}[{timezone}]
+date{pattern}[{timezone}]
----
The date conversion specifier may be followed by a set of braces containing a date and time pattern string per https://docs.oracle.com/javase/{java-target-version}/docs/api/java/text/SimpleDateFormat.html[`SimpleDateFormat`].
diff --git a/src/site/antora/modules/ROOT/pages/manual/rolling-file.adoc b/src/site/antora/modules/ROOT/pages/manual/rolling-file.adoc
new file mode 100644
index 0000000000..ae07f298b9
--- /dev/null
+++ b/src/site/antora/modules/ROOT/pages/manual/rolling-file.adoc
@@ -0,0 +1,1651 @@
+////
+ 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.
+////
+
+= Rolling file appenders
+:check-mark: ✓
+:open-book: 📖
+:x-mark: ✗
+
+Log4j Core provides multiple appenders that allow to archive the current log file and truncate it.
+
+[TIP]
+====
+The rolling file appenders support many configuration options.
+
+If you are just interested in some configuration examples, see the <<recipes>> section.
+====
+
+[#appenders]
+== Appenders
+
+Log4j Core provides two rolling file appenders:
+
+`RollingFile`::
+The `RollingFile` Appender uses
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/io/FileOutputStream.html[`FileOutputStream`]
+to access log files.
+
+`RollingRandomAccessFile`::
+The `RollingRandomAccessFile` Appender uses
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/io/RandomAccessFile.html[`RandomAccessFile`]
+to access log files.
+
+[NOTE]
+====
+Two appenders, even from different logger contexts, share a common
+xref:manual/architecture.adoc#AbstractManager[`RollingFileManager`] if:
+
+* they have the same non-null value of the <<attr-fileName,`fileName` attribute>>.
+* they have no `fileName` attribute, but have the same value of the <<attr-filePattern,`filePattern` attribute>>.
+
+Sharing a `RollingFileManager` guarantees that rollovers will occur only once, but requires most of the remaining configuration parameters to be the same.
+====
+
+[#common-configuration]
+=== Common configuration
+
+[#attributes]
+.Common configuration attributes
+[cols="1m,1,1,5"]
+|===
+| Attribute | Type | Default value | Description
+
+4+h| Required
+
+| [[attr-filePattern]]filePattern
+| https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html[`Path`]
+|
+| The pattern for the archived log files.
+See <<conversion-patterns>> for details
+
+If <<attr-fileName,`fileName`>> is `null`, the file pattern will also be used for the current file.
+
+| [[attr-name]]name
+| `String`
+|
+| The name of the appender.
+
+4+h| Optional
+
+| [[attr-bufferSize]]bufferSize
+| `int`
+| xref:manual/systemproperties.adoc#log4j2.encoderByteBufferSize[`8192`]
+a|
+The size of the
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/ByteBuffer.html[`ByteBuffer`]
+internally used by the appender.
+
+See xref:manual/appenders.adoc#buffering[Buffering] for more details.
+
+| [[attr-bufferedIo]]bufferedIo
+| `boolean`
+| `true`
+|
+If set to `true`, Log4j Core will format each log event in an internal buffer, before sending it to the underlying resource.
+
+The `RandomAccessRollingFile` Appender always enables the internal buffer.
+
+See xref:manual/appenders.adoc#buffering[Buffering] for more details.
+
+| [[attr-createOnDemand]]createOnDemand
+| boolean
+| `false`
+|
+The appender creates the file on-demand. The
+appender only creates the file when a log event passes all filters and
+is routed to this appender. Defaults to false.
+
+| [[attr-fileName]]fileName
+| https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/Path.html[`Path`]
+| `null`
+a| The path to the current log file, can be `null`.
+If the folder containing the file does not exist, it will be created.
+
+[WARNING]
+====
+This attribute should not contain any
+xref:manual/configuration.adoc#lazy-property-substitution[runtime lookups]
+nor pattern converters.
+
+To use pattern converters, see <<attr-filePattern,`filePattern`>>.
+====
+
+| [[attr-filePermissions]]filePermissions
+| https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFilePermissions.html[`PosixFilePermissions`]
+| `null`
+a|
+If not `null`, it specifies the POSIX file permissions to apply to each created file.
+The permissions must be provided in the format used by
+https://docs.oracle.com/javase/8/docs/api/java/nio/file/attribute/PosixFilePermissions.html#fromString-java.lang.String-[`PosixFilePermissions.fromString()`],
+e.g. `rw-rw----`.
+
+The underlying files system shall support
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[POSIX]
+file attribute view.
+
+| [[attr-fileOwner]]fileOwner
+| `String`
+| `null`
+|
+If not `null`, it specifies the file owner to apply to each created file.
+
+The underlying files system shall support file
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/FileOwnerAttributeView.html[owner]
+attribute view.
+
+| [[attr-fileGroup]]fileGroup
+| `String`
+| `null`
+|
+If not `null`, it specifies the file group owner to apply to each created file.
+
+The underlying files system shall support
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[POSIX]
+file attribute view.
+
+| [[attr-ignoreExceptions]]ignoreExceptions
+| `boolean`
+| `true`
+| If `false`, logging exception will be forwarded to the caller of the logging statement.
+Otherwise, they will be ignored.
+
+Logging exceptions are always also logged to xref:manual/status-logger.adoc[]
+
+| [[attr-immediateFlush]]immediateFlush
+| `boolean`
+| `true`
+|
+If set to `true`, the appender will flush its internal buffer after each event.
+
+See xref:manual/appenders.adoc#buffering[Buffering] for more details.
+
+|===
+
+[#elements]
+.Common nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[element-Filter]]xref:manual/filters.adoc[`Filter`]
+| zero or one
+|
+Allows filtering log events just before they are formatted and sent.
+
+See also xref:manual/filters.adoc#appender-stage[appender filtering stage].
+
+| [[element-Layout]]xref:manual/layouts.adoc[`Layout`]
+| zero or one
+|
+Formats log events.
+
+See xref:manual/layouts.adoc[] for more information.
+
+| [[element-TriggeringPolicy]]<<TriggeringPolicy,`TriggeringPolicy`>>
+| **one**
+|
+Determines when to archive the current log file.
+
+See <<TriggeringPolicy>> for more information.
+
+| [[element-RolloverStrategy]]<<RolloverStrategy,`RolloverStrategy`>>
+| zero or one
+|
+Determines the actions performed during a rollover.
+
+See <<RolloverStrategy>> for more information.
+
+|===
+
+[#conversion-patterns]
+=== Conversion patterns
+
+The `filePattern` attribute accepts the following pattern specifiers:
+
+* xref:manual/configuration.adoc#lazy-property-substitution[runtime lookups], which are evaluated in
+xref:manual/lookups.adoc#global-context[a global context].
+[[conversion-pattern-date]]
+* a `%d++{...}++` pattern, functionally identical to the
+xref:manual/pattern-layout.adoc#converter-date[homonymous `PatternLayout` pattern]
+except it uses the actual or inferred timestamp of the **previous** rollover.
+[[conversion-pattern-integer]]
+* a `%i` pattern that expands to the computed index for the archived file.
+
+All patterns accept also format specifiers, e.g. `%03i` prints the index as zero-padded number with 3 digits.
+
+[TIP]
+====
+The `+$${date:...}+` runtime lookup and `+%d{...}+` conversion pattern are not equivalent:
+
+* `+$${date:...}+` formats the **current** date.
+* `+%d{...}+` formats the date of the **previous** rollover.
+
+Setting the `filePattern` property to
+
+[source]
+----
+$${date:yyyy-MM}/%d{yyyy-MM-dd}.log
+----
+
+will write the `2024-06-30.log` log file into the `2024-07` directory.
+Consider using
+
+[source]
+----
+%d{yyyy-MM}/%d{yyyy-MM-dd}.log
+----
+
+instead.
+====
+
+[#RollingFileAppender]
+=== `RollingFile` configuration
+
+The `RollingFile` Appender provides the following configuration options, beyond the <<common-configuration,common ones>>:
+
+[#RollingFileAppender-attributes]
+.`RollingFile` configuration attributes
+[cols="1m,1,1,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[RollingFileAppender-attr-append]]append
+| `boolean`
+| `true`
+|
+If `true`, the log file will be opened in
+https://docs.oracle.com/javase/8/docs/api/java/nio/file/StandardOpenOption.html#APPEND[`APPEND` mode].
+
+On most systems this guarantees atomic writes to the end of the file, even if the file is opened by multiple applications.
+
+| [[RollingFileAppender-attr-locking]]locking
+| `boolean`
+| `false`
+|
+If `true`, Log4j will lock the log file at **each** log event.
+
+Note that the effects of this setting depend on the Operating System: some systems like most POSIX OSes do not offer mandatory locking, but only advisory file locking.
+
+This setting can also reduce the performance of the appender.
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-RollingFileAppender[{open-book} Plugin reference for `RollingFile`]
+
+[#RollingRandomAccessFileAppender]
+=== `RollingRandomAccessFile` configuration
+
+The `RollingRandomAccessFile` Appender provides the following configuration options, beyond the <<common-configuration,common ones>>:
+
+[#RollingRandomAccessFileAppender-attributes]
+.`RollingRandomAccessFile` configuration attributes
+[cols="1m,1,1,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[RollingRandomAccessFile-attr-append]]append
+| `boolean`
+| `true`
+|
+If `true`, the appender starts writing at the end of the file.
+
+This setting does not give the same atomicity guarantees as for the
+<<RollingFileAppender-attr-append,`RollingFile` Appender>>.
+The log file cannot be opened by multiple applications at the same time.
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-RollingRandomAccessFileAppender[{open-book} Plugin reference for `RollingRandomAccessFile`]
+
+[#TriggeringPolicy]
+== Triggering Policies
+
+Triggering policies are Log4j plugins that implement the
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/TriggeringPolicy.html[`TriggeringPolicy`]
+interface and are used to decide when is it time to rollover the current log file.
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-TriggeringPolicy[{open-book} Plugin reference for `TriggeringPolicy`]
+
+[#TriggeringPolicy-common]
+=== Common concerns
+
+Triggering policies usually decide to rollover a file based on two parameters:
+
+* the size of the current file.
++
+[NOTE]
+====
+While all JVMs can reliably check the size of a file, Log4j only checks it at startup and at each rollover and infers all file size changes, based on the size of logs delivered.
+If multiple managers are writing to the same file, the size computation will be off.
+====
+
+* the creation timestamp of the current file.
++
+[IMPORTANT]
+====
+Not all file systems support a creation timestamp.
+Most notably, POSIX does not specify such a timestamp, so the value used by Log4j might depend on the type of filesystem used and the JVM.
+If the creation timestamp is not available, the last modification timestamp is used, which might differ by up to a whole rollover period.
+
+See
+https://docs.oracle.com/javase/8/docs/api/java/nio/file/attribute/BasicFileAttributes.html#creationTime--[`BasicFileAttributes.creationTime()`]
+for more details.
+
+After the first rollover Log4j uses the timestamp of the rollover as creation timestamp.
+====
+
+[#OnStartupTriggeringPolicy]
+=== `OnStartupTriggeringPolicy`
+
+The `OnStartupTriggeringPolicy` policy causes a rollover only once during the lifetime of a JVM.
+A rollover will occur if the log file was created before the start time of the current JVM and the minimum file size is met or exceeded.
+
+[#OnStartupTriggeringPolicy-attributes]
+.`OnStartupTriggeringPolicy` configuration attributes
+[cols="1m,1,1,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[OnStartupTriggeringPolicy-attr-minSize]]minSize
+| `long`
+| `1`
+|
+The minimum size the file must have to roll over.
+
+|===
+
+[NOTE]
+====
+The `OnStartupTriggeringPolicy` uses JMX to retrieve the start time of the JVM.
+
+On platforms where JMX is absent or disabled, like Android or
+https://cloud.google.com/appengine[Google App Engine], the `OnStartupTriggeringPolicy` will use the timestamp, when its class was loaded instead.
+====
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-OnStartupTriggeringPolicy[{open-book} Plugin reference for `OnStartupTriggeringPolicy`]
+
+[#CronTriggeringPolicy]
+=== `CronTriggeringPolicy`
+
+The `CronTriggeringPolicy` triggers rollover based on a CRON expression.
+
+[NOTE]
+====
+The
+<<attr-filePattern,`filePattern`>>
+attribute of the Appender should contain a
+<<conversion-pattern-date,`+%d{...}+` timestamp>>, otherwise the target file will be overwritten on each rollover.
+====
+
+[WARNING]
+====
+This policy is controlled by a timer and is asynchronous in processing log events, so it is possible that log events from the previous or next period may appear at the beginning or end of the log file.
+====
+
+[#CronTriggeringPolicy-attributes]
+.`CronTriggeringPolicy` configuration attributes
+[cols="1m,1,2,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[CronTriggeringPolicy-attr-evaluateOnStartup]]evaluateOnStartup
+| boolean
+| `false`
+|
+On startup the cron expression will be evaluated against the current file's creation timestamp.
+If a rollover should have occurred between that time and the current time the file will be immediately rolled over.
+
+| [[CronTriggeringPolicy-attr-schedule]]schedule
+| link:..//javadoc/log4j-core/org/apache/logging/log4j/core/util/CronExpression.html[`CronExpression`]
+| `0 0 0 * * ?`
+a| The cron expression, using the same syntax as the
+https://www.quartz-scheduler.org/[Quartz scheduler].
+
+The supported fields are in order:
+
+* second
+* minute
+* hour
+* day of month
+* month
+* day of week
+
+See
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/util/CronExpression.html[`CronExpression`]
+for a full specification of the format.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-CronTriggeringPolicy[{open-book} Plugin reference for `CronTriggeringPolicy`]
+
+[#SizeBasedTriggeringPolicy]
+=== `SizeBasedTriggeringPolicy`
+
+The `SizeBasedTriggeringPolicy` causes a rollover once the file has reached the specified size.
+
+The size can be specified in bytes, with the suffix KB, MB, GB, or TB for example `20MB`.
+size.
+The size may also contain a fractional value such as `1.5 MB`.
+The size is evaluated using the Java root Locale so a period must always be used for the fractional unit.
+
+[NOTE]
+====
+When combined with a time-based triggering policy, the
+<<attr-filePattern,`filePattern`>>
+attribute of the Appender should contain an
+<<conversion-pattern-integer,`%i` conversion pattern>>.
+Otherwise, the target file will be overwritten on each rollover.
+====
+
+[#SizeBasedTriggeringPolicy-attributes]
+.`SizeBasedTriggeringPolicy` configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[SizeBasedTriggeringPolicy-attr-size]]size
+| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/FileSize.html[`FileSize`]
+| `10 MB`
+a|
+The maximum file size of the current log file.
+Once this size is reached, a rollover will occur.
+
+The syntax of this attribute is:
+----
+<number> [ " " ] [ <unit> ]
+----
+i.e.:
+
+* a number recognized by
+https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html#getInstance--[`NumberFormat`]
+* followed by optional whitespace
+* followed by an optional unit: `k`, `kB`, `M`, `MB`, `G`, `GB`, `T`, `TB`.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-SizeBasedTriggeringPolicy[{open-book} Plugin reference for `SizeBasedTriggeringPolicy`]
+
+[#TimeBasedTriggeringPolicy]
+=== `TimeBasedTriggeringPolicy`
+
+The `TimeBasedTriggeringPolicy` causes a rollover, when the smallest time unit in `filePattern` changes value.
+So the rollover can occur at the end of a month, week, at midnight, end of the hour, etc.
+
+[NOTE]
+====
+The
+<<attr-filePattern,`filePattern`>>
+attribute of the Appender should contain a
+<<conversion-pattern-date,`+%d{...}+` timestamp>>, otherwise the target file will be overwritten on each rollover.
+
+Multiple `%d` patterns can be used.
+The rollover frequency time unit will be determined by the last `%d` pattern.
+====
+
+[#TimeBasedTriggeringPolicy-attributes]
+.`TimeBasedTriggeringPolicy` configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[TimeBasedTriggeringPolicy-attr-interval]]interval
+| `int`
+| `1`
+|
+How often a rollover should occur based on the most
+specific time unit in the last `+%d{...}+` pattern.
+
+| [[TimeBasedTriggeringPolicy-attr-modulate]]modulate
+| `boolean`
+| `false`
+a|
+If `true`, the rollover will be aligned to a boundary of `interval` time units.
+
+For example, if the rotation frequency is hourly with an interval of `4` and the application starts at `3:14`:
+
+`false`::
+Will roll over at `3:00`, `7:00`, `11:00`, `15:00`, `19:00` and `23:00` each day.
+
+`true`::
+Will roll over at `0:00`, `4:00`, `8:00`, `12:00`, `16:00` and `20:00` each day.
+
+Only applies if <<TimeBasedTriggeringPolicy-attr-interval,`interval`>> is greater than `1`.
+
+| [[TimeBasedTriggeringPolicy-attr-maxRandomDelay]]maxRandomDelay
+| `int`
+| `0`
+|
+Indicates the maximum number of seconds to randomly delay a rollover.
+
+This setting is useful on servers where multiple applications are configured to roll over log files at the same time and can spread the load of doing so across time.
+|===
+
+[TIP]
+====
+When the rollover frequency is daily or lower, the rolling file appender will rotate files at midnight of the server's default timezone.
+
+You can modify the time of the rollover by specifying a different timezone in the `%d` pattern.
+See xref:manual/pattern-layout.adoc#converter-date[`date` converter syntax] for more details.
+====
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-TimeBasedTriggeringPolicy[{open-book} Plugin reference for `TimeBasedTriggeringPolicy`]
+
+[#Policies]
+=== Multiple policies
+
+A rolling file appender allows only **one** <<element-TriggeringPolicy,nested triggering policy element>>.
+If you wish to use multiple policies, you need to wrap them in a `Policies` element.
+The element itself has no configuration attributes.
+
+[WARNING]
+====
+The effects of using **both** time-based triggering policies (<<CronTriggeringPolicy>> and <<TimeBasedTriggeringPolicy>>) at the same time are undefined.
+====
+
+For example, the following XML fragment defines policies that rollover the log:
+
+* when the JVM starts.
+* when the log size reaches 10 MB.
+* at midnight local time.
+
+[tabs]
+====
+XML::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/policies.xml[`log4j2.xml`]
+[source,xml,indent=0]
+----
+include::example$manual/rolling-file/policies.xml[tag=appender]
+----
+
+JSON::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/policies.json[`log4j2.json`]
+[source,json,indent=0]
+----
+include::example$manual/rolling-file/policies.json[tag=appender]
+----
+
+YAML::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/policies.yaml[`log4j2.yaml`]
+[source,yaml,indent=0]
+----
+include::example$manual/rolling-file/policies.yaml[tag=appender]
+----
+
+Properties::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/policies.properties[`log4j2.properties`]
+[source,properties,indent=0]
+----
+include::example$manual/rolling-file/policies.properties[tag=appender]
+----
+====
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-CompositeTriggeringPolicy[{open-book} Plugin reference for `Policies`]
+
+[#RolloverStrategy]
+== Rollover strategies
+
+A rollover strategy determines how old archive files are rotated or deleted to make place for newer ones.
+The actions performed during a rollover include:
+
+* Renaming files in a cyclic way.
+See <<RolloverStrategy-index>> for more details.
+* Compression of archived log files.
+See <<RolloverStrategy-compress>> for more details.
+* Deletion of old archived log files.
+See <<DeleteAction>> for more details.
+* Changing the POSIX permissions of archived log files.
+See <<PosixViewAttributeAction>> for more details.
+
+There are two different rollover strategies available out of the box:
+
+`DefaultRolloverStrategy`::
+This is the default strategy used if the
+<<attr-fileName,`fileName` configuration attribute>>
+is specified.
+It stores the current log file in the location specified by `fileName` and the archived log files in the location specified by
+<<attr-filePattern,`filePattern`>>.
+
+`DirectWriteRolloverStrategy`::
+This is the default strategy used if the
+<<attr-fileName,`fileName` configuration attribute>>
+is `null`.
+It stores the current log file directly in its rolled over location specified by <<attr-filePattern,`filePattern`>>.
+
+[TIP]
+====
+Using runtime lookups in the `fileName` configuration attribute is discouraged, since it will break the logic of the `DefaultRolloverStrategy`.
+Use the `DirectWriteRolloverStrategy` instead by omitting the `fileName` attribute in your configuration.
+====
+
+[#RolloverStrategy-configuration]
+=== Common configuration
+
+Both rollover strategies support the following configuration parameters:
+
+[#RolloverStrategy-attributes]
+.Common rollover strategy configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[RolloverStrategy-attr-compressionLevel]]compressionLevel
+| `int`
+| `7`
+| Determine the compression level of archived log files.
+
+See <<RolloverStrategy-compress>> for more details.
+
+| [[RolloverStrategy-attr-tempCompressedFilePattern]]tempCompressedFilePattern
+| https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html[`Path`]
+|
+| Temporary location to store compressed files.
+
+See <<RolloverStrategy-compress>> for more details.
+
+| [[RolloverStrategy-attr-stopCustomActionsOnError]]stopCustomActionsOnError
+| `boolean`
+| `true`
+| If `true`, <<AbstractPathAction,custom actions>> will be stopped if one of them fails.
+|===
+
+[#RolloverStrategy-elements]
+.Common Rollover Strategy nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[element-Action]]link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/Action.html[`Action`]
+| zero or more
+|
+Additional actions to perform on a rollover beyond file rotation and compression.
+
+See <<AbstractPathAction>> for more details.
+|===
+
+[#DefaultRolloverStrategy]
+=== `DefaultRolloverStrategy` configuration
+
+The `DefaultRolloverStrategy` supports additional attributes that control the <<RolloverStrategy-index,incrementation of file indexes>>.
+
+[#DefaultRolloverStrategy-attributes]
+.`DefaultRolloverStrategy` configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[DefaultRolloverStrategy-attr-fileIndex]]fileIndex
+| _enumeration_
+| `max`
+a|
+Determines the strategy for determining the value of the <<conversion-pattern-integer,`%i`>> conversion pattern for the current log file.
+
+The supported values are:
+
+<<RolloverStrategy-index-min,`min`>>:: uses the value of the <<DefaultRolloverStrategy-attr-min,`min`>> attribute.
+<<RolloverStrategy-index-max,`max`>>:: uses the first unused integer between the <<DefaultRolloverStrategy-attr-min,`min`>> and <<DefaultRolloverStrategy-attr-max,`max`>> attributes.
+<<RolloverStrategy-index-nomax,`nomax`>>:: uses the first unused integer not lower than the value of the <<DefaultRolloverStrategy-attr-min,`min`>> attribute.
+
+| [[DefaultRolloverStrategy-attr-min]]min
+| `int`
+| `1`
+|
+Minimum value for the <<conversion-pattern-integer,`%i`>> conversion pattern.
+
+| [[DefaultRolloverStrategy-attr-max]]max
+| `int`
+| `7`
+|
+Maximum value for the <<conversion-pattern-integer,`%i`>> conversion pattern.
+
+This attribute is **ignored** if <<DefaultRolloverStrategy-attr-fileIndex,`fileIndex`>> is set to `nomax`.
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-DefaultRolloverStrategy[{open-book} Plugin reference for `DefaultRolloverStrategy`]
+
+[#DirectWriteRolloverStrategy]
+=== `DirectWriteRolloverStrategy` configuration
+
+The `DirectWriteRolloverStrategy` has a reduced set of configuration options for <<RolloverStrategy-index,incrementing the file index>>:
+
+* the minimum file index is always `1`.
+* the incrementing strategy is always <<RolloverStrategy-index-max,`max`>>.
+* the maximum file index can be configured using the following configuration attribute:
++
+[#DirectWriteRolloverStrategy-attributes]
+.`DirectWriteRolloverStrategy` configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[DirectWriteRolloverStrategy-attr-maxFiles]]maxFiles
+| `int`
+| `7`
+| Maximum value for the `%i` conversion pattern.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-DirectWriteRolloverStrategy[{open-book} Plugin reference for `DirectWriteRolloverStrategy`]
+
+[#RolloverStrategy-index]
+=== Incrementing file indexes
+
+During a rollover event, the current log file is moved to the location determined by evaluating
+<<attr-filePattern,`filePattern`>>, using <<DefaultRolloverStrategy-attr-min,`min`>> as value for the <<conversion-pattern-integer,`%i` conversion pattern>>.
+If an old log file is already present in that location, the rolling file appender:
+
+. Tries to increment the value of `%i` using the strategy specified by the <<DefaultRolloverStrategy-attr-fileIndex,`fileIndex` configuration attribute>>.
+. If that fails, it removes the oldest log file and rotates the remaining ones to make place for a new log archive.
+
+There are three strategies available:
+
+[#RolloverStrategy-index-min]
+`min`::
+Using the `min` strategy, the **newest** log file will have index `min` and the oldest one will have index `max`.
++
+[NOTE]
+====
+This is the log rotation strategy used by traditional UNIX tools and by Log4j 1.
+It is **not** the default strategy of Log4j 2.
+====
++
+Assuming `min="1"` and `max="3"` the rotation of the log files is represented in the graph below:
++
+[plantuml]
+....
+@startuml
+class "Initial status" as initial {
+ <color:green>app.log</color>
+}
+class "1st rollover" as first {
+ <color:green>app.log</color>
+ app.1.log
+}
+class "2nd rollover" as second {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+}
+class "3rd rollover" as third {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+ app.3.log
+}
+class "4th rollover" as fourth {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+ app.3.log
+}
+
+object "Delete file" as delete
+
+initial::app.log -> first::app.1.log
+
+first::app.log -> second::app.1.log
+first::app.1.log -> second::app.2.log
+
+second::app.log -> third::app.1.log
+second::app.1.log -> third::app.2.log
+second::app.2.log -> third::app.3.log
+
+third::app.log -> fourth::app.1.log
+third::app.1.log -> fourth::app.2.log
+third::app.2.log -> fourth::app.3.log
+third::app.3.log -[#red]-> delete
+@enduml
+....
+
+[#RolloverStrategy-index-max]
+`max`::
+Using the `max` strategy, the **oldest** log file will have index `min` and the newest one will have index `max`.
++
+[NOTE]
+====
+This is the default strategy since Log4j 2.
+====
++
+Assuming `min="1"` and `max="3"` the rotation of the log files is represented in the graph below:
++
+[plantuml]
+....
+@startuml
+class "Initial status" as initial {
+ <color:green>app.log</color>
+}
+class "1st rollover" as first {
+ <color:green>app.log</color>
+ app.1.log
+}
+class "2nd rollover" as second {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+}
+class "3rd rollover" as third {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+ app.3.log
+}
+class "4th rollover" as fourth {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+ app.3.log
+}
+
+object "Delete file" as delete
+
+initial::app.log -> first::app.1.log
+
+first::app.log -> second::app.2.log
+first::app.1.log -> second::app.1.log
+
+second::app.log -> third::app.3.log
+second::app.1.log -> third::app.1.log
+second::app.2.log -> third::app.2.log
+
+third::app.log -> fourth::app.3.log
+third::app.1.log -[#red]-> delete
+third::app.2.log -> fourth::app.1.log
+third::app.3.log -> fourth::app.2.log
+@enduml
+....
+
+[#RolloverStrategy-index-nomax]
+`nomax`::
++
+Using the `nomax` strategy no files will ever be deleted and newer archive files will be assigned increasing index numbers, starting from `min`.
++
+[plantuml]
+....
+@startuml
+class "Initial status" as initial {
+ <color:green>app.log</color>
+}
+class "1st rollover" as first {
+ <color:green>app.log</color>
+ app.1.log
+}
+class "2nd rollover" as second {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+}
+class "3rd rollover" as third {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+ app.3.log
+}
+class "4th rollover" as fourth {
+ <color:green>app.log</color>
+ app.1.log
+ app.2.log
+ app.3.log
+ app.4.log
+}
+
+initial::app.log -> first::app.1.log
+
+first::app.log -> second::app.2.log
+first::app.1.log -> second::app.1.log
+
+second::app.log -> third::app.3.log
+second::app.1.log -> third::app.1.log
+second::app.2.log -> third::app.2.log
+
+third::app.log -> fourth::app.4.log
+third::app.1.log -> fourth::app.1.log
+third::app.2.log -> fourth::app.2.log
+third::app.3.log -> fourth::app.3.log
+@enduml
+....
+
+[#RolloverStrategy-compress]
+=== Compressing archived files
+
+When the current log file is archived, the rolling file appender can compress it.
+Compression is activated, based on the extension of the archived file name.
+The following extensions are recognized:
+
+[cols="1,1,2"]
+|===
+| Extension | Supports `compressionLevel` | Description
+
+
+| [[RolloverStrategy-compress-zip]]`.zip`
+| {check-mark}
+| ZIP archive using the
+https://docs.oracle.com/javase/8/docs/api/java/util/zip/DeflaterOutputStream.html[DEFLATE]
+algorithm
+
+| [[RolloverStrategy-compress-gz]]`.gz`
+| {check-mark}
+| https://docs.oracle.com/javase/8/docs/api/java/util/zip/GZIPOutputStream.html[GZIP] archive using the DEFLATE algorithm
+
+| [[RolloverStrategy-compress-bz2]]`.bz2`<<commons-compress-dep,^dep^>>
+| {x-mark}
+|https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/compressors/bzip2/BZip2CompressorOutputStream.html[BZip2] algorithm
+
+| [[RolloverStrategy-compress-deflate]]`.deflate`<<commons-compress-dep,^dep^>>
+| {x-mark}
+| https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/compressors/deflate/DeflateCompressorOutputStream.html[DEFLATE] algorithm
+
+| [[RolloverStrategy-compress-pack200]]`.pack200`<<commons-compress-dep,^dep^>>
+| {x-mark}
+| https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/compressors/pack200/package-summary.html[Pack200] algorithm
+
+| [[RolloverStrategy-compress-xz]]`.xz` <<commons-compress-dep,^dep^>>
+| {x-mark}
+| https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/compressors/xz/package-summary.html[XZ] algorithm
+
+| [[RolloverStrategy-compress-zst]]`.zst` <<commons-compress-dep,^dep^>>
+| {x-mark}
+| https://commons.apache.org/proper/commons-compress/apidocs/org/apache/commons/compress/compressors/zstandard/package-summary.html[ZStandard] algorithm
+
+|===
+
+If the <<RolloverStrategy-attr-tempCompressedFilePattern,`tempCompressedFilePattern`>> attribute is set, the current log file:
+
+* will be compressed and stored in the location given by `tempCompressedFilePattern`
+* and then it will be moved to the location given by <<attr-filePattern,`filePattern`>>.
+
+[[commons-compress-dep]]
+^dep^::
+Additional dependencies are required to use these compression algorithms:
++
+[tabs]
+====
+Maven::
++
+[source,xml,subs=+attributes]
+----
+<dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-compress</artifactId>
+ <version>{commons-compress-version}</version>
+ <scope>runtime</scope>
+</dependency>
+----
+
+Gradle::
++
+[source,groovy,subs=+attributes]
+----
+runtimeOnly 'org.apache.commons:commons-compress:{commons-compress-version}'
+----
+
+====
++
+The `.xz` and `.zst` extensions require **additional** Commons Compress dependencies.
+See
+https://commons.apache.org/proper/commons-compress/index.html[Commons Compress documentation]
+for more details.
+
+[#AbstractPathAction]
+== Optional actions
+
+The rotation of files and compression is **always** handled automatically by the rolling file appenders.
+Since Log4j 2.6, additional actions can be configured manually.
+
+Log4j Core provides out-of-the-box two actions:
+
+* the <<DeleteAction>> to delete old log files after a rollover,
+* the <<PosixViewAttributeAction>> to change the POSIX permissions of old log files.
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-AbstractPathAction[{open-book} Plugin reference for `AbstractPathAction`]
+
+[#AbstractPathAction-config]
+=== Common action configuration
+
+Both actions support the following configuration attributes:
+
+[#AbstractPathAction-attributes]
+.Common action configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[AbstractPathAction-attr-basePath]]basePath
+| https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html[`Path`]
+|
+|
+It sets the base directory for the action.
+The action will be limited to files in this directory, and all paths will be relative to this directory.
+
+**Required**
+
+| [[AbstractPathAction-attr-followLinks]]followLinks
+| `boolean`
+| `false`
+a|
+If set to `true`, the action will follow symbolic links.
+
+[WARNING]
+====
+Setting this value to `true` will allow the action to access files outside <<AbstractPathAction-attr-basePath,`basePath`>>, which might introduce a security risk.
+====
+
+| [[AbstractPathAction-attr-maxDepth]]maxDepth
+| `int`
+| `1`
+| The maximum number of directory levels to visit.
+By default, the action does not recurse into subdirectories of <<AbstractPathAction-attr-basePath,`basePath`>>.
+
+|===
+
+[#AbstractPathAction-elements]
+.Common action nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[AbstractPathAction-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| zero or more
+| A set of path conditions.
+The action will only be performed on files for which the condition returns `true`.
+
+|===
+
+[#DeleteAction]
+=== `Delete` action
+
+The `Delete` Action deletes old log files that match the configured condition.
+
+[TIP]
+====
+A limited version of this action is performed automatically to <<RolloverStrategy-index,increment file indexes>>.
+
+You only need an explicit `Delete` Action if you use a <<conversion-pattern-date,`%d` pattern>>.
+====
+
+Besides the <<AbstractPathAction-config,common configuration options>> the `Delete` Action also supports the following options:
+
+[#DeleteAction-attributes]
+.`Delete` Action configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[DeleteAction-attr-testMode]]testMode
+| `boolean`
+| `false`
+|
+If `true`, no files will be deleted, but a xref:manual/status-logger.adoc[] message of level `INFO` will be issued instead.
+
+|===
+
+[#DeleteAction-elements]
+.`Delete` Action nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[DeleteAction-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| zero or more
+|
+If present, the action will only be performed on files for which the condition returns `true`.
+
+**Required**, unless a <<DeleteAction-element-ScriptCondition,`ScriptCondition`>> is provided, in which case these elements are ignored.
+
+| [[DeleteAction-element-PathSorter]]link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathSorter.html[`PathSorter`]
+| zero or one
+|
+Provides a sorting order for files contained in <<AbstractPathAction-attr-basePath,`basePath`>>.
+
+The default implementation is
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTime.html[`PathSortByModificationTime`],
+which sorts files by ascending modification timestamp.
+
+| [[DeleteAction-element-ScriptCondition]]<<ScriptCondition>>
+| zero or one
+| If present, all the <<DeleteAction-element-PathCondition,nested ``PathCondition``s>> are ignored and the provided script is executed to select the file to delete.
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-DeleteAction[{open-book} Plugin reference for `Delete`]
+
+[#PosixViewAttributeAction]
+=== `PosixViewAttribute` action
+
+This action allows modifying the POSIX attributes (owner, group and permissions) of archive log files.
+
+[NOTE]
+====
+By default, the POSIX attributes are inherited from the current log file.
+
+This action is only necessary if archived log files must have different attributes.
+====
+
+Besides the <<AbstractPathAction-config,common configuration options>> the `PosixViewAttribute` Action also supports the following options.
+
+[#PosixViewAttributeAction-attributes]
+.`PosixViewAttribute` Action configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+
+| [[PosixViewAttributeAction-attr-filePermissions]]filePermissions
+| https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFilePermissions.html[`PosixFilePermissions`]
+| `null`
+a|
+If not `null`, it specifies the POSIX file permissions to apply to each created file.
+The permissions must be provided in the format used by
+https://docs.oracle.com/javase/8/docs/api/java/nio/file/attribute/PosixFilePermissions.html#fromString-java.lang.String-[`PosixFilePermissions.fromString()`],
+e.g. `rw-rw----`.
+
+The underlying files system shall support
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[POSIX]
+file attribute view.
+
+| [[PosixViewAttributeAction-attr-fileOwner]]fileOwner
+| `String`
+| `null`
+|
+If not `null`, it specifies the file owner to apply to each created file.
+
+The underlying files system shall support file
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/FileOwnerAttributeView.html[owner]
+attribute view.
+
+| [[PosixViewAttributeAction-attr-fileGroup]]fileGroup
+| `String`
+| `null`
+|
+If not `null`, it specifies the file group owner to apply to each created file.
+
+The underlying files system shall support
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[POSIX]
+file attribute view.
+
+|===
+
+[#PosixViewAttributeAction-elements]
+.`PosixViewAttribute` Action nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[PosixViewAttributeAction-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| one or more
+|
+A set of conditions to select the files to modify.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-PosixViewAttributeAction[{open-book} Plugin reference for `PosixViewAttribute`]
+
+[#PathCondition]
+=== Path conditions
+
+To select the files for additional actions, Log4j provides the following path conditions:
+
+[#IfAccumulatedFileSize]
+==== `IfAccumulatedFileSize`
+
+When evaluated on a list of files, this condition sums the size of each file with the size of the preceding files.
+It returns `true` for files that exceed a configurable threshold.
+
+[IMPORTANT]
+====
+The result of this condition depends on the sorting order on files.
+See <<DeleteAction-element-PathSorter,`PathSorter`>> for more information.
+====
+
+[#IfAccumulatedFileSize-attributes]
+.`IfAccumulatedFileSize` configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[IfAccumulatedFileSize-attr-exceeds]]exceeds
+| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/FileSize.html[`FileSize`]
+|
+|
+The threshold size for the condition to match.
+
+Admits the same syntax as the <<SizeBasedTriggeringPolicy-attr-size,`size` attribute of `SizeBasedTriggeringPolicy`>>.
+
+**Required**
+
+|===
+
+.`IfAccumulatedFileSize` nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[IfAccumulatedFileSize-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| zero or more
+| A set of optional nested conditions.
+This condition matches only if **all** the nested conditions also match.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-IfAccumulatedFileSize[{open-book} Plugin reference for `IfAccumulatedFileSize`]
+
+[#IfAccumulatedFileCount]
+==== `IfAccumulatedFileCount`
+
+When evaluated on a list of files, this condition returns `true` if the 1-based index of a file exceeds a configurable threshold.
+
+[IMPORTANT]
+====
+The result of this condition depends on the sorting order on files.
+See <<DeleteAction-element-PathSorter,`PathSorter`>> for more information.
+====
+
+[#IfAccumulatedFileCount-attributes]
+.`IfAccumulatedFileCount` configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[IfAccumulatedFileCount-attr-exceeds]]exceeds
+| `int`
+|
+|
+The threshold for the condition to match.
+
+**Required**
+
+|===
+
+.`IfAccumulatedFileCount` nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[IfAccumulatedFileCount-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| zero or more
+| A set of optional nested conditions.
+This condition matches only if **all** the nested conditions also match.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-IfAccumulatedFileCount[{open-book} Plugin reference for `IfAccumulatedFileCount`]
+
+[#IfFileName]
+==== `IfFileName`
+
+Matches files based on their path **relative** to the base directory.
+
+[#IfFileName-attributes]
+.`IfFileName` configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[IfFileName-attr-glob]]glob
+| String
+|
+|
+Matches the path relative to the base directory using a `glob` pattern.
+
+See
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)[`FileSystem.getPathMatcher()`]
+for the supported `glob` syntax.
+
+**Required**, unless <<IfFileName-attr-regex,`regex`>> is specified.
+
+| [[IfFileName-attr-regex]]regex
+| https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/regex/Pattern.html[`Pattern`]
+|
+|
+Matches the path relative to the directory using a regular expression.
+
+See
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/regex/Pattern.html[`Pattern`]
+for the supported regular expression syntax.
+
+**Required**, unless <<IfFileName-attr-glob,`glob`>> is specified.
+|===
+
+.`IfFileName` nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[IfFileName-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| zero or more
+| A set of optional nested conditions.
+This condition matches only if **all** the nested conditions also match.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-IfFileName[{open-book} Plugin reference for `IfFileName`]
+
+[#IfLastModified]
+==== `IfLastModified`
+
+Accepts files based on their last modification timestamp.
+
+[#IfLastModified-attributes]
+.`IfLastModified` configuration attributes
+[cols="1m,1,,5"]
+|===
+| Attribute | Type | Default value | Description
+
+| [[IfLastModified-attr-age]]age
+| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/Duration.html[`Duration`]
+|
+| The condition accepts files that are as old or older than the specified duration.
+
+**Required**
+|===
+
+.`IfLastModified` nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[IfLastModified-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| zero or more
+| A set of optional nested conditions.
+This condition matches only if **all** the nested conditions also match.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-IfLastModified[{open-book} Plugin reference for `IfLastModified`]
+
+[#IfNot]
+==== `IfNot`
+
+Negates the result of the nested condition.
+
+.`IfNot` nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[IfNot-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| **one**
+| The path condition to negate.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-IfNot[{open-book} Plugin reference for `IfNot`]
+
+[#IfAll]
+==== `IfAll`
+
+Accepts a file if all the nested conditions are true.
+
+.`IfAll` nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[IfAll-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| one or more
+| The nested conditions to check.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-IfAll[{open-book} Plugin reference for `IfAll`]
+
+[#IfAny]
+==== `IfAny`
+
+.`IfAny` nested elements
+[cols="1m,1,4"]
+|===
+| Type | Multiplicity | Description
+
+| [[IfAny-element-PathCondition]]<<PathCondition,`PathCondition`>>
+| one or more
+| The nested conditions to check.
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-IfAny[{open-book} Plugin reference for `IfAny`]
+
+[#ScriptCondition]
+=== `ScriptCondition`
+
+The `ScriptCondition` uses a JSR 223 script to determine a list of matching files.
+
+Its configuration consists of a single nested script element:
+
+.`ScriptCondition` nested elements
+[cols="3,1,4"]
+|===
+| Type | Multiplicity | Description
+
+|
+xref:manual/scripts.adoc#Script[`Script`],
+xref:manual/scripts.adoc#ScriptFile[`ScriptFile`]
+or
+xref:manual/scripts.adoc#ScriptRef[`ScriptRef`]
+| **one**
+| A reference to the script to execute.
+
+See xref:manual/scripts.adoc[Scripts] for more details about scripting.
+|===
+
+The script must return a list of
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html[`PathWithAttributes`]
+objects and supports the following bindings:
+
+[#ScriptFilter-bindings]
+.Script Bindings
+[cols="1m,1,4"]
+|===
+| Binding name | Type | Description
+
+| [[ScriptFilter-binding-basePath]]basePath
+| https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html[`Path`]
+| The path of the base directory.
+
+| [[ScriptFilter-binding-configuration]]configuration
+| xref:manual/configuration.adoc[`Configuration`]
+|
+The `Configuration` object.
+
+| [[ScriptFilter-binding-pathList]]pathList
+| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html[`List<PathWithAttributes>`]
+|
+The list of files contained in the base directory.
+
+The paths are obtained by
+https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html#resolve-java.nio.file.Path-[resolving]
+the relative file names against
+<<ScriptFilter-binding-basePath,`basePath`>>.
+
+| [[ScriptFilter-binding-substitutor]]substitutor
+| link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrSubstitutor.html[`StrSubstitutor`]
+| The `StrSubstitutor` used to replace lookup variables.
+
+| [[ScriptFilter-binding-statusLogger]]statusLogger
+| link:../javadoc/log4j-core/org/apache/logging/log4j/core/Logger.html[`Logger`]
+| The xref:manual/status-logger.adoc[] to used by diagnostic messages in the script.
+
+| <key>
+| `String`
+| If `<key>` is not one of the above, it will be bound to the value given by
+xref:manual/configuration.adoc#property-substitution[the global `Properties` configuration element.]
+
+|===
+
+xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rolling-action-ScriptCondition[{open-book} Plugin reference for `ScriptCondition`]
+
+[#recipes]
+== Configuration recipes
+
+[#logrotate-daily]
+=== `logrotate` equivalent configuration
+
+https://github.com/logrotate/logrotate[`Logrotate`] is a common UNIX utility that rotates log files.
+
+Since a Java application cannot be notified that the log files need to be reloaded `logrotate` can be used with Java application through its `copytruncate` option (see
+https://man7.org/linux/man-pages/man8/logrotate.8.html[`logrotate(8)` man page]).
+A sample `logrotate` configuration file might therefore look like:
+
+[source]
+----
+/var/log/app.log {
+ copytruncate
+ compress
+ rotate 15
+ daily
+ maxsize 100k
+}
+----
+
+This configuration has a problem, which is explained in the documentation of the `copytruncate` option:
+
+[quote]
+Note that there is a very small time slice between copying the file and truncating it, so some logging data might be lost.
+
+Fortunately you can replace the usage of `logrotate` with a rolling file appender.
+An equivalent configuration will look like this:
+
+[tabs]
+====
+XML::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/logrotate.xml[`log4j2.xml`]
+[source,xml,indent=0]
+----
+include::example$manual/rolling-file/logrotate.xml[tag=appender]
+----
+
+JSON::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/logrotate.json[`log4j2.json`]
+[source,json,indent=0]
+----
+include::example$manual/rolling-file/logrotate.json[tag=appender]
+----
+
+YAML::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/logrotate.yaml[`log4j2.yaml`]
+[source,yaml,indent=0]
+----
+include::example$manual/rolling-file/logrotate.yaml[tag=appender]
+----
+
+Properties::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/logrotate.properties[`log4j2.properties`]
+[source,properties,indent=0]
+----
+include::example$manual/rolling-file/logrotate.properties[tag=appender]
+----
+====
+
+<1> Equivalent to `compress`: archived files are compressed.
+<2> Equivalent to `rotate 15`: only the `15` latest log files are kept.
+<3> Equivalent to `daily`: logs will be rotated at midnight of each day.
+<4> Equivalent to `maxsize 100k`: logs will be rotated if they exceed 100 kB of size.
+
+[#timestamped]
+=== Timestamped log file names
+
+The following configuration creates one log file every day and deletes those more than 15 days old.
+
+[NOTE]
+====
+Since we have a `%d` pattern in the configuration file, we need to use an explicit <<DeleteAction>>.
+====
+
+[tabs]
+====
+XML::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/timestamped.xml[`log4j2.xml`]
+[source,xml,indent=0]
+----
+include::example$manual/rolling-file/timestamped.xml[tag=appender]
+----
+
+JSON::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/timestamped.json[`log4j2.json`]
+[source,json,indent=0]
+----
+include::example$manual/rolling-file/timestamped.json[tag=appender]
+----
+
+YAML::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/timestamped.yaml[`log4j2.yaml`]
+[source,yaml,indent=0]
+----
+include::example$manual/rolling-file/timestamped.yaml[tag=appender]
+----
+
+Properties::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/timestamped.properties[`log4j2.properties`]
+[source,properties,indent=0]
+----
+include::example$manual/rolling-file/timestamped.properties[tag=appender]
+----
+====
+
+<1> Only the `filePattern` attribute is used, since we use the <<DirectWriteRolloverStrategy,`DirectWriteRolloverStrategy`>>.
+<2> An explicit `Delete` action is provided
+
+[#per-month]
+=== Separate folder per month
+
+We can also create separate folders for temporarily related files.
+In the example below, we create a different folder for each month:
+
+[tabs]
+====
+XML::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/per-month.xml[`log4j2.xml`]
+[source,xml,indent=0]
+----
+include::example$manual/rolling-file/per-month.xml[tag=appender]
+----
+
+JSON::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/per-month.json[`log4j2.json`]
+[source,json,indent=0]
+----
+include::example$manual/rolling-file/per-month.json[tag=appender]
+----
+
+YAML::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/per-month.yaml[`log4j2.yaml`]
+[source,yaml,indent=0]
+----
+include::example$manual/rolling-file/per-month.yaml[tag=appender]
+----
+
+Properties::
++
+.Snippet from an example {antora-examples-url}/manual/rolling-file/per-month.properties[`log4j2.properties`]
+[source,properties,indent=0]
+----
+include::example$manual/rolling-file/per-month.properties[tag=appender]
+----
+====
+
+<1> We use two `%d` patterns to specify the folder and file name.
+<2> We increase the recursion depth of the `Delete` action to extend to subfolders of the base directory.