From eaae9e381181066856565706551f4746e8ab5102 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Thu, 25 Jul 2024 11:50:22 +0200 Subject: [PATCH] Revamp file and delegating appenders This PR splits the documentation of file appenders and the `Async`, `Failover`, `Rewrite` and `Routing` appenders into their own files. As in the previous PRs we: * check and reformat the configuration options, * add links to the Plugin Reference, * improve the readability of the description by shortening it and reformatting it, * remove examples to provide smaller ones that make the same point. Part of #2528. --- pom.xml | 14 + src/site/antora/antora.tmpl.yml | 2 + src/site/antora/antora.yml | 2 + .../manual/appenders/delegating/async.json | 23 + .../appenders/delegating/async.properties | 30 + .../manual/appenders/delegating/async.xml | 39 + .../manual/appenders/delegating/async.yaml | 32 + .../manual/appenders/delegating/failover.json | 33 + .../appenders/delegating/failover.properties | 36 + .../manual/appenders/delegating/failover.xml | 42 + .../manual/appenders/delegating/failover.yaml | 37 + .../manual/appenders/delegating/rewrite.json | 40 + .../appenders/delegating/rewrite.properties | 43 + .../manual/appenders/delegating/rewrite.xml | 42 + .../manual/appenders/delegating/rewrite.yaml | 40 + .../delegating/routing-definition.json | 32 + .../delegating/routing-definition.properties | 38 + .../delegating/routing-definition.xml | 39 + .../delegating/routing-definition.yaml | 34 + .../appenders/delegating/routing-ref.json | 52 + .../delegating/routing-ref.properties | 52 + .../appenders/delegating/routing-ref.xml | 47 + .../appenders/delegating/routing-ref.yaml | 44 + .../appenders/delegating/routing-script.json | 40 + .../delegating/routing-script.properties | 49 + .../appenders/delegating/routing-script.xml | 49 + .../appenders/delegating/routing-script.yaml | 48 + .../rolling-file/logrotate.json | 0 .../rolling-file/logrotate.properties | 0 .../rolling-file/logrotate.xml | 0 .../rolling-file/logrotate.yaml | 0 .../rolling-file/per-month.json | 0 .../rolling-file/per-month.properties | 0 .../rolling-file/per-month.xml | 0 .../rolling-file/per-month.yaml | 0 .../rolling-file/policies.json | 0 .../rolling-file/policies.properties | 0 .../{ => appenders}/rolling-file/policies.xml | 0 .../rolling-file/policies.yaml | 0 .../rolling-file/script-condition.groovy | 0 .../rolling-file/script-condition.json | 0 .../rolling-file/script-condition.properties | 0 .../rolling-file/script-condition.xml | 0 .../rolling-file/script-condition.yaml | 0 .../rolling-file/timestamped.json | 0 .../rolling-file/timestamped.properties | 0 .../rolling-file/timestamped.xml | 0 .../rolling-file/timestamped.yaml | 0 src/site/antora/modules/ROOT/nav.adoc | 4 +- .../modules/ROOT/pages/manual/appenders.adoc | 1070 ++------------- .../pages/manual/appenders/delegating.adoc | 1202 +++++++++++++++++ .../ROOT/pages/manual/appenders/file.adoc | 279 ++++ .../manual/{ => appenders}/rolling-file.adoc | 110 +- 53 files changed, 2603 insertions(+), 1041 deletions(-) create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.json create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.properties create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.xml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.yaml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.json create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.properties create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.xml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.yaml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.json create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.properties create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.xml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.yaml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.json create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.properties create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.xml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.yaml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.json create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.properties create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.xml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.yaml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.json create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.properties create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.xml create mode 100644 src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.yaml rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/logrotate.json (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/logrotate.properties (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/logrotate.xml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/logrotate.yaml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/per-month.json (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/per-month.properties (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/per-month.xml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/per-month.yaml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/policies.json (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/policies.properties (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/policies.xml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/policies.yaml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/script-condition.groovy (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/script-condition.json (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/script-condition.properties (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/script-condition.xml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/script-condition.yaml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/timestamped.json (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/timestamped.properties (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/timestamped.xml (100%) rename src/site/antora/modules/ROOT/examples/manual/{ => appenders}/rolling-file/timestamped.yaml (100%) create mode 100644 src/site/antora/modules/ROOT/pages/manual/appenders/delegating.adoc create mode 100644 src/site/antora/modules/ROOT/pages/manual/appenders/file.adoc rename src/site/antora/modules/ROOT/pages/manual/{ => appenders}/rolling-file.adoc (90%) diff --git a/pom.xml b/pom.xml index f454a451b33..1dc924059ef 100644 --- a/pom.xml +++ b/pom.xml @@ -334,8 +334,10 @@ 1.26.2 1.11.0 1.3.3 + 1.2.21 4.0.0 2.17.2 + 4.0.5 2.23.1 2.23.1 2.23.1 @@ -747,6 +749,12 @@ ${site-commons-logging.version} + + com.conversantmedia + disruptor + ${site-conversant.version} + + com.lmax disruptor @@ -760,6 +768,12 @@ pom + + org.jctools + jctools-core + ${site-jctools.version} + + ch.qos.logback logback-core diff --git a/src/site/antora/antora.tmpl.yml b/src/site/antora/antora.tmpl.yml index bebb37808cb..406a7217967 100644 --- a/src/site/antora/antora.tmpl.yml +++ b/src/site/antora/antora.tmpl.yml @@ -54,8 +54,10 @@ asciidoc: commons-compress-version: "${site-commons-compress.version}" commons-csv-version: "${site-commons-csv.version}" commons-logging-version: "${site-commons-logging.version}" + conversant-version: "${site-conversant.version}" disruptor-version: "${site-disruptor.version}" jackson-version: "${site-jackson.version}" + jctools-version: "${site-jctools.version}" log4j-api-version: "${log4j-api.version}" log4j-core-version: "${site-log4j-core.version}" log4j-layout-template-json-version: "${site-log4j-layout-template-json.version}" diff --git a/src/site/antora/antora.yml b/src/site/antora/antora.yml index 5e39f80906d..08535b1dc79 100644 --- a/src/site/antora/antora.yml +++ b/src/site/antora/antora.yml @@ -54,8 +54,10 @@ asciidoc: commons-compress-version: "1.2.3-commons-compress" commons-csv-version: "1.2.3-commons-csv" commons-logging-version: "1.2.3-commons-logging" + conversant-version: "1.2.3-conversant" disruptor-version: "1.2.3-disruptor" jackson-version: "1.2.3-jackson" + jctools-version: "1.2.3-jctools" log4j-api-version: "1.2.3-api" log4j-core-version: "1.2.3-core" log4j-layout-template-json-version: "1.2.3-layout-template-json" diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.json b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.json new file mode 100644 index 00000000000..ef29d1d8b9a --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.json @@ -0,0 +1,23 @@ +{ + "Configuration": { + "Appenders": { + // tag::appenders[] + "File": { + "name": "FILE", + "fileName": "app.log" + }, + "Async": { + "name": "ASYNC" + } + // end::appenders[] + }, + "Loggers": { + "Root": { + "level": "INFO", + "AppenderRef": { + "ref": "ASYNC" + } + } + } + } +} \ No newline at end of file diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.properties new file mode 100644 index 00000000000..46374a42826 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.properties @@ -0,0 +1,30 @@ +# +# 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::appenders[] +appender.0.type = File +appender.0.name = FILE +appender.0.fileName = app.log + +appender.1.type = Async +appender.1.name = ASYNC +appender.1.appenderRef.type = AppenderRef +appender.1.appenderRef.ref = FILE +# end::appenders[] + +rootLogger.level = INFO +rootLogger.appenderRef.0.ref = ASYNC diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.xml new file mode 100644 index 00000000000..3ebd1f30dee --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.yaml new file mode 100644 index 00000000000..1edfd88d8f2 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/async.yaml @@ -0,0 +1,32 @@ +# +# 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::appenders[] + File: + name: "FILE" + fileName: "app.log" + Async: + name: "ASYNC" + AppenderRef: + ref: "FILE" + # end::appenders[] + Loggers: + Root: + level: "INFO" + AppenderRef: + ref: "ASYNC" diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.json b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.json new file mode 100644 index 00000000000..daa6e77d68e --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.json @@ -0,0 +1,33 @@ +{ + "Configuration": { + "Appenders": { + // tag::appenders[] + "File": { + "name": "FILE", + "fileName": "app.log", + "ignoreExceptions": false // <1> + }, + "Console": { + "name": "CONSOLE" + }, + "Failover": { + "name": "FAILOVER", + "primary": "FILE", + "Failovers": { + "AppenderRef": { + "ref": "CONSOLE" + } + } + } + // end::appenders[] + }, + "Loggers": { + "Root": { + "level": "INFO", + "AppenderRef": { + "ref": "FAILOVER" + } + } + } + } +} \ No newline at end of file diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.properties new file mode 100644 index 00000000000..fd2b3207288 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.properties @@ -0,0 +1,36 @@ +# +# 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::appenders[] +appender.0.type = File +appender.0.name = FILE +appender.0.fileName = app.log +appender.0.ignoreExceptions = false + +appender.1.type = Console +appender.1.name = CONSOLE + +appender.2.type = Failover +appender.2.name = FAILOVER +appender.2.primary = FILE +appender.2.fail.type = Failovers +appender.2.fail.0.type = AppenderRef +appender.2.fail.0.ref = CONSOLE +# end::appenders[] + +rootLogger.level = INFO +rootLogger.appenderRef.0.ref = FAILOVER diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.xml new file mode 100644 index 00000000000..67017dd20a2 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.yaml new file mode 100644 index 00000000000..6fcc3268c82 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/failover.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::appenders[] + File: + name: "FILE" + fileName: "app.log" + ignoreExceptions: false + Console: + name: "CONSOLE" + Failover: + name: "FAILOVER" + primary: "FILE" + Failovers: + AppenderRef: + ref: "CONSOLE" + # end::appenders[] + Loggers: + Root: + level: "INFO" + AppenderRef: + ref: "FAILOVER" diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.json b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.json new file mode 100644 index 00000000000..0fbd5945e89 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.json @@ -0,0 +1,40 @@ +{ + "Configuration": { + "Appenders": { + "Console": { + "name": "CONSOLE", + "JsonTemplateLayout": {} + }, + // tag::appender[] + "Rewrite": { + "name": "REWRITE", + "LoggerNameLevelRewritePolicy": { // <1> + "logger": "org.example", + "KeyValuePair": [ + { + "key": "WARN", + "value": "INFO" + }, + { + "key": "INFO", + "value": "DEBUG" + } + ] + }, + "AppenderRef": { + "level": "INFO", // <2> + "ref": "CONSOLE" + } + } + // end::appender[] + }, + "Loggers": { + "Root": { + "level": "INFO", + "AppenderRef": { + "ref": "REWRITE" + } + } + } + } +} \ No newline at end of file diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.properties new file mode 100644 index 00000000000..50a0ee9323f --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.properties @@ -0,0 +1,43 @@ +# +# 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. +# +## +appender.0.type = Console +appender.0.name = CONSOLE +appender.0.layout.type = JsonTemplateLayout + +# tag::appender[] +appender.1.type = Rewrite +appender.1.name = REWRITE + +# <1> +appender.1.policy.type = LoggerNameLevelRewritePolicy +appender.1.policy.logger = org.example +appender.1.policy.kv0.type = KeyValuePair +appender.1.policy.kv0.key = WARN +appender.1.policy.kv0.value = INFO +appender.1.policy.kv1.type = KeyValuePair +appender.1.policy.kv1.key = INFO +appender.1.policy.kv1.value = DEBUG + +appender.1.appenderRef.type = AppenderRef +# <2> +appender.1.appenderRef.level = INFO +appender.1.appenderRef.ref = CONSOLE +# end::appender[] + +rootLogger.level = INFO +rootLogger.appenderRef.0.ref = REWRITE diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.xml new file mode 100644 index 00000000000..2efeae6f4c5 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.yaml new file mode 100644 index 00000000000..e79edd9cf6c --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/rewrite.yaml @@ -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. +# +Configuration: + Appenders: + Console: + name: "CONSOLE" + JsonTemplateLayout: {} + # tag::appender[] + Rewrite: + name: "REWRITE" + LoggerNameLevelRewritePolicy: # <1> + logger: "org.example" + KeyValuePair: + - key: "WARN" + value: "INFO" + - key: "INFO" + value: "DEBUG" + AppenderRef: + level: "INFO" # <2> + ref: "CONSOLE" + # end::appender[] + Loggers: + Root: + level: "INFO" + AppenderRef: + ref: "REWRITE" diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.json b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.json new file mode 100644 index 00000000000..1b86bf4e96a --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.json @@ -0,0 +1,32 @@ +{ + "Configuration": { + "Appenders": { + // tag::appender[] + "Routing": { + "name": "ROUTING", + "Routes": { + "pattern": "$${event:Marker}}", // <1> + "Route": { + "File": { // <2> + "name": "${event:Marker}", + "fileName": "${event:Marker:-main}.log", + "JsonTemplateLayout": {} + } + } + }, + "IdlePurgePolicy": { // <3> + "timeToLive": 15 + } + } + // end::appender[] + }, + "Loggers": { + "Root": { + "level": "INFO", + "AppenderRef": { + "ref": "ROUTING" + } + } + } + } +} \ No newline at end of file diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.properties new file mode 100644 index 00000000000..23ec12ef127 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.properties @@ -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. +# +## +# tag::appender[] +appender.0.type = Routing +appender.0.name = ROUTING +appender.0.route.type = Routes +# <1> +appender.0.route.pattern = $${event:Marker} + +appender.0.route.0.type = Route +# <2> +appender.0.route.0.appender.type = File +appender.0.route.0.appender.name = ${event:Marker} +appender.0.route.0.appender.fileName = ${event:Marker:-main}.log +appender.0.route.0.appender.layout.type = JsonTemplateLayout + +# <3> +appender.0.purge.type = IdlePurgePolicy +appender.0.purge.timeToLive = 15 +# end::appender[] + +rootLogger.level = INFO +rootLogger.appenderRef.0.ref = ROUTING diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.xml new file mode 100644 index 00000000000..e159948a9f0 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.yaml new file mode 100644 index 00000000000..ea95d1e81e2 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-definition.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[] + Routing: + Routes: + pattern: "$${event:Marker}" # <1> + Route: + File: # <2> + name: "${event:Marker}" + fileName: "${event:Marker:-main}.log" + IdlePurgePolicy: # <3> + timeToLive: 15 + # end::appender[] + Loggers: + Root: + level: "INFO" + AppenderRef: + ref: "ROUTING" diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.json b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.json new file mode 100644 index 00000000000..8dfd2374775 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.json @@ -0,0 +1,52 @@ +{ + "Configuration": { + "Appenders": { + "File": [ + { + "name": "MAIN_LOG", + "fileName": "main.log", + "JsonTemplateLayout": {} + }, + { + "name": "MARKED_LOG", + "fileName": "marked.log", + "JsonTemplateLayout": {} + }, + { + "name": "AUDIT_LOG", + "fileName": "audit.log", + "JsonTemplateLayout": {} + } + ], + // tag::appender[] + "Routing": { + "name": "ROUTING", + "Routes": { + "pattern": "$${event:Marker}}", + "Route": [ + { // <1> + "key": "AUDIT", + "ref": "AUDIT_LOG" + }, + { // <2> + "key": "$${event:Marker}", + "ref": "MAIN_LOG" + }, + { // <3> + "ref": "MARKED_LOG" + } + ] + } + } + // end::appender[] + }, + "Loggers": { + "Root": { + "level": "INFO", + "AppenderRef": { + "ref": "ROUTING" + } + } + } + } +} \ No newline at end of file diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.properties new file mode 100644 index 00000000000..461abfca4bf --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.properties @@ -0,0 +1,52 @@ +# +# 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. +# +## +appender.0.type = File +appender.0.name = MAIN_LOG +appender.0.fileName = main.log +appender.0.layout.type = JsonTemplateLayout + +appender.1.type = File +appender.1.name = MARKED_LOG +appender.1.fileName = marked.log +appender.1.layout.type = JsonTemplateLayout + +appender.2.type = File +appender.2.name = AUDIT_LOG +appender.2.fileName = audit.log +appender.2.layout.type = JsonTemplateLayout + +# tag::appender[] +appender.3.type = Routing +appender.3.name = ROUTING +appender.3.route.type = Routes +appender.3.route.pattern = $${event:Marker} +# <1> +appender.3.route.0.type = Route +appender.3.route.0.key = AUDIT +appender.3.route.0.ref = AUDIT_LOG +# <2> +appender.3.route.1.type = Route +appender.3.route.1.key = $${event:Marker} +appender.3.route.1.ref = MAIN_LOG +# <3> +appender.3.route.2.type = Route +appender.3.route.2.ref = MARKED_LOG +# end::appender[] + +rootLogger.level = INFO +rootLogger.appenderRef.0.ref = ROUTING diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.xml new file mode 100644 index 00000000000..ea2ff48c1be --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.yaml new file mode 100644 index 00000000000..d00e60e70af --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-ref.yaml @@ -0,0 +1,44 @@ +# +# 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: + File: + - name: "MAIN_LOG" + fileName: "main.log" + JsonTemplateLayout: {} + - name: "MARKED_LOG" + fileName: "marked.log" + JsonTemplateLayout: {} + - name: "AUDIT_LOG" + fileName: "audit.log" + JsonTemplateLayout: {} + # tag::appender[] + Routing: + Routes: + pattern: "$${event:Marker}" + Route: + - key: "AUDIT" # <1> + ref: "AUDIT_LOG" + - key: "$${event:Marker}" # <2> + ref: "MAIN_LOG" + - ref: "MARKED_LOG" # <3> + # end::appender[] + Loggers: + Root: + level: "INFO" + AppenderRef: + ref: "ROUTING" diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.json b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.json new file mode 100644 index 00000000000..5df4437a233 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.json @@ -0,0 +1,40 @@ +{ + "Configuration": { + "Appenders": { + // tag::appender[] + "Routing": { + "name": "ROUTING", + "Script": { + "language": "groovy", + // <1> + "scriptText": "staticVariables.servers = ['server1', 'server2', 'server3']; staticVariables.count = 0;" + }, + "Routes": { + "Script": { + "language": "groovy", + // <2> + "scriptText": "int count = staticVariables.count++; String server = staticVariables.servers[count % 3]; return configuration.properties['server'] = server;" + }, + "Route": { + "Socket": { // <3> + "name": "${server}", + "protocol": "TCP", + "host": "${server}", + "port": "500", + "Rfc5425Layout": {} + } + } + } + } + // end::appender[] + }, + "Loggers": { + "Root": { + "level": "INFO", + "AppenderRef": { + "ref": "ROUTING" + } + } + } + } +} \ No newline at end of file diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.properties new file mode 100644 index 00000000000..44e27827ef4 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.properties @@ -0,0 +1,49 @@ +# +# 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 = Routing +appender.0.name = ROUTING + +appender.0.script.type = Script +appender.0.script.language = groovy +# <1> +appender.0.script.scriptText = \ + staticVariables.servers = ['server1', 'server2', 'server3']; \ + staticVariables.count = 0; + +appender.0.route.type = Routes +appender.0.route.script.type = Script +appender.0.route.script.language = groovy +# <2> +appender.0.route.script.scriptText = \ + int count = staticVariables.count++; \ + String server = staticVariables.servers[count % 3]; \ + return configuration.properties['server'] = server; + +appender.0.route.0.type = Route +# <3> +appender.0.route.0.appender.type = Socket +appender.0.route.0.appender.name = ${server} +appender.0.route.0.appender.protocol = TCP +appender.0.route.0.appender.host = ${server} +appender.0.route.0.appender.port = 500 +appender.0.route.0.appender.layout = Rfc5424Layout +# end::appender[] + +rootLogger.level = INFO +rootLogger.appenderRef.0.ref = ROUTING diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.xml new file mode 100644 index 00000000000..0a0f916ec0b --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.yaml new file mode 100644 index 00000000000..64b88b30b22 --- /dev/null +++ b/src/site/antora/modules/ROOT/examples/manual/appenders/delegating/routing-script.yaml @@ -0,0 +1,48 @@ +# +# 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[] + Routing: + Script: + language: "groovy" + # <1> + scriptText: | + staticVariables.servers = ['server1', 'server2', 'server3']; + staticVariables.count = 0; + Routes: + Script: + language: "groovy" + # <2> + scriptText: | + int count = staticVariables.count++; + String server = staticVariables.servers[count % 3]; + return configuration.properties['server'] = server; + Route: + # <3> + Socket: + name: "${server}" + protocol: "TCP" + host: "${server}" + port: 500 + Rfc5424Layout: {} + # end::appender[] + Loggers: + Root: + level: "INFO" + AppenderRef: + ref: "ROUTING" diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.json b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/logrotate.json similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.json rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/logrotate.json diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/logrotate.properties similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.properties rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/logrotate.properties diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/logrotate.xml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.xml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/logrotate.xml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/logrotate.yaml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/logrotate.yaml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/logrotate.yaml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.json b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/per-month.json similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.json rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/per-month.json diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/per-month.properties similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.properties rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/per-month.properties diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/per-month.xml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.xml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/per-month.xml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/per-month.yaml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/per-month.yaml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/per-month.yaml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.json b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/policies.json similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.json rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/policies.json diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/policies.properties similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.properties rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/policies.properties diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/policies.xml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.xml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/policies.xml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/policies.yaml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/policies.yaml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/policies.yaml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.groovy b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.groovy similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.groovy rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.groovy diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.json b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.json similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.json rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.json diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.properties similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.properties rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.properties diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.xml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.xml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.xml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.yaml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/script-condition.yaml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/script-condition.yaml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.json b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/timestamped.json similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.json rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/timestamped.json diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.properties b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/timestamped.properties similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.properties rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/timestamped.properties diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.xml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/timestamped.xml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.xml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/timestamped.xml diff --git a/src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.yaml b/src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/timestamped.yaml similarity index 100% rename from src/site/antora/modules/ROOT/examples/manual/rolling-file/timestamped.yaml rename to src/site/antora/modules/ROOT/examples/manual/appenders/rolling-file/timestamped.yaml diff --git a/src/site/antora/modules/ROOT/nav.adoc b/src/site/antora/modules/ROOT/nav.adoc index 820ee2380fb..59bab7b1e38 100644 --- a/src/site/antora/modules/ROOT/nav.adoc +++ b/src/site/antora/modules/ROOT/nav.adoc @@ -43,7 +43,9 @@ ** xref:manual/systemproperties.adoc[] ** xref:manual/customconfig.adoc[] ** xref:manual/appenders.adoc[] -*** xref:manual/rolling-file.adoc[] +*** xref:manual/appenders/file.adoc[] +*** xref:manual/appenders/rolling-file.adoc[] +*** xref:manual/appenders/delegating.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 de76005f814..f6cb1adbcbb 100644 --- a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc +++ b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc @@ -17,27 +17,25 @@ = Appenders -Appenders are responsible for delivering LogEvents to their destination. +Appenders are responsible for delivering log events to their destination. Every Appender must implement the link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html[`Appender`] interface. -Most Appenders will extend -link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/AbstractAppender.html[`AbstractAppender`] -which adds -link:../javadoc/log4j-core/org/apache/logging/log4j/core/LifeCycle.html[`Lifecycle`] -and -link:../javadoc/log4j-core/org/apache/logging/log4j/core/filter/Filterable.html[`Filterable`] -support. `Lifecycle` allows components to finish initialization after configuration has been completed and to perform cleanup during shutdown. -`Filterable` allows the component to have `Filter` attached to it which are evaluated during event processing. -Appenders usually are only responsible for writing the event data to the target destination. -In most cases, they delegate responsibility for formatting the event to a xref:manual/layouts.adoc[layout]. -Some appenders wrap other appenders so that they can modify the `LogEvent`, handle a failure in an `Appender`, route the event to a subordinate `Appender` based on advanced `Filter` criteria or provide similar functionality that does not directly format the event for viewing. +While not strictly required by the Log4j Core architecture, most appenders inherit from +link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/AbstractAppender.html[`AbstractAppender`] +and: -Appenders always have a name so that they can be referenced from Loggers. +* delegate the filtering of log events to an implementation of +link:../javadoc/log4j-core/org/apache/logging/log4j/core/Filter.html[`Filter`]. +See xref:manual/filters.adoc[] for more information. +* delegate the formatting of log events to an implementation of +link:../javadoc/log4j-core/org/apache/logging/log4j/core/Layout.html[`Layout`]. +See xref:manual/layouts.adoc[] for more information. +* only directly handle the writing of log event data to the target destination. -In the tables below, the "Type" column corresponds to the Java type expected. -For non-JDK classes, these should usually be in link:../javadoc/log4j-core/index.html[Log4j Core] unless otherwise noted. +Appenders always have a name so that they can be referenced from a +xref:manual/configuration.adoc#configuring-loggers[logger configuration]. [#commons-concerns] == Common concerns @@ -61,7 +59,7 @@ The buffer is flushed to the underlying resource on three occasions: * at the end of each log event batch, if xref:manual/async.adoc[asynchronous loggers] or -<> +xref:manual/appenders/delegating.adoc#AsyncAppender[appenders] are used. * at the end of each log event, if the <> @@ -120,59 +118,91 @@ It does not ensure that the operating system writes the event to the underlying [TIP] ==== -If you are using xref:manual/async.adoc[asynchronous loggers] or <>, you can set this attribute to `false`. +If you are using +xref:manual/async.adoc[asynchronous loggers] +or +xref:manual/appenders/delegating.adoc#AsyncAppender[appenders], you can set this attribute to `false`. Log4j Core will still flush the internal buffer, whenever the log event queue becomes empty. ==== +[#exception-handling] +=== Exception handling + +By default, Log4j Core uses xref:manual/status-logger.adoc[] to report exceptions that occur in appenders. +This behavior can be changed using the following configuration property: + +[#ignoreExceptions] +==== `ignoreExceptions` + +[cols="1h,5"] +|=== +| Type | `boolean` +| Default value | `true` +|=== + +If `false` logging exceptions will be forwarded to the caller. +Otherwise, they will be logged using xref:manual/status-logger.adoc[]. + +[TIP] +==== +If logging is important for your business, consider using a +xref:manual/appenders/delegating.adoc#FailoverAppender[`Failover` Appender] +to redirect log events to a different appender in case of exceptions. +==== + [#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 `$$+{...}+` property substitution expressions. .List of attributes evaluated at runtime [cols="1,1,1,1"] |=== | Component | Parameter | Event type | Evaluation context -| <> +| <> | <> | Log event | xref:manual/lookups.adoc#global-context[_global_] -| <> +| <> | <> | Log event | xref:manual/lookups.adoc#global-context[_global_] -| <> +| <> | <> | Log event | xref:manual/lookups.adoc#global-context[_global_] -| <> -| <> +| xref:manual/appenders/delegating.adoc#PropertiesRewritePolicy[PropertiesRewrite Policy] +| xref:manual/appenders/delegating.adoc#PropertiesRewritePolicy-element-Property[`Property/value`] | Log event | xref:manual/lookups.adoc#global-context[_global_] -| <> -| `pattern` +| xref:manual/appenders/delegating.adoc#Routes[Routes Container] +| xref:manual/appenders/delegating.adoc#Routes-attr-pattern[`pattern`] | Log event | xref:manual/lookups.adoc#event-context[_log event_] -| xref:manual/rolling-file.adoc[`RollingFileAppender`] -| xref:manual/rolling-file.adoc#attr-filePattern[`filePattern`] +| xref:manual/appenders/rolling-file.adoc[Rolling File Appenders] +| xref:manual/appenders/rolling-file.adoc#attr-filePattern[`filePattern`] | Rollover | xref:manual/lookups.adoc#global-context[_global_] -| xref:manual/rolling-file.adoc#AbstractPathAction[Optional actions] -| `basePath` +| xref:manual/appenders/rolling-file.adoc#AbstractPathAction[Optional Rollover Actions] +| xref:manual/appenders/rolling-file.adoc#AbstractPathAction-attr-basePath[`basePath`] | Rollover | xref:manual/lookups.adoc#global-context[_global_] |=== -The <> component of the <> 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. +The +xref:manual/appenders/delegating.adoc#Route[`Route`] +component of the +xref:manual/appenders/delegating.adoc#RoutingAppender[Routing Appender] +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 `$$+{...}+` property substitution expressions, but only unescaped `$+{...}+` property substitution expressions. See xref:manual/configuration.adoc#lazy-property-substitution[runtime property substitution] for more details. @@ -180,169 +210,38 @@ See xref:manual/configuration.adoc#lazy-property-substitution[runtime property s == Collection Log4j bundles several predefined appenders to assist in several common deployment use cases. -Following sections explain all these in detail. - -[id=AsyncAppender] -=== [[asyncappender]] AsyncAppender - -The AsyncAppender accepts references to other Appenders and causes LogEvents to be written to them on a separate Thread. -Note that exceptions while writing to those Appenders will be hidden from the application. -The AsyncAppender should be configured after the appenders it references to allow it to shut down properly. - -By default, AsyncAppender uses -https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/concurrent/ArrayBlockingQueue.html[`java.util.concurrent.ArrayBlockingQueue`] -which does not require any external libraries. -Note that multi-threaded applications should exercise care when using this appender as such: the blocking queue is susceptible to lock contention and our -xref:manual/performance.adoc#async[tests showed] performance may become worse when more threads are logging concurrently. -Consider using -xref:manual/async.adoc[lock-free Async Loggers] for optimal performance. - -[NOTE] -==== -Log4j 2 brought the following enhancements to the Log4j 1 async appender: - -* all appenders referenced by `AsyncAppender` flush their buffers to the OS at the end of a batch, when the queue becomes empty. -This guarantees that the batch of log events is passed to the OS and is a more performant version of the <> attribute. -+ -WARNING: Similarly to what happens with the `immediateFlush` attribute, this does not guarantee that the OS stores the data on the underlying device. - -* the type of queue is configurable to allow users to use faster and more performant queues, such as those from the -https://github.com/JCTools/JCTools?tab=readme-ov-file#jctools[JCTools] -or -https://github.com/conversant/disruptor[Conversant Disruptor] projects. -==== +They are documented in separate pages based on their target resource: -.AsyncAppender Parameters -[width="100%",cols="20%,20%,60%",options="header",] -|======================================================================= -|Parameter Name |Type |Description -|AppenderRef |String |The name of the Appenders to invoke -asynchronously. Multiple AppenderRef elements can be configured. - -|blocking |boolean |If true, the appender will wait until there are free -slots in the queue. If false, the event will be written to the error -appender if the queue is full. The default is true. +[#file-appenders] +=== File appenders -|shutdownTimeout |integer |How many milliseconds the Appender should -wait to flush outstanding log events in the queue on shutdown? The -default is zero which means to wait forever. +File appenders write logs to the filesystem. +They can be further split into: -|bufferSize |integer a| -Specifies the maximum number of events that can be queued. The default -is 1024. Note that when using a disruptor-style `BlockingQueue`, this -buffer size must be a power of 2. +Single file appenders::: +See xref:manual/appenders/file.adoc[] for details. -When the application is logging faster than the underlying appender can -keep up with for a long enough time to fill up the queue, the behavior -is determined by the -link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/AsyncQueueFullPolicy.html[`AsyncQueueFullPolicy`]. +Rolling file appenders::: +See xref:manual/appenders/rolling-file.adoc[] for details. -|errorRef |String |The name of the Appender to invoke if none of the -appenders can be called, either due to errors in the appenders or -because the queue is full. If not specified then errors will be ignored. - -|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. - -|name |String |The name of the Appender. - -|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 >. +[#delegating-appenders] +=== Delegating appenders -|includeLocation |boolean |Extracting location is an expensive operation -(it can make logging 5 - 20 times slower). To improve performance, -location is not included by default when adding a log event to the -queue. You can change this by setting includeLocation="true". +Delegating appenders are intended to decorate other appenders: -|BlockingQueueFactory -|BlockingQueueFactory -|This element overrides what type of `BlockingQueue` to use. -See <> for more details. -|======================================================================= - -There are also a few system properties that can be used to maintain application throughput even when the underlying appender cannot keep up with the logging rate and the queue is filling up. -See the details for system properties -xref:manual/systemproperties.adoc#log4j2.asyncQueueFullPolicy[`log4j2.asyncQueueFullPolicy`] -and -xref:manual/systemproperties.adoc#log4j2.discardThreshold[`log4j2.DiscardThreshold`]. - -A typical AsyncAppender configuration might look like this: - -[source,xml] ----- - - - - - - %d %p %c{1.} [%t] %m%n - - - - - - - - - - - - ----- +xref:manual/appenders/delegating.adoc#AsyncAppender[Asynchronous appender]:: +Perform all I/O on a dedicated thread -[[BlockingQueueFactory]] -Starting in Log4j 2.7, a custom implementation of `BlockingQueue` or `TransferQueue` can be specified using a -link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/BlockingQueueFactory.html[`BlockingQueueFactory`] -plugin. -To override the default `BlockingQueueFactory`, specify the plugin inside an `` element like so: +xref:manual/appenders/delegating.adoc#FailoverAppender[Failover appender]:: +Provide a backup appender in case an appender fails -[source,xml] ----- - - - - - - - - - - - - - - ----- +xref:manual/appenders/delegating.adoc#RewriteAppender[Rewrite appender]:: +Modify log events prior to delivering them to the target -Log4j ships with the following implementations: +xref:manual/appenders/delegating.adoc#RoutingAppender[Routing appender]:: +Dynamically choose a different appender for each log event -.BlockingQueueFactory Implementations -[cols="25%,75%",options="header",] -|======================================================================= -|Plugin Name |Description -|ArrayBlockingQueue |This is the default implementation that uses -https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/concurrent/ArrayBlockingQueue.html[`ArrayBlockingQueue`]. - -|DisruptorBlockingQueue |This uses the -https://github.com/conversant/disruptor[Conversant Disruptor] -implementation of `BlockingQueue`. This plugin takes a single optional -attribute, `spinPolicy`, which corresponds to the `SpinPolicy` enum. - -|JCToolsBlockingQueue |This uses -https://jctools.github.io/JCTools/[JCTools], specifically the MPSC -bounded lock-free queue. -This implementation is provided by the `log4j-jctools` artifact. - -|LinkedTransferQueue |This uses the new Java 7 implementation -https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/concurrent/LinkedTransferQueue.html[`LinkedTransferQueue`]. -Note that this queue does not use the `bufferSize` configuration -attribute from AsyncAppender as `LinkedTransferQueue` does not support a -maximum capacity. -|======================================================================= +See xref:manual/appenders/delegating.adoc[] for details. [#CassandraAppender] === CassandraAppender @@ -547,206 +446,6 @@ A typical Console configuration might look like: ---- -[#FailoverAppender] -=== FailoverAppender - -The FailoverAppender wraps a set of appenders. -If the primary Appender fails the secondary appenders will be tried in order until one succeeds or there are no more secondaries to try. - -.FailoverAppender Parameters -[cols="20%,20%,60%",options="header",] -|======================================================================= -|Parameter Name |Type |Description -|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. - -|primary |String |The name of the primary Appender to use. - -|failovers |String[] |The names of the secondary Appenders to use. - -|name |String |The name of the Appender. - -|retryIntervalSeconds |integer |The number of seconds that should pass -before retrying the primary Appender. The default is 60. - -|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. - -|target |String |Either "SYSTEM_OUT" or "SYSTEM_ERR". The default is -"SYSTEM_ERR". -|======================================================================= - -A Failover configuration might look like: - -[source,xml] ----- - - - - - - %d %p %c{1.} [%t] %m%n - - - - - - - - - - - - - - - - - - ----- - -[id=fileappender] -=== [[FileAppender]] FileAppender - -The FileAppender is an OutputStreamAppender that writes to the File defined in the `fileName` parameter. -The FileAppender uses a FileManager (which extends OutputStreamManager) to perform the file I/O. -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",] -|======================================================================= -|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. - -|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. - -|locking |boolean |When set to true, I/O operations will occur only -while the file lock is held allowing FileAppenders in multiple JVMs and -potentially multiple hosts to write to the same file simultaneously. -This will significantly impact performance so should be used carefully. -Furthermore, on many systems, the file lock is "advisory" meaning that -other applications can perform operations on the file without acquiring -a lock. The default value is false. - -|name |String |The name of the Appender. - -|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 <>. - -|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. - -|======================================================================= - -Here is a sample File configuration: - -[source,xml] ----- - - - - - - %d %p %c{1.} [%t] %m%n - - - - - - - - - ----- [#FlumeAppender] === FlumeAppender @@ -1630,7 +1329,7 @@ public class JpaLogEntity extends BasicLogEventEntity { return this.id; } - public void setId(long id) { + public void setId(final long id) { this.id = id; } @@ -1652,7 +1351,7 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity { public TestEntity() { super(null); } - public TestEntity(LogEvent wrappedEvent) { + public TestEntity(final LogEvent wrappedEvent) { super(wrappedEvent); } @@ -1860,101 +1559,6 @@ _Note:_ Make sure to not let `org.apache.kafka` log to a Kafka appender on DEBUG ---- -[#MemoryMappedFileAppender] -=== MemoryMappedFileAppender - -_New since 2.1. Be aware that this is a new addition, and although it has been tested on several platforms, it does not have as much track record as the other file appenders._ - -The MemoryMappedFileAppender maps a part of the specified file into memory and writes log events to this memory, relying on the operating system's virtual memory manager to synchronize the changes to the storage device. -The main benefit of using memory-mapped files is I/O performance. -Instead of making system calls to write to disk, this appender can simply change the program's local memory, which is orders of magnitude faster. -Also, in most operating systems the memory region mapped is the kernel's -https://en.wikipedia.org/wiki/Page_cache[page cache] (file cache), meaning that no copies need to be created in user space. - -// TODO: -// performance tests that compare performance of this appender to -// RandomAccessFileAppender and FileAppender.) - -There is some overhead with mapping a file region into memory, especially very large regions (half a gigabyte or more). -The default region size is 32 MB, which should strike a reasonable balance between the frequency and the duration of remap operations. - -// (TODO: performance test remapping various sizes.) - -Similar to the FileAppender and the RandomAccessFileAppender, MemoryMappedFileAppender uses a MemoryMappedFileManager to actually perform the file I/O. While MemoryMappedFileAppender from different Configurations cannot be shared, the MemoryMappedFileManagers can be if the manager is accessible. -For example, two web applications in a servlet container can have its own configuration and safely write to the same file if Log4j is in a ClassLoader that is common to both of them. - -.MemoryMappedFileAppender 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. - -|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. - -|filters |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. - -|immediateFlush |boolean a| -When set to true, each write will be followed by a call to -https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/MappedByteBuffer.html#force()[`MappedByteBuffer#force()`]. -This will guarantee the data is written to the storage device. - -The default for this parameter is `false`. This means that the data is -written to the storage device even if the Java process crashes, but -there may be data loss if the operating system crashes. - -Note that manually forcing a sync on every log event loses most of the -performance benefits of using a memory-mapped file. - -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. - -|regionLength |int |The length of the mapped region, defaults to 32 MB -(32 * 1024 * 1024 bytes). This parameter must be a value between 256 and -1,073,741,824 (1 GB or 2^30); values outside this range will be adjusted -to the closest valid value. Log4j will round the specified value up to -the nearest power of two. - -|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. - -|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 <>. -|======================================================================= - -Here is a sample MemoryMappedFile configuration: - -[source,xml] ----- - - - - - - %d %p %c{1.} [%t] %m%n - - - - - - - - - ----- - [#NoSQLAppender] === NoSQLAppender @@ -2377,474 +1981,6 @@ Here are a few sample configurations for the NoSQLAppender and CouchDB provider: ---- -[#OutputStreamAppender] -=== OutputStreamAppender - -The OutputStreamAppender provides the base for many of the other Appenders such as the File and Socket appenders that write the event to an Output Stream. -It cannot be directly configured. -Support for immediateFlush and buffering is provided by the OutputStreamAppender. -The OutputStreamAppender uses an OutputStreamManager to handle the actual I/O, allowing the stream to be shared by Appenders in multiple configurations. - -[#RandomAccessFileAppender] -=== RandomAccessFileAppender - -The RandomAccessFileAppender is similar to the standard -<> 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. -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. - -.RandomAccessFileAppender 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. - -|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. - -|filters |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. - -|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. - -|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. - -|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 <>. -|======================================================================= - -Here is a sample RandomAccessFile configuration: - -[source,xml] ----- - - - - - - %d %p %c{1.} [%t] %m%n - - - - - - - - - ----- - -[#RewriteAppender] -=== RewriteAppender - -The RewriteAppender allows the LogEvent to be manipulated before it is processed by another Appender. -This can be used to mask sensitive information such as passwords or to inject information into each event. -The RewriteAppender must be configured with a RewritePolicy. -The RewriteAppender should be configured after any Appenders it references to allow it to shut down properly. - -.RewriteAppender Parameters -[cols="20%,20%,60%",options="header",] -|======================================================================= -|Parameter Name |Type |Description -|AppenderRef |String |The name of the Appenders to call after the -LogEvent has been manipulated. Multiple AppenderRef elements can be -configured. - -|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. - -|name |String |The name of the Appender. - -|rewritePolicy |RewritePolicy |The RewritePolicy that will manipulate -the LogEvent. - -|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 <>. -|======================================================================= - -[#RewritePolicy] -==== RewritePolicy - -RewritePolicy is an interface that allows implementations to inspect and possibly modify LogEvents before they are passed to Appender. -RewritePolicy declares a single method named rewrite that must be implemented. -The method is passed the LogEvent and can return the same event or create a new one. - -===== MapRewritePolicy - -MapRewritePolicy will evaluate LogEvents that contain a MapMessage and will add or update elements of the Map. - -[cols="20%,20%,60%",options="header",] -|================================================================ -|Parameter Name |Type |Description -|mode |String |"Add" or "Update" -|keyValuePair |KeyValuePair[] |An array of keys and their values. -|================================================================ - -The following configuration shows a RewriteAppender configured to add a product key and its value to the MapMessage.: - -[source,xml] ----- - - - - - - - - - - - - - - - - - - - ----- - -[#PropertiesRewritePolicy] -===== PropertiesRewritePolicy - -PropertiesRewritePolicy will add properties configured on the policy to the ThreadContext Map being logged. -The properties will not be added to the actual ThreadContext Map. -The property values may contain variables that will be evaluated when the configuration is processed as well as when the event is logged. - -[cols="20%,20%,60%",options="header",] -|=== -|Parameter Name |Type |Description - -|[[PropertiesRewritePolicy-element-properties]]properties -|Property[] -|One of more Property elements to define the keys and values to be added to the ThreadContext Map. - -The `value` attribute of each `Property` element supports -xref:manual/configuration.adoc#lazy-property-substitution[runtime property substitution] -in the -xref:manual/lookups.adoc#global-context[_global context_]. -|=== - -The following configuration shows a RewriteAppender configured to add a product key and its value to the MapMessage: - -[source,xml] ----- - - - - - - - - - - ${sys:user.name} - ${sys:environment} - - - - - - - - - ----- - -===== LoggerNameLevelRewritePolicy - -You can use this policy to make loggers in third-party code less chatty by changing event levels. -The LoggerNameLevelRewritePolicy will rewrite log event levels for a given logger name prefix. -You configure a LoggerNameLevelRewritePolicy with a logger name prefix and a pair of levels, where a pair defines a source level and a target level. - -[cols="20%,20%,60%",options="header",] -|======================================================================= -|Parameter Name |Type |Description -|logger |String |A logger name used as a prefix to test each event's -logger name. - -|LevelPair |KeyValuePair[] |An array of keys and their values, each key -is a source level, each value a target level. -|======================================================================= - -The following configuration shows a RewriteAppender configured to map level INFO to DEBUG and level WARN to INFO for all loggers that start with `com.foo.bar`. - -[source,xml] ----- - - - - - - - - - - - - - - - - - - - - ----- - -[#RoutingAppender] -=== RoutingAppender - -The `RoutingAppender` evaluates LogEvents and then routes them to a subordinate Appender. -The target Appender may be an appender previously configured and may be referenced by its name or the Appender can be dynamically created as needed. -The `RoutingAppender` should be configured after any Appenders it references to allow it to shut down properly. - -You can also configure a `RoutingAppender` with scripts: you can run a script when the appender starts and when a route is chosen for an log event. - -.RoutingAppender Parameters -[width="100%",cols="20%,20%,60%",options="header",] -|======================================================================= -|Parameter Name |Type |Description -|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. - -|name |String |The name of the Appender. - -|RewritePolicy |RewritePolicy |The RewritePolicy that will manipulate -the LogEvent. - -|Routes |Routes |Contains one or more Route declarations to identify the -criteria for choosing Appenders. - -|Script |Script a| -This Script runs when Log4j starts the RoutingAppender and returns a -String Route key to determine the default Route. - -This script is passed the following variables: - -.RoutingAppender Script Parameters -[cols="20%,20%,60%",options="header",] -|======================================================================= - -|Parameter Name |Type |Description |configuration |Configuration |The active Configuration. - -|staticVariables |Map |A Map shared between all script invocations for this appender instance. -This is the same map passed to the Routes Script. - -|======================================================================= - -|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 <>. -|======================================================================= - -In this example, the script causes the "ServiceWindows" route to be the default route on Windows and "ServiceOther" on all other operating systems. -Note that the List Appender is one of our test appenders, any appender can be used, it is only used as a shorthand. - -[source,xml] ----- - - - - - - - - - - - - - - - - - - - - - ----- - -[#Routes] -==== Routes - -The `Routes` element accepts a single attribute named "pattern". -The pattern is evaluated against all the registered Lookups and the result is used to select a `Route`. -Each `Route` may be configured with a key. -If the key matches the result of evaluating the pattern then that `Route` -will be selected. -If no key is specified on a `Route` then that `Route` is the default. -Only one `Route` can be configured as the default. - -The `Routes` element may contain a `Script` child element. -If specified, the -`Script` is run for each log event and returns the String Route key to use. - -You must specify either the pattern attribute or the `Script` element, but not both. - -Each `Route` must reference an `Appender`. -If the `Route` contains a ref attribute then the `Route` will reference an `Appender` that was defined in the configuration. -If the `Route` contains an `Appender` definition then an -`Appender` will be created within the context of the `RoutingAppender` and will be reused each time a matching `Appender` name is referenced through a `Route`. - -[WARNING] -==== -Lookups in the **children** of the `Route` component are **not** evaluated at configuration time. -The substitution is delayed until the `Route` element is evaluated. -This means that `$+{...}+` expression **should not** be escaped as `$$+{...}+`. - -See xref:manual/configuration.adoc#lazy-property-substitution[lazy property substitution] for more details. -==== - -This script is passed the following variables: - -.RoutingAppender Routes Script Parameters -[cols="20%,20%,60%",options="header",] -|======================================================================= -|Parameter Name |Type |Description -|configuration |Configuration |The active Configuration. - -|staticVariables |Map |A Map shared between all script invocations for -this appender instance. This is the same map passed to the Routes -Script. - -|logEvent |LogEvent |The log event. -|======================================================================= - -In this example, the script runs for each log event and picks a route based on the presence of a Marker named "AUDIT". - -[source,xml] ----- - - - - - - - - - - - - - - - - %d %p %c{1.} [%t] %m%n - - - - - - - - - - - - - - - - ----- - -[#Purge] -==== Purge Policy - -The RoutingAppender can be configured with a PurgePolicy whose purpose is to stop and remove dormant Appenders that have been dynamically created by the RoutingAppender. -Log4j currently provides the IdlePurgePolicy is the only PurgePolicy available for cleaning up the Appenders. -The IdlePurgePolicy accepts 2 attributes; timeToLive, which is the number of timeUnits the Appender should survive without having any events sent to it, and timeUnit, the String representation of java.util.concurrent.TimeUnit which is used with the timeToLive attribute. - -Below is a sample configuration that uses a RoutingAppender to route all Audit events to a FlumeAppender and all other events will be routed to a RollingFileAppender captures only the specific event type. -Note that the AuditAppender was predefined while the RollingFileAppenders are created as needed. - -[source,xml] ----- - - - - - - - - - - - - - - %d %p %c{1.} [%t] %m%n - - - - - - - - - - - - - - - ----- - [#servlet-appender] === Servlet appender @@ -3010,42 +2146,6 @@ As with other Appenders, the formatting can be controlled by specifying a Layout ---- -[#ScriptAppenderSelector] -=== ScriptAppenderSelector - -When the configuration is built, the `ScriptAppenderSelector` appender calls a `ScriptPlugin` to compute an appender name. -Log4j then creates one of the appender named listed under `AppenderSet` using the name of the -`ScriptAppenderSelector`. -After configuration, Log4j ignores the -`ScriptAppenderSelector`. -Log4j only builds the one selected appender from the configuration tree and ignores other `AppenderSet` child nodes. - -In the following example, the script returns the name "List2". -The appender name is recorded under the name of the -`ScriptAppenderSelector`, not the name of the selected appender, in this example, "SelectIt". - -[source,xml] ----- - - - - - - - - - - - - - - - - ----- - [#SocketAppender] === SocketAppender @@ -3157,7 +2257,7 @@ This is a secured <> configuration: ---- [#SSL] -=== SSL +==== SSL Several appenders can be configured to use either a plain network connection or a Secure Socket Layer (SSL) connection. This section documents the parameters available for SSL configuration. diff --git a/src/site/antora/modules/ROOT/pages/manual/appenders/delegating.adoc b/src/site/antora/modules/ROOT/pages/manual/appenders/delegating.adoc new file mode 100644 index 00000000000..b04af5edd76 --- /dev/null +++ b/src/site/antora/modules/ROOT/pages/manual/appenders/delegating.adoc @@ -0,0 +1,1202 @@ +//// + 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. +//// + += Delegating Appenders +:open-book: 📖 + +Log4j Core supplies multiple appenders that do not perform any work themselves, but modify the way other appenders work. +The following behaviors can be modified: + +* If you want to perform all I/O from a dedicated thread, see <>. +* If you want to provide a backup appender in case an appender fails, see <>. +* If you want to modify the log event, before it is sent to the target destination, see <>. +* If you want to create appenders dynamically or choose a different appender for each log event, see <>. + +[#AsyncAppender] +== `Async` Appender + +The `Async` Appender stores log events in a blocking queue and forwards them to other appenders on a separate thread. +Due to the asynchronous barrier, exceptions occurring in those appenders will not be forwarded to the caller of the log statement. + +The `Async` should be configured after the appenders it references to allow it to shut down properly. + +[TIP] +==== +The blocking queue is susceptible to lock contention, and performance may become worse when more threads are logging concurrently. +Consider using +xref:manual/async.adoc[lock-free asynchronous loggers] instead, for optimal performance. +==== + +[NOTE] +==== +Log4j 2 brought the following enhancements to the Log4j 1 async appender: + +* all appenders referenced by `AsyncAppender` flush their buffers to the OS at the end of a batch, when the queue becomes empty. +This guarantees that the batch of log events is passed to the OS and is a more performant version of the xref:manual/appenders.adoc#immediateFlush[`immediateFlush`] attribute. ++ +WARNING: Similarly to what happens with the `immediateFlush` attribute, this does not guarantee that the OS stores the data on the underlying device. + +* the type of queue is configurable to allow users to use faster and more performant queues, such as those from the +https://github.com/JCTools/JCTools?tab=readme-ov-file#jctools[JCTools] +or +https://github.com/conversant/disruptor[Conversant Disruptor] projects. +==== + +[#AsyncAppender-configuration] +=== `Async` configuration + +The `Async` Appender supports the following configuration options: + +[#AsyncAppender-attributes] +.`Async` Appender configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +4+h| Required + +| [[AsyncAppender-attr-name]]name +| `String` +| +| The name of the appender. + +4+h| Optional + +| [[AsyncAppender-attr-blocking]]blocking +| `boolean` +| `true` +| +If `true`, the Appender will wait until there are free slots in the queue. + +If false, the event will be written to the error +appender if the queue is full. The default is true. + +| [[AsyncAppender-attr-bufferSize]]bufferSize +| `int` +| 1024 +| +Specifies the maximum number of events that can be queued. + +When using a disruptor-style `BlockingQueue`, this +buffer size must be a power of 2. + +When the application is logging faster than the underlying appender can +keep up with for a long enough time to fill up the queue, the behavior +is determined by the <>. + +| [[AsyncAppender-attr-errorRef]]errorRef +| String +| +| The name of the appender to invoke if none of the appenders can be called, either due to exceptions in the appenders or because the queue is full. + +If not specified then errors will be ignored. + +| [[AsyncAppender-attr-includeLocation]]includeLocation +| boolean +| `false` +| +If set to `false`, location information will not be available to layouts of the downstream appenders. + +See xref:manual/layouts.adoc#LocationInformation[location information] for more information. + +| [[AsyncAppender-attr-ignoreExceptions]]ignoreExceptions +| `boolean` +| `true` +a| If `false`, logging exceptions will be forwarded to the caller of the log statement. +Otherwise, they will be ignored. + +Logging exceptions are always also logged to xref:manual/status-logger.adoc[] + +[NOTE] +==== +This setting only applies to logging exceptions that occur on the caller thread. +Exceptions that occur on the asynchronous thread will always be logged. +==== + +| [[AsyncAppender-attr-shutdownTimeout]]shutdownTimeout +| `int` +| `0` +| +Timeout in milliseconds to wait before stopping the asynchronous thread. + +A value of `0` will wait until the queue is empty. + +|=== + +[#AsyncAppender-elements] +.`Async` Appender nested elements +[cols="1m,1,4"] +|=== +| Type | Multiplicity | Description + +| [[AsyncAppender-element-Filter]]xref:manual/filters.adoc[`Filter`] +| zero or one +| +Allows filtering log events just before they are appended to the blocking queue. + +See also xref:manual/filters.adoc#appender-stage[appender filtering stage]. + +| [[AsyncAppender-element-AppenderRef]]xref:manual/configuration.adoc#configuring-appenderrefs[`AppenderRef`] +| one or more +| +A list of appenders to invoke asynchronously. + +See xref:manual/configuration.adoc#configuring-appenderrefs[appender references] for more information. + +| [[AsyncAppender-element-BlockingQueueFactory]]<> +| zero or one +| +The blocking queue factory implementation to use. + +If not provided, <> will be used. + +See <> below. + +|=== + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-AsyncAppender[{open-book} Plugin reference for `Async`] + +As an example, you can instrument a xref:manual/appenders/file.adoc#FileAppender[`File` appender] to perform asynchronous I/O, by using the following appender configurations: + +[tabs] +==== +XML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/async.xml[`log4j2.xml`] +[source,xml,indent=0] +---- +include::example$manual/appenders/delegating/async.xml[tag=appenders] +---- + +JSON:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/async.json[`log4j2.json`] +[source,json,indent=0] +---- +include::example$manual/appenders/delegating/async.json[tag=appenders] +---- + +YAML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/async.yaml[`log4j2.yaml`] +[source,yaml,indent=0] +---- +include::example$manual/appenders/delegating/async.yaml[tag=appenders] +---- + +Properties:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/async.properties[`log4j2.properties`] +[source,properties,indent=0] +---- +include::example$manual/appenders/delegating/async.properties[tag=appenders] +---- +==== + +[#AsyncQueueFullPolicy] +=== Queue full policy + +When the queue is full the `Async` Appender uses an +link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/AsyncQueueFullPolicy.html[`AsyncQueueFullPolicy`] +to decide whether to: + +* drop the log event. +* busy wait until the log event can be added to the queue. +* log the event on the current thread. + +The queue full policy can only be configured through +xref:manual/systemproperties.adoc[configuration properties]. +See xref:manual/systemproperties.adoc#properties-async[Async components] for more details. + +[#BlockingQueueFactory] +=== Blocking Queue Factories + +The `Async` appender allows you to customize the blocking queue used by specifying a nested +link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/BlockingQueueFactory.html[`BlockingQueueFactory`] +element. + +You can specify the size of the queue using the <> configuration attribute. + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-async-BlockingQueueFactory[{open-book} Plugin reference for `BlockingQueueFactory`] + +[#ArrayBlockingQueueFactory] +`ArrayBlockingQueue`:: ++ +This is the default implementation that produces +https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/concurrent/ArrayBlockingQueue.html[`ArrayBlockingQueue`]s. ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-async-ArrayBlockingQueueFactory[{open-book} Plugin reference for `ArrayBlockingQueue`] + +[#DisruptorBlockingQueueFactory] +`DisruptorBlockingQueue`:: ++ +This queue factory uses the +https://github.com/conversant/disruptor[Conversant Disruptor] +implementation of `BlockingQueue`. ++ +[#DisruptorBlockingQueueFactory-attributes] +.`DisruptorBlockingQueue` Factory configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +| spinPolicy +| https://javadoc.io/doc/com.conversantmedia/disruptor/latest/com.conversantmedia.disruptor/com/conversantmedia/util/concurrent/SpinPolicy.html[`SpinPolicy`] +| https://javadoc.io/doc/com.conversantmedia/disruptor/latest/com.conversantmedia.disruptor/com/conversantmedia/util/concurrent/SpinPolicy.html#WAITING[`WAITING`] +| +The `SpinPolicy` to apply, when adding elements to the queue. + +|=== ++ +.Additional dependencies are required to use `DisruptorBlockingQueue` +[%collapsible] +===== +[tabs] +==== +Maven:: ++ +[source,xml,subs="+attributes"] +---- + + com.conversantmedia + disruptor + {conversant-version} + runtime + +---- + +Gradle:: ++ +[source,groovy,subs="+attributes"] +---- +runtimeOnly 'com.conversantmedia:disruptor:{conversant-version}' +---- + +==== +===== ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-async-DisruptorBlockingQueueFactory[{open-book} Plugin reference for `DisruptorBlockingQueue`] + +[#JCToolsBlockingQueueFactory] +`JCToolsBlockingQueue`:: ++ +This queue factory uses +https://jctools.github.io/JCTools/[JCTools], specifically the MPSC bounded lock-free queue. ++ +.Additional dependencies are required to use `JCToolsBlockingQueue` +[%collapsible] +===== + +[tabs] +==== + +Maven:: ++ +[source,xml,subs="+attributes"] +---- + + org.jctools + jctools-core + {jctools-version} + runtime + +---- + +Gradle:: ++ +[source,groovy,subs="+attributes"] +---- +runtimeOnly 'org.jctools:jctools-core:{jctools-version}' +---- + +==== +===== + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-async-JCToolsBlockingQueueFactory[{open-book} Plugin reference for `JCToolsBlockingQueue`] + +[#LinkedTransferQueueFactory] +`LinkedTransferQueue`:: ++ +This queue factory produces +https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/concurrent/LinkedTransferQueue.html[`LinkedTransferQueue`]s. +Note that this queue does not have a maximum capacity and ignores the <> attribute. ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-async-LinkedTransferQueueFactory[{open-book} Plugin reference for `LinkedTransferQueue`] + +[#FailoverAppender] +== `Failover` Appender + +The `Failover` Appender can protect your logging pipeline against I/O exceptions in other appenders. + +During normal operations the `Failover` Appender forwards all log events to a primary appender. +However, if the primary appender fails, a set of secondary appenders will be checked until one succeeds. + +[#FailoverAppender-configuration] +=== `Failover` configuration + +The `Failover` Appender supports the following configuration options: + +[#FailoverAppender-attributes] +.`Failover` Appender configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +4+h| Required + +| [[FailoverAppender-attr-name]]name +| `String` +| +| +The name of this appender. + +| [[FailoverAppender-attr-primary]]primary +| `String` +| +| +The name of the primary appender to use. + +4+h| Optional + +| [[FailoverAppender-attr-retryIntervalSeconds]]retryIntervalSeconds +| `int` +| `60` +| +It specifies how many seconds to wait after a failure of the primary appender before the primary appender can be used again. + +| [[FailoverAppender-attr-ignoreExceptions]]ignoreExceptions +| `boolean` +| `true` +| If `false` and **all** the fallback appenders fail to handle the log event, the logging exception will be forwarded to the caller. +Otherwise, it will be ignored. + +Logging exceptions are always also logged to xref:manual/status-logger.adoc[] + +|=== + +[#FailoverAppender-elements] +.`Failover` Appender nested elements +[cols="1m,1,4"] +|=== +| Type | Multiplicity | Description + +| [[FailoverAppender-element-Filter]]xref:manual/filters.adoc[`Filter`] +| zero or one +| +Allows filtering log events just before they are appended to the blocking queue. + +See also xref:manual/filters.adoc#appender-stage[appender filtering stage]. + +| [[FailoverAppender-element-Failovers]]xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-FailoversPlugin[`Failovers`] +| **one** +| +A container element for a list of +xref:manual/configuration.adoc#configuring-appenderrefs[`AppenderRef`]s +that specifies the names of the secondary appenders +|=== + +[IMPORTANT] +==== +The primary appender must be configured to forward exceptions to the caller, by setting the +xref:manual/appenders.adoc#ignoreExceptions[`ignoreExceptions`] +configuration attribute to `false`. +==== + +The following example shows how to configure `Failover` to use an appender named `FILE` as primary and fall back to `CONSOLE` if an error occurs: + +[tabs] +==== +XML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/failover.xml[`log4j2.xml`] +[source,xml,indent=0] +---- +include::example$manual/appenders/delegating/failover.xml[tag=appenders] +---- + +JSON:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/failover.json[`log4j2.json`] +[source,json,indent=0] +---- +include::example$manual/appenders/delegating/failover.json[tag=appenders] +---- + +YAML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/failover.yaml[`log4j2.yaml`] +[source,yaml,indent=0] +---- +include::example$manual/appenders/delegating/failover.yaml[tag=appenders] +---- + +Properties:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/failover.properties[`log4j2.properties`] +[source,properties,indent=0] +---- +include::example$manual/appenders/delegating/failover.properties[tag=appenders] +---- +==== + +<1> The primary appender must set `ignoreExceptions` to `false`. + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-FailoverAppender[{open-book} Plugin reference for `Failover`] + +[#RewriteAppender] +== `Rewrite` Appender + +The `Rewrite` allows the log events to be manipulated before they are processed by another Appender. +This can be used to inject additional information into each event. + +[NOTE] +==== +Although this appender can be used to mask sensitive information contained in log events, we strongly discourage such practice. +Sensitive data like passwords and credit card numbers can appear in log files in many formats, and it is challenging to detect them all. + +A better approach to sensitive data is not to log them at all. +Third-party frameworks like +https://github.com/palantir/safe-logging[Palantir `safe-logging`] +can ensure that objects marked as sensitive are not passed as parameters to log statements. +==== + +[#RewriteAppender-configuration] +=== `Rewrite` Configuration + +[#RewriteAppender-attributes] +.`Rewrite` Appender configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +4+h| Required + +| [[RewriteAppender-attr-name]]name +| `String` +| +| +The name of this appender. + +4+h| Optional + +| [[RewriteAppender-attr-ignoreExceptions]]ignoreExceptions +| `boolean` +| `true` +| If `false` and the downstream appender fails with an exception, the exception will be propagated to the caller. +Otherwise, it will be ignored. + +Logging exceptions are always also logged to xref:manual/status-logger.adoc[] + +|=== + +[#RewriteAppender-elements] +.`Rewrite` Appender nested elements +[cols="1m,1,4"] +|=== +| Type | Multiplicity | Description + +| [[RewriteAppender-element-AppenderRef]]xref:manual/configuration.adoc#configuring-appenderrefs[`AppenderRef`] +| **one** +| +The +xref:manual/configuration.adoc#configuring-appenderrefs[reference to an appender] +that will perform the actual logging. + +| [[RewriteAppender-element-Filter]]xref:manual/filters.adoc[`Filter`] +| zero or one +| +Allows filtering log events just before they are appended to the blocking queue. + +See also xref:manual/filters.adoc#appender-stage[appender filtering stage]. + +| [[RewriteAppender-element-RewritePolicy]]<> +| **one** +| +The <> to apply to all logged events. + +|=== + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rewrite-RewriteAppender[{open-book} Plugin reference for `Rewrite`] + +[#RewritePolicy] +=== Rewrite Policies + +A rewrite policy is a Log4j plugin that implements the +link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rewrite/RewritePolicy.html[`RewritePolicy`] +interface. +Rewrite policies allow to apply arbitrary modifications to log events. + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rewrite-RewritePolicy[{open-book} Plugin reference for `RewritePolicy`] + +Log4j Core provides three rewrite policies out-of-the-box: + +[#MapRewritePolicy] +`MapRewritePolicy`:: ++ +The `MapRewritePolicy` only modifies events that contain a +xref:manual/messages.adoc#MapMessage[`MapMessage`]. +It allows adding or updating the keys of the `MapMessage`. ++ +[#MapRewritePolicy-attributes] +.`MapRewritePolicy` configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +| [[MapRewritePolicy-attr-mode]]mode +| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rewrite/MapRewritePolicy.Mode.html[`MapRewritePolicy.Mode`] +| link:../https://logging.apache.org/log4j/2.x/javadoc/log4j-core/org/apache/logging/log4j/core/appender/rewrite/MapRewritePolicy.Mode.html#Add[`Add`] +a| +It determines which map entries to modify: + +Add:: +All the configured map entries will be added to the `MapMessage`, modifying the existing ones. + +Update:: +The rewrite policy will add to the `MapMessage` only entries corresponding to existing keys. + +|=== ++ +[#MapRewritePolicy-elements] +.`MapRewritePolicy` nested elements +[cols="1m,1,4"] +|=== + +| Type | Multiplicity | Description + +| [[MapRewritePolicy-element-KeyValuePair]] +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-util-KeyValuePair[`KeyValuePair`] +| one or more +| +A list of map entries to add to the `MapMessage`. + +|=== ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rewrite-MapRewritePolicy[{open-book} Plugin reference for `MapRewritePolicy`] + +[#PropertiesRewritePolicy] +`PropertiesRewritePolicy`:: ++ +The `PropertiesRewritePolicy` will add properties to the context data of the log event. ++ +[NOTE] +==== +Only the context data of the log event will be modified. +The contents of the xref:manual/thread-context.adoc[] will remain unchanged. +==== ++ +[#PropertiesRewritePolicy-elements] +.`PropertiesRewritePolicy` nested elements +[cols="1m,1,4"] +|=== +| Type | Multiplicity | Description + +| [[PropertiesRewritePolicy-element-Property]]xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-config-Property[`Property`] +| one or more +| +A list of map entries to add to the context data of the log event. + +The `value` attribute of each `Property` element supports +xref:manual/configuration.adoc#lazy-property-substitution[runtime property substitution] +in the +xref:manual/lookups.adoc#global-context[_global context_]. +|=== ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rewrite-PropertiesRewritePolicy[{open-book} Plugin reference for `PropertiesRewritePolicy`] + +[#LoggerNameLevelRewritePolicy] +LoggerNameLevelRewritePolicy:: ++ +You can use this policy to change the log level of loggers from third-party libraries. +The `LoggerNameLevelRewritePolicy` will rewrite the level of log event for a given logger name prefix. ++ +[WARNING] +==== +The new log levels will only be used by the filter attached to the `Rewrite` appender and those downstream of the appender. +Filters configured on loggers will use the previous levels. +See xref:manual/filters.adoc[] for more details on filtering +==== ++ +[#LoggerNameLevelRewritePolicy-attributes] +.`LoggerNameLevelRewritePolicy` configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +| [[LoggerNameLevelRewritePolicy-attr-mode]]logger +| `String` +| +| +The rewrite policy will only be applied to loggers with this logger name and their children. + +|=== ++ +[#LoggerNameLevelRewritePolicy-elements] +.`LoggerNameLevelRewritePolicy` nested elements +[cols="1m,1,4"] +|=== +| Type | Multiplicity | Description + +| [[LoggerNameLevelRewritePolicy-element-KeyValuePair]]xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-util-KeyValuePair[`KeyValuePair`] +| one or more +| +Provides a mapping between old level names and new level names. + +|=== ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-rewrite-LoggerNameLevelRewritePolicy[{open-book} Plugin reference for `LoggerNameLevelRewritePolicy`] + +[#RewriteAppender-examples] +=== Configuration example + +If a library `org.example` over-evaluates the severity of its log events, you decrease their severity with the following configuration: + +[tabs] +==== +XML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/rewrite.xml[`log4j2.xml`] +[source,xml,indent=0] +---- +include::example$manual/appenders/delegating/rewrite.xml[tag=appender] +---- + +JSON:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/rewrite.json[`log4j2.json`] +[source,json,indent=0] +---- +include::example$manual/appenders/delegating/rewrite.json[tag=appender] +---- + +YAML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/rewrite.yaml[`log4j2.yaml`] +[source,yaml,indent=0] +---- +include::example$manual/appenders/delegating/rewrite.yaml[tag=appender] +---- + +Properties:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/rewrite.properties[`log4j2.properties`] +[source,properties,indent=0] +---- +include::example$manual/appenders/delegating/rewrite.properties[tag=appender] +---- +==== + +<1> Decreases the severity of `WARN` and `INFO` messages, so they appear with the new severity in your log viewer. +<2> If additionally you don't want to log `DEBUG` log events, you must apply a filter. + +[#RoutingAppender] +== `Routing` Appender + +The `Routing` Appender evaluates log events and then routes them to one of its subordinate appenders. +The target appender may be: + +* an existing appender referenced by its name. +* a new appender obtained by evaluating a configuration snippet. + +The `Routing` Appender should be configured after any appenders it references to allow it to shut down properly. + +[#RoutingAppender-configuration] +=== `Routing` Configuration + +[#RoutingAppender-attributes] +.`Routing` Appender configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +4+h| Required + +| [[RoutingAppender-attr-name]]name +| `String` +| +| +The name of this appender. + +4+h| Optional + +| [[RoutingAppender-attr-ignoreExceptions]]ignoreExceptions +| `boolean` +| `true` +| If `false` and the downstream appender fails with an exception, the exception will be propagated to the caller. +Otherwise, it will be ignored. + +Logging exceptions are always also logged to xref:manual/status-logger.adoc[] + +|=== + +[#RoutingAppender-elements] +.`Routing` Appender nested elements +[cols="1m,1,4"] +|=== +| Type | Multiplicity | Description + +| [[RoutingAppender-element-AbstractScript]]xref:manual/scripts.adoc[`AbstractScript`] +| zero or one +a| +This script has two purposes: + +. It initializes a shared `Map` bound to the `staticVariables` identifier. +The values of this map can be used later by the <>. +. It returns the name of the default route. + +The script has the following bindings: + +`staticVariables`:: +A `Map` that is reused between script calls. +This is the same map, which is passed to the <>. + +`configuration`:: +The current xref:manual/configuration.adoc[`Configuration` object]. + +`statusLogger`:: +The xref:manual/status-logger.adoc[] to use to print diagnostic messages in the script. + +See also xref:manual/scripts.adoc[] for more details on scripting in Log4j Core. + +| [[RoutingAppender-element-Filter]]xref:manual/filters.adoc[`Filter`] +| zero or one +| +Allows filtering log events before routing them to a subordinate appender. + +See also xref:manual/filters.adoc#appender-stage[appender filtering stage]. + +| [[RoutingAppender-element-PurgePolicy]]<> +| zero or one +| +The <> to apply to handle the lifecycle of automatically instantiated appenders. + +See <> for more details. + +| [[RoutingAppender-element-RewritePolicy]]<> +| zero or one +| +The <> to apply to all logged events. + +If set, the `Routing` appender will rewrite a log event before routing it. +See also <>. + +| [[RoutingApender-element-Routes]]<> +| **one** +| +Determines the routing configuration of the appender. + +See <> for more details. + +|=== + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-routing-RoutingAppender[{open-book} Plugin reference for `Routing`] + +[#route-selection] +=== Route selection + +At the base of route selection there are two configuration elements: + +[#Routes] +`Routes`:: ++ +The `Routes` element is a container for <> definitions. +It provides two additional properties, which are used to determine the appropriate route for each log event: ++ +[#Routes-attributes] +.`Routes` configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +| [[Routes-attr-pattern]]pattern +| `String` +| +| +If present, this pattern is evaluated at each log event to determine the key of the route to use. + +This attribute supports +xref:manual/configuration.adoc#lazy-property-substitution[runtime property substitution] +using the +xref:manual/lookups.adoc#event-context[current event as context]. + +**Required**, unless a nested <> is provided. +|=== ++ +[#Routes-elements] +.`Routes` nested elements +[cols="1m,1,4"] +|=== +| Type | Multiplicity | Description + +| [[Routes-element-AbstractScript]]xref:manual/scripts.adoc[`AbstractScript`] +| zero or one +a| +If present, this script is evaluated at each log event to determine the key of the route to use. +The script has the following bindings: + +`staticVariables`:: +A `Map` that is reused between script calls. +This is the same map, which is passed to the <>. + +`logEvent`:: +The +link:../javadoc/log4j-core/org/apache/logging/log4j/core/LogEvent.html[`LogEvent`] +being processed. + +`configuration`:: +The current xref:manual/configuration.adoc[`Configuration` object]. + +`statusLogger`:: +The xref:manual/status-logger.adoc[] to use to print diagnostic messages in the script. + +See also xref:manual/scripts.adoc[] for more details on scripting in Log4j Core. + +**Required**, unless the <> attribute is provided. + +| <> +| one or more +| +|=== ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-routing-Routes[{open-book} Plugin reference for `Routes`] + +[#Route] +`Route`:: +The `Route` element determines the appender to use if the route is selected. +The appender can be: ++ +-- +* A previously declared appender, from the xref:manual/configuration.adoc#main-configuration-elements[`Appenders` section] of the configuration file. +* A new appender that is instantiated based on a nested appender definition, when the route becomes active. +See also <> to learn more about the lifecycle of such an appender. +-- ++ +[#Route-attributes] +.`Route` configuration attributes +[cols="1m,1,1,5"] +|=== + +| Attribute | Type | Default value | Description + +| [[Route-attr-key]] +key +| `String` +| `null` +| +A key that is compared with the evaluation of either the <> attribute or <> of the `Routes element. + +| [[Route-attr-ref]] +ref +| `String` +| +| +The reference to an existing appender to use. + +You cannot specify both this attribute and a <>. + +|=== ++ +[#Route-elements] +.`Route` nested elements +[cols="1m,1,4"] +|=== + +| Type | Multiplicity | Description + +| [[Route-element-Appender]] +xref:manual/appenders.adoc[`Appender`] +| zero or one +| +The definition of an `Appender` to create, when this route is used for the first time. + +You cannot specify both this nested element and the <>. + +|=== ++ +[WARNING] +==== +Lookups in the **children** of the `Route` component are **not** evaluated at configuration time. +The substitution is delayed until the `Route` element is evaluated. +This means that `$+{...}+` expression **should not** be escaped as `$$+{...}+`. + +The appender definition is evaluated in the xref:manual/lookups.adoc#event-context[context of the current event], instead of the global context. + +See xref:manual/configuration.adoc#lazy-property-substitution[lazy property substitution] for more details. +==== ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-routing-Route[{open-book} Plugin reference for `Route`] + +For each log event, the appropriate route is selected as follows: + +. First the <> or <> are evaluated to obtain a **key**. +. The key is compared with the <> of each `Route` element. +. If there is a `Route` for that key, it is selected. +. Otherwise, the **default** `Route` is selected. The key of the default `Route` is determined by the <> or is `null` (lack of <>) if the script is absent. + +[NOTE] +==== +If the `Route` element contains an appender definition, the appender will be instantiated: + +* once if the `Route` has a non-default key. +* once for each value of the key, if the `Route` has the default key. +==== + +[#PurgePolicy] +=== Purge Policy + +If your default <> contains an <>, the `Routing` Appender can instantiate a large number of appenders, one for each value of the routing key. +These appenders might be useful only for a short period of time, but will consume system resources unless they are stopped. + +The purge policy is a Log4j plugin that implements the +link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/routing/PurgePolicy.html[`PurgePolicy`] +interface and handles the lifecycle of automatically instantiated appenders. + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-routing-PurgePolicy[{open-book} Plugin reference for `PurgePolicy`] + +[NOTE] +==== +If an appender has been destroyed, it can be created again when the `Route` is selected again. +==== + +Log4j Core provides one implementation of `PurgePolicy`: + +[#IdlePurgePolicy] +`IdlePurgePolicy`:: ++ +This policy destroys appenders if they have not been used for a certain amount of time. +It supports the following configuration attributes: ++ +[#IdlePurgePolicy-attributes] +.`IdlePurgePolicy` configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +| [[IdlePurgePolicy-attr-timeToLive]]timeToLive +| `long` +| +| +It specifies the number of <> that an appender can be idle, before it is destroyed. + +**Required** + +| [[IdlePurgePolicy-attr-checkInterval]]checkInterval +| `long` +| <> +| +It specifies the number of <> between two runs of this purge policy. + +| [[IdlePurgePolicy-attr-timeUnit]]timeUnit +| https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/TimeUnit.html[`TimeUnit`] +| https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/TimeUnit.html#MINUTES[`MINUTES`] +| +It specifies the time unit to use for the other attributes. + +|=== ++ +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-routing-IdlePurgePolicy[{open-book} Plugin reference for `IdlePurgePolicy`] + +[#RoutingAppender-examples] +=== Configuration examples + +[#RoutingAppender-example-ref] +==== Using appender references + +You can deliver log events for different xref:manual/markers.adoc[] into separate log files, using the following configuration: + +[tabs] +==== +XML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-ref.xml[`log4j2.xml`] +[source,xml,indent=0] +---- +include::example$manual/appenders/delegating/routing-ref.xml[tag=appender] +---- + +JSON:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-ref.json[`log4j2.json`] +[source,json,indent=0] +---- +include::example$manual/appenders/delegating/routing-ref.json[tag=appender] +---- + +YAML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-ref.yaml[`log4j2.yaml`] +[source,yaml,indent=0] +---- +include::example$manual/appenders/delegating/routing-ref.yaml[tag=appender] +---- + +Properties:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-ref.properties[`log4j2.properties`] +[source,properties,indent=0] +---- +include::example$manual/appenders/delegating/routing-ref.properties[tag=appender] +---- +==== + +<1> This route is selected if the log event is marked with an `AUDIT` marker. +<2> This route is selected if the log event has no marker. +In this case the expression `+${event:Marker}+` evaluates to itself. +See xref:manual/configuration.adoc#property-substitution[Property evaluation] for more details. +<3> This is the **default** route. +It is selected if the log event has a marker, but it is not the `AUDIT` marker. + +[#RoutingAppender-example-definition] +==== Using appender definitions + +If the number of appenders is high or unknown, you might want to use appender definitions instead of appender references. +In the example below, a different log file is created for each xref:manual/markers.adoc[marker]. + +[tabs] +==== +XML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-definition.xml[`log4j2.xml`] +[source,xml,indent=0] +---- +include::example$manual/appenders/delegating/routing-definition.xml[tag=appender] +---- + +JSON:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-definition.json[`log4j2.json`] +[source,json,indent=0] +---- +include::example$manual/appenders/delegating/routing-definition.json[tag=appender] +---- + +YAML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-definition.yaml[`log4j2.yaml`] +[source,yaml,indent=0] +---- +include::example$manual/appenders/delegating/routing-definition.yaml[tag=appender] +---- + +Properties:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-definition.properties[`log4j2.properties`] +[source,properties,indent=0] +---- +include::example$manual/appenders/delegating/routing-definition.properties[tag=appender] +---- +==== + +<1> The `pattern` attribute is evaluated at configuration time, so the `+${event:Marker}+` lookup needs to be escaped. +<2> The appender definition is **not** evaluated at configuration time, so no escaping is necessary. +<3> To prevent resource leaks, consider using a <>. + +[#RoutingAppender-example-script] +==== Using scripts + +If the flexibility of xref:manual/lookups.adoc[] is not enough to express your routing logic, you can also resort to scripts. +In the example below, we route messages in a round-robin fashion to three different Syslog servers: + +[tabs] +==== +XML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-script.xml[`log4j2.xml`] +[source,xml,indent=0] +---- +include::example$manual/appenders/delegating/routing-script.xml[tag=appender] +---- + +JSON:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-script.json[`log4j2.json`] +[source,json,indent=0] +---- +include::example$manual/appenders/delegating/routing-script.json[tag=appender] +---- + +YAML:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-script.yaml[`log4j2.yaml`] +[source,yaml,indent=0] +---- +include::example$manual/appenders/delegating/routing-script.yaml[tag=appender] +---- + +Properties:: ++ +.Snippet from an example {antora-examples-url}/manual/appenders/delegating/routing-script.properties[`log4j2.properties`] +[source,properties,indent=0] +---- +include::example$manual/appenders/delegating/routing-script.properties[tag=appender] +---- +==== + +<1> The <> performs the initialization of state variables. +<2> The <> returns the name of the server to use. +It also exports the value as `server` entry in +link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html#getProperties()[`Configuration.getProperties()`]. +<3> The exported value can be used as `+${server}+` in the appender definition. + +[#ScriptAppenderSelector] +== `ScriptAppenderSelector` + +The `ScriptAppenderSelector` plugin allows using different appender definitions based on the output of a script. +At **configuration time**: + +. The nested script element is evaluated to obtain the name of an appender. +. The plugin looks for the appropriate appender definition inside the `` container. + +[IMPORTANT] +==== +The functionality of `ScriptAppenderSelector` has been replaced by the more general +xref:manual/configuration.adoc#arbiters[`Arbiter` mechanism]. +==== + +[#ScriptAppenderSelector-attributes] +.`ScriptAppenderSelector` Appender configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description +| [[ScriptAppenderSelector-attr-name]]name +| `String` +| +| +The name of this appender. + +**Required** +|=== + +[#ScriptAppenderSelector-elements] +.`ScriptAppenderSelector` Appender nested elements +[cols="1m,1,4"] +|=== +| Type | Multiplicity | Description + +| [[ScriptAppenderSelector-element-AbstractScript]]xref:manual/scripts.adoc[`AbstractScript`] +| **one** +| +The script to determine the appender name. + +| [[RoutingAppender-element-AppenderSet]]`AppenderSet` +| **one** +| +A lazy container for appender definitions. + +|=== + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-ScriptAppenderSelector[{open-book} Plugin reference for `ScriptAppenderSelector`] \ No newline at end of file diff --git a/src/site/antora/modules/ROOT/pages/manual/appenders/file.adoc b/src/site/antora/modules/ROOT/pages/manual/appenders/file.adoc new file mode 100644 index 00000000000..e84b666fe33 --- /dev/null +++ b/src/site/antora/modules/ROOT/pages/manual/appenders/file.adoc @@ -0,0 +1,279 @@ +//// + 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. +//// + += File appenders +:check-mark: ✓ +:open-book: 📖 +:x-mark: ✗ + +Log4j Core provides multiple appenders that store log messages in a file. +These appenders differ in the way they access the file system and might provide different performance characteristics. + +[NOTE] +==== +File appenders do not offer a mechanism for external applications to force it to reopen the log file. +External log archiving tools such as +https://github.com/logrotate/logrotate[`logrotate`] +will therefore need to copy the current log file and **then** truncate it. +Log events emitted during this operation will be lost. + +If you want to rotate your log files, use xref:manual/appenders/rolling-file.adoc[a rolling file appender] instead. +==== + +[#appenders] +== Appenders + +Log4j Core provides three file appender implementations: + +`File`:: +The `File` Appender uses +https://docs.oracle.com/javase/{java-target-version}/docs/api/java/io/FileOutputStream.html[`FileOutputStream`] +to access log files. + +`RandomAccessFile`:: +The `RandomAccessFile` Appender uses +https://docs.oracle.com/javase/{java-target-version}/docs/api/java/io/RandomAccessFile.html[`RandomAccessFile`] +to access log files. + +`MemoryMappedFile`:: +The `MemoryMappedFile` Appender maps log files into a +https://docs.oracle.com/javase/8/docs/api/java/nio/MappedByteBuffer.html[`MappedByteBuffer`]. ++ +Instead of making system calls to write to disk, this appender can simply change the program's local memory, which is orders of magnitude faster. + +[NOTE] +==== +Two appenders, even from different logger contexts, share a common +xref:manual/architecture.adoc#AbstractManager[`FileManager`] +if they use the same value <>. + +Sharing a `FileManager` guarantees that multiple appenders will access the log file sequentially, 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-fileName]]fileName +| https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/file/Path.html[`Path`] +| +| The path to the current log file +If the folder containing the file does not exist, it will be created. + +| [[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-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. + +|=== + +[#FileAppender] +=== `File` configuration + +The `File` Appender provides the following configuration options, beyond the <>: + +[#FileAppender-attributes] +.`File` configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +| [[FileAppender-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. + +| [[FileAppender-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. + +See xref:manual/appenders.adoc#buffering[Buffering] for more details. + +| [[FileAppender-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. + +| [[FileAppender-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. + +| [[FileAppender-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. + +| [[FileAppender-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. + +| [[FileAppender-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-FileAppender[{open-book} Plugin reference for `File`] + +[#RandomAccessFileAppender] +=== `RandomAccessFile` configuration + +The `RandomAccessFile` Appender provides the following configuration options, beyond the <>: + +[#RandomAccessFileAppender-attributes] +.`RollingRandomAccessFile` configuration attributes +[cols="1m,1,1,5"] +|=== +| Attribute | Type | Default value | Description + +| [[RandomAccessFileAppender-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 +<>. +The log file cannot be opened by multiple applications at the same time. +|=== + +Unlike the <>, this appender always uses an internal buffer of size <>. + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-RandomAccessFileAppender[{open-book} Plugin reference for `RandomAccessFile`] + +[#MemoryMappedFileAppender] +=== `MemoryMappedFile` configuration + +The `MemoryMappedFile` Appender provides the following configuration options, beyond the <>: + +[#MemoryMappedFileAppender-attributes] +.`RollingRandomAccessFile` configuration attributes +[cols="1m,1,2,5"] +|=== +| Attribute | Type | Default value | Description + +| [[MemoryMappedFileAppender-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 +<>. +The log file cannot be opened by multiple applications at the same time. + +| [[MemoryMappedFileAppender-attr-regionLength]]regionLength +| `int` +| `32 × 1024 × 1024` +| +It specifies the size measured in bytes of the memory mapped log file buffer. +|=== + +Unlike other file appenders, this appender always uses a memory mapped buffer of size <> as its internal buffer. + +xref:plugin-reference.adoc#org-apache-logging-log4j_log4j-core_org-apache-logging-log4j-core-appender-MemoryMappedFileAppender[{open-book} Plugin reference for `MemoryMappedFile`] diff --git a/src/site/antora/modules/ROOT/pages/manual/rolling-file.adoc b/src/site/antora/modules/ROOT/pages/manual/appenders/rolling-file.adoc similarity index 90% rename from src/site/antora/modules/ROOT/pages/manual/rolling-file.adoc rename to src/site/antora/modules/ROOT/pages/manual/appenders/rolling-file.adoc index 66b3f1f8765..5d5c5fb00b7 100644 --- a/src/site/antora/modules/ROOT/pages/manual/rolling-file.adoc +++ b/src/site/antora/modules/ROOT/pages/manual/appenders/rolling-file.adoc @@ -408,7 +408,7 @@ On startup the cron expression will be evaluated against the current file's crea 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`] +| 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]. @@ -423,7 +423,7 @@ The supported fields are in order: * day of week See -link:../javadoc/log4j-core/org/apache/logging/log4j/core/util/CronExpression.html[`CronExpression`] +link:../../javadoc/log4j-core/org/apache/logging/log4j/core/util/CronExpression.html[`CronExpression`] for a full specification of the format. |=== @@ -456,7 +456,7 @@ Otherwise, the target file will be overwritten on each rollover. | Attribute | Type | Default value | Description | [[SizeBasedTriggeringPolicy-attr-size]]size -| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/FileSize.html[`FileSize`] +| 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. @@ -564,34 +564,34 @@ For example, the following XML fragment defines policies that rollover the log: ==== XML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/policies.xml[`log4j2.xml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/policies.xml[`log4j2.xml`] [source,xml,indent=0] ---- -include::example$manual/rolling-file/policies.xml[tag=appender] +include::example$manual/appenders/rolling-file/policies.xml[tag=appender] ---- JSON:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/policies.json[`log4j2.json`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/policies.json[`log4j2.json`] [source,json,indent=0] ---- -include::example$manual/rolling-file/policies.json[tag=appender] +include::example$manual/appenders/rolling-file/policies.json[tag=appender] ---- YAML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/policies.yaml[`log4j2.yaml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/policies.yaml[`log4j2.yaml`] [source,yaml,indent=0] ---- -include::example$manual/rolling-file/policies.yaml[tag=appender] +include::example$manual/appenders/rolling-file/policies.yaml[tag=appender] ---- Properties:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/policies.properties[`log4j2.properties`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/policies.properties[`log4j2.properties`] [source,properties,indent=0] ---- -include::example$manual/rolling-file/policies.properties[tag=appender] +include::example$manual/appenders/rolling-file/policies.properties[tag=appender] ---- ==== @@ -670,7 +670,7 @@ See <> for more details. |=== | Type | Multiplicity | Description -| [[element-Action]]link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/Action.html[`Action`] +| [[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. @@ -1106,13 +1106,13 @@ If present, the action will only be performed on files for which the condition r **Required**, unless a <> 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`] +| [[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 <>. The default implementation is -link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathSortByModificationTime.html[`PathSortByModificationTime`], +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]]<> @@ -1217,7 +1217,7 @@ See <> for more information. | Attribute | Type | Default value | Description | [[IfAccumulatedFileSize-attr-exceeds]]exceeds -| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/FileSize.html[`FileSize`] +| link:../../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/FileSize.html[`FileSize`] | | The threshold size for the condition to match. @@ -1345,7 +1345,7 @@ Accepts files based on their last modification timestamp. | Attribute | Type | Default value | Description | [[IfLastModified-attr-age]]age -| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/Duration.html[`Duration`] +| 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. @@ -1442,7 +1442,7 @@ 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`] +link:../../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html[`PathWithAttributes`] objects and supports the following bindings: [#ScriptFilter-bindings] @@ -1461,7 +1461,7 @@ objects and supports the following bindings: The `Configuration` object. | [[ScriptFilter-binding-pathList]]pathList -| link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html[`List`] +| link:../../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html[`List`] | The list of files contained in the base directory. @@ -1471,11 +1471,11 @@ the relative file names against <>. | [[ScriptFilter-binding-substitutor]]substitutor -| link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrSubstitutor.html[`StrSubstitutor`] +| 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`] +| 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. | @@ -1524,34 +1524,34 @@ An equivalent configuration will look like this: ==== XML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/logrotate.xml[`log4j2.xml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/logrotate.xml[`log4j2.xml`] [source,xml,indent=0] ---- -include::example$manual/rolling-file/logrotate.xml[tag=appender] +include::example$manual/appenders/rolling-file/logrotate.xml[tag=appender] ---- JSON:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/logrotate.json[`log4j2.json`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/logrotate.json[`log4j2.json`] [source,json,indent=0] ---- -include::example$manual/rolling-file/logrotate.json[tag=appender] +include::example$manual/appenders/rolling-file/logrotate.json[tag=appender] ---- YAML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/logrotate.yaml[`log4j2.yaml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/logrotate.yaml[`log4j2.yaml`] [source,yaml,indent=0] ---- -include::example$manual/rolling-file/logrotate.yaml[tag=appender] +include::example$manual/appenders/rolling-file/logrotate.yaml[tag=appender] ---- Properties:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/logrotate.properties[`log4j2.properties`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/logrotate.properties[`log4j2.properties`] [source,properties,indent=0] ---- -include::example$manual/rolling-file/logrotate.properties[tag=appender] +include::example$manual/appenders/rolling-file/logrotate.properties[tag=appender] ---- ==== @@ -1574,34 +1574,34 @@ Since we have a `%d` pattern in the configuration file, we need to use an explic ==== XML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/timestamped.xml[`log4j2.xml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/timestamped.xml[`log4j2.xml`] [source,xml,indent=0] ---- -include::example$manual/rolling-file/timestamped.xml[tag=appender] +include::example$manual/appenders/rolling-file/timestamped.xml[tag=appender] ---- JSON:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/timestamped.json[`log4j2.json`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/timestamped.json[`log4j2.json`] [source,json,indent=0] ---- -include::example$manual/rolling-file/timestamped.json[tag=appender] +include::example$manual/appenders/rolling-file/timestamped.json[tag=appender] ---- YAML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/timestamped.yaml[`log4j2.yaml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/timestamped.yaml[`log4j2.yaml`] [source,yaml,indent=0] ---- -include::example$manual/rolling-file/timestamped.yaml[tag=appender] +include::example$manual/appenders/rolling-file/timestamped.yaml[tag=appender] ---- Properties:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/timestamped.properties[`log4j2.properties`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/timestamped.properties[`log4j2.properties`] [source,properties,indent=0] ---- -include::example$manual/rolling-file/timestamped.properties[tag=appender] +include::example$manual/appenders/rolling-file/timestamped.properties[tag=appender] ---- ==== @@ -1616,14 +1616,14 @@ If the supplied <> are not sufficient, you can us The <> can be rewritten into the following Groovy script: -.Snippet from an example {antora-examples-url}/manual/rolling-file/script-condition.groovy[`script-condition.groovy`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/script-condition.groovy[`script-condition.groovy`] [source,groovy] ---- -include::example$manual/rolling-file/script-condition.groovy[tag=script] +include::example$manual/appenders/rolling-file/script-condition.groovy[tag=script] ---- <1> Adding xref:manual/status-logger.adoc[] calls in your script might help in debugging it. -<2> link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html#getPath()[`PathWithAttributes.getPath()`] +<2> link:../../javadoc/log4j-core/org/apache/logging/log4j/core/appender/rolling/action/PathWithAttributes.html#getPath()[`PathWithAttributes.getPath()`] always starts with `basePath`, so we need to relativize it. <3> Equivalent to the <> condition. <4> Equivalent to the <> condition. @@ -1634,34 +1634,34 @@ You can use the script in your configuration file as follows: ==== XML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/script-condition.xml[`log4j2.xml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/script-condition.xml[`log4j2.xml`] [source,xml,indent=0] ---- -include::example$manual/rolling-file/script-condition.xml[tag=appender] +include::example$manual/appenders/rolling-file/script-condition.xml[tag=appender] ---- JSON:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/script-condition.json[`log4j2.json`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/script-condition.json[`log4j2.json`] [source,json,indent=0] ---- -include::example$manual/rolling-file/script-condition.json[tag=appender] +include::example$manual/appenders/rolling-file/script-condition.json[tag=appender] ---- YAML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/script-condition.yaml[`log4j2.yaml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/script-condition.yaml[`log4j2.yaml`] [source,yaml,indent=0] ---- -include::example$manual/rolling-file/script-condition.yaml[tag=appender] +include::example$manual/appenders/rolling-file/script-condition.yaml[tag=appender] ---- Properties:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/script-condition.properties[`log4j2.properties`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/script-condition.properties[`log4j2.properties`] [source,properties,indent=0] ---- -include::example$manual/rolling-file/script-condition.properties[tag=appender] +include::example$manual/appenders/rolling-file/script-condition.properties[tag=appender] ---- ==== @@ -1675,34 +1675,34 @@ In the example below, we create a different folder for each month: ==== XML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/per-month.xml[`log4j2.xml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/per-month.xml[`log4j2.xml`] [source,xml,indent=0] ---- -include::example$manual/rolling-file/per-month.xml[tag=appender] +include::example$manual/appenders/rolling-file/per-month.xml[tag=appender] ---- JSON:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/per-month.json[`log4j2.json`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/per-month.json[`log4j2.json`] [source,json,indent=0] ---- -include::example$manual/rolling-file/per-month.json[tag=appender] +include::example$manual/appenders/rolling-file/per-month.json[tag=appender] ---- YAML:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/per-month.yaml[`log4j2.yaml`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/per-month.yaml[`log4j2.yaml`] [source,yaml,indent=0] ---- -include::example$manual/rolling-file/per-month.yaml[tag=appender] +include::example$manual/appenders/rolling-file/per-month.yaml[tag=appender] ---- Properties:: + -.Snippet from an example {antora-examples-url}/manual/rolling-file/per-month.properties[`log4j2.properties`] +.Snippet from an example {antora-examples-url}/manual/appenders/rolling-file/per-month.properties[`log4j2.properties`] [source,properties,indent=0] ---- -include::example$manual/rolling-file/per-month.properties[tag=appender] +include::example$manual/appenders/rolling-file/per-month.properties[tag=appender] ---- ====