Externalize examples
diff --git a/pom.xml b/pom.xml
index da15c02..e24b65b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -604,6 +604,23 @@
</configuration>
</plugin>
+ <!--
+ ~ Adds Antora examples to the list of checked files
+ -->
+ <plugin>
+ <groupId>com.diffplug.spotless</groupId>
+ <artifactId>spotless-maven-plugin</artifactId>
+ <configuration>
+ <java>
+ <includes>
+ <include>src/main/java/**/*.java</include>
+ <include>src/test/java/**/*.java</include>
+ <include>src/site/antora/modules/ROOT/examples/**/*.java</include>
+ </includes>
+ </java>
+ </configuration>
+ </plugin>
+
<!-- ███████ ████████ █████ ██████ ████████ ███████ ██ ████████ ███████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████ ██ ███████ ██████ ██ ███████ ██ ██ █████
diff --git a/src/site/antora/antora.tmpl.yml b/src/site/antora/antora.tmpl.yml
index 0b0192a..034e5de 100644
--- a/src/site/antora/antora.tmpl.yml
+++ b/src/site/antora/antora.tmpl.yml
@@ -39,6 +39,7 @@
asciidoc:
attributes:
# Commons
+ antora-examples-url: "https://raw.githubusercontent.com/apache/logging-log4j2/2.x/src/site/antora/modules/ROOT/examples"
project-github-url: "${scm.url}"
project-name: "Log4j"
project-id: "log4j"
diff --git a/src/site/antora/antora.yml b/src/site/antora/antora.yml
index 6e86de6..f5ebbf6 100644
--- a/src/site/antora/antora.yml
+++ b/src/site/antora/antora.yml
@@ -39,7 +39,8 @@
asciidoc:
attributes:
# Commons
- project-github-url: "https://github.com/apache/logging-log4j2"
+ antora-examples-url: "https://raw.githubusercontent.com/apache/logging-log4j2/2.x/src/site/antora/modules/ROOT/examples"
+ project-github-url: "https://github.com/apache/logging-log4j2/"
project-name: "Log4j"
project-id: "log4j"
java-target-version: "8"
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/MarkerExample.java b/src/site/antora/modules/ROOT/examples/manual/markers/MarkerExample.java
new file mode 100644
index 0000000..6715c1b
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/MarkerExample.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.MarkerManager;
+
+public final class MarkerExample {
+
+ private static final Logger logger = LogManager.getLogger("example.MarkerExample");
+ // tag::create-marker[]
+ private static final Marker SQL_MARKER = MarkerManager.getMarker("SQL");
+ // end::create-marker[]
+ // tag::create-marker-parent[]
+ private static final Marker QUERY_MARKER =
+ MarkerManager.getMarker("SQL_QUERY").addParents(SQL_MARKER);
+ private static final Marker UPDATE_MARKER =
+ MarkerManager.getMarker("UPDATE").addParents(SQL_MARKER);
+ // end::create-marker-parent[]
+
+ public static void main(final String[] args) {
+ doQuery("my_table");
+ doQueryParent("my_table");
+ doUpdate("my_table", "column", "value");
+ }
+
+ public static void doQuery(String table) {
+ // Do business logic here
+ // tag::use-marker[]
+ logger.debug(SQL_MARKER, "SELECT * FROM {}", table);
+ // end::use-marker[]
+ }
+
+ public static void doQueryParent(String table) {
+ // Do business logic here
+ // tag::use-marker-parent[]
+ logger.debug(QUERY_MARKER, "SELECT * FROM {}", table);
+ // end::use-marker-parent[]
+ }
+
+ public static void doUpdate(String table, String column, String value) {
+ // Do business logic here
+ // tag::use-marker-parent[]
+ logger.debug(UPDATE_MARKER, "UPDATE {} SET {} = {}", table, column, value);
+ // end::use-marker-parent[]
+ }
+}
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.json b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.json
new file mode 100644
index 0000000..dd79820
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.json
@@ -0,0 +1,31 @@
+{
+ "Configuration": {
+ "Appenders": {
+ "Console": {
+ "name": "SQL_LOG",
+ "PatternLayout": {
+ "pattern": "%d %p %marker - %m%n"
+ }
+ }
+ },
+ "Loggers": {
+ "Root": {
+ "level": "INFO"
+ },
+ // tag::logger[]
+ "Logger": {
+ "name": "example",
+ "level": "ALL", // <1>
+ "AppenderRef": {
+ "ref": "SQL_LOG",
+ "MarkerFilter": { // <2>
+ "marker": "SQL",
+ "onMatch": "ACCEPT",
+ "onMismatch": "DENY"
+ }
+ }
+ }
+ // end::logger[]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.properties b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.properties
new file mode 100644
index 0000000..e6a8b58
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.properties
@@ -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.
+#
+appender.0.type = Console
+appender.0.name = SQL_LOG
+appender.0.layout.type = PatternLayout
+appender.0.layout.pattern = %d %p %marker - %m%n
+
+rootLogger.level = INFO
+
+# tag::logger[]
+logger.0.name = example
+logger.0.level = ALL # <1>
+logger.0.appenderRef.0.ref = SQL_LOG
+logger.0.appenderRef.0.filter.type = MarkerFilter # <2>
+logger.0.appenderRef.0.filter.marker = SQL
+logger.0.appenderRef.0.filter.onMatch = ACCEPT
+logger.0.appenderRef.0.filter.onMismatch = DENY
+# end::logger[]
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.xml b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.xml
new file mode 100644
index 0000000..7127c7c
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to you under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<Configuration xmlns="https://logging.apache.org/xml/ns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ https://logging.apache.org/xml/ns
+ https://logging.apache.org/xml/ns/log4j-config-2.xsd">
+ <Appenders>
+ <Console name="SQL_LOG">
+ <PatternLayout pattern="%d %p %-32marker - %m%n"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="INFO"/>
+ <!-- tag::logger[] -->
+ <Logger name="example" level="ALL"><!--1-->
+ <AppenderRef ref="SQL_LOG">
+ <MarkerFilter marker="SQL"
+ onMatch="ACCEPT"
+ onMismatch="DENY"/><!--2-->
+ </AppenderRef>
+ </Logger>
+ <!-- end::logger[] -->
+ </Loggers>
+</Configuration>
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.yaml b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.yaml
new file mode 100644
index 0000000..d742eaf
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/log4j2.yaml
@@ -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.
+#
+Configuration:
+ Appenders:
+ Console:
+ name: "SQL_LOG"
+ PatternLayout:
+ pattern: "%d %p %marker - %m%n"
+ Loggers:
+ Root:
+ level: "INFO"
+ # tag::logger[]
+ Logger:
+ name: "example"
+ level: "ALL" # <1>
+ AppenderRef:
+ ref: "SQL_LOG"
+ MarkerFilter: # <2>
+ marker: "SQL"
+ onMatch: "ACCEPT"
+ onMismatch: DENY
+ # end::logger[]
diff --git a/src/site/antora/modules/ROOT/examples/manual/markers/marker-filtering.log b/src/site/antora/modules/ROOT/examples/manual/markers/marker-filtering.log
new file mode 100644
index 0000000..cfbc745
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/markers/marker-filtering.log
@@ -0,0 +1,7 @@
+# tag::use-marker[]
+{docdate} 10:42:30,982 DEBUG [ SQL ] - SELECT * FROM my_table
+# end::use-marker[]
+# tag::use-marker-parent[]
+{docdate} 10:42:30,982 DEBUG [ SQL_QUERY[ SQL ] ] - SELECT * FROM my_table
+{docdate} 10:42:30,982 DEBUG [ SQL_UPDATE[ SQL ] ] - UPDATE my_table SET column = value
+# end::use-marker-parent[]
\ No newline at end of file
diff --git a/src/site/antora/modules/ROOT/pages/manual/markers.adoc b/src/site/antora/modules/ROOT/pages/manual/markers.adoc
index be12bda..29ca8f5 100644
--- a/src/site/antora/modules/ROOT/pages/manual/markers.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/markers.adoc
@@ -16,9 +16,9 @@
////
= Markers
-Markers allow "tag" log statements with a
+Markers allow to "tag" log statements with a
link:../javadoc/log4j-api/org/apache/logging/log4j/Marker.html[`Marker`]
-object, labeling them as belonging to a specific type.
+object, labeling them as belonging to a specific type.
For example, developers can use markers to tag log statements related to a particular subsystem or functionality.
By using markers, it is possible to filter log statements based on the `Marker`
@@ -30,106 +30,129 @@
[#create]
== Creating Markers
-To create a `Marker`, use the `MarkerManager` class as follows:
+[#simple-markers]
+=== Simple markers
-[source, java]
+To create a `Marker`, create a field in your class using the `MarkerManager.getMarker()` method:
+
+[source,java,indent=0]
----
-Marker SQL_MARKER = MarkerManager.getMarker("SQL");
+include::example$manual/markers/MarkerExample.java[tag=create-marker]
----
Since a `Marker` is reusable across multiple log statements, storing it in a `static final` field makes it a constant.
Once created, use it as the first argument in the log statement:
-[source, java]
+[source,java,indent=0]
----
-LOGGER.debug(SQL_MARKER, "Here is my SQL related message");
+include::example$manual/markers/MarkerExample.java[tag=use-marker]
----
-The example below creates the marker as the constant and then uses it to tag a log statement.
-The log method works _as usual_, but the marker needs to be the first argument.
+If you use the <<example-configuration,configuration example below>>, you'll see the following log statement on your console:
-[source, java]
+[subs=+attributes]
----
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.MarkerManager;
-
-public class MyApp {
-
- private static final Logger LOGGER = LogManager.getLogger();
-
- private static final Marker SQL_MARKER = MarkerManager.getMarker("MY_APP_SQL"); <1>
-
- public void doQuery(String table) {
- // Do business logic here
-
- LOGGER.debug(SQL_MARKER, "SELECT * FROM {}", table); <2>
- }
-}
+include::example$manual/markers/marker-filtering.log[tag=use-marker]
----
-<1> The marker is created and stored as a constant
-<2> Using the marker to tag a log statement
-
-You must create a configuration file to write log statements tagged with the "SQL" marker to the console.
-This file uses the `<MarkerFilter>` element to accept or deny log statements
-based on the marker.
-
-The following code shows how the `MarkerFilter` is used in the configuration file.
-It assumes that the `Console` appender is defined in the configuration file.
-
-Once a developer tags a log event with a marker, we can apply specialized configuration on that particular marker.
-For instance, we can use a xref:manual/filters.adoc#MarkerFilter[`MarkerFilter`] to redirect
-log events whose marker matches a particular name to a dedicated appender.
-In the example below, Log4j redirects all `MY_SQL_APP`-marked log messages from the `com.example` package to the `CONSOLE` appender:
-
-[source, xml]
-----
-<logger name="com.example" level="OFF"><!--1-->
- <AppenderRef ref="CONSOLE">
- <Filters>
- <MarkerFilter marker="MY_APP_SQL" onMatch="ACCEPT" onMismatch="DENY"/><!--2-->
- </Filters>
- </AppenderRef>
-</logger>
-----
-<1> Match all messages from `com.example` package from all levels
-<2> Only allow `MY_APP_SQL`-marked messages
[#hierarchy]
-== Parent and child markers
+=== Parent and child markers
A marker can have zero or more parent markers, allowing for a hierarchy of markers.
-To create such a hierarchy, you must use the `setParents` method on the `Marker` object
-after you create the child marker. This method will connect both markers.
+To create such a hierarchy, you must use the `addParents()` method on the `Marker` object after you create the child marker.
-[source, java]
+[source,java,indent=0]
----
-Marker SQL_MARKER = MarkerManager.getMarker("MY_APP_SQL"); // <1>
-Marker UPDATE_MARKER = MarkerManager.getMarker("MY_APP_SQL_UPDATE").setParents(SQL_MARKER); // <2>
-----
-<1> Creating the parent marker
-<2> Creating the child marker and connecting it to the parent marker
-
-The child marker works as expected by adding to the log method as the first argument.
-
-[source, java]
-----
-LOGGER.debug(UPDATE_MARKER, "UPDATE {} SET {}", table, values);
+include::example$manual/markers/MarkerExample.java[tag=create-marker-parent]
----
-It is now possible to filter for the parent or, more specifically, only for the child marker.
+The usage of child markers does not differ from the usage of simple markers, you just need to pass them as the first argument of a logging call.
+
+[source,java,indent=0]
+----
+include::example$manual/markers/MarkerExample.java[tag=use-marker-parent]
+----
+
+Messages marked with children markers behave as if they were both marked with the children marker and all its parents.
+If you use the <<example-configuration,configuration example below>>, you'll see the following log statement on your console:
+
+[subs=+attributes]
+----
+include::example$manual/markers/marker-filtering.log[tag=use-marker-parent]
+----
+
+[#configuring-log4j]
+== Configuring filtering
+
+Markers can be used to filter the log statements that are delivered to your log files.
+Marker processing is supported at least by
+https://logback.qos.ch/manual/filters.html#TurboFilter[Logback]
+and the Log4j Core logging backends.
+Will will discuss only the configuration of the latter.
+
+In order to filter messages by marker, you need to add
+xref:manual/filters.adoc#MarkerFilter[`MarkerFilter`]
+to your configuration file.
+For example the snippet below can be used to redirect all SQL-related logs to the `SQL_LOG` appender:
+
+[[example-configuration]]
+[tabs]
+====
+XML::
++
+[source,xml]
+----
+include::example$manual/markers/log4j2.xml[tag=logger]
+----
+
+JSON::
++
+[source,json]
+----
+include::example$manual/markers/log4j2.json[tag=logger]
+----
+
+YAML::
++
+[source,yaml]
+----
+include::example$manual/markers/log4j2.yaml[tag=logger]
+----
+
+Java properties::
++
+[source,properties]
+----
+include::example$manual/markers/log4j2.properties[tag=logger]
+----
+====
+
+<1> Match all messages from `example` package from all levels
+<2> Only allow messages marker with `SQL` or one of its children to be sent to the `SQL_LOG` appender.
[#pitfalls]
== Pitfalls
-It is important to note that marker names must be unique, as Log4j registers them permanently by name.
-Developers should avoid generic marker names, as they may conflict with
+It is important to note that marker names must be unique, as Log4j registers them permanently by name.
+Developers should avoid generic marker names, as they may conflict with
those provided by third parties. Except, of course, if the user is aware of the implications.
-While it is possible to add or remove parent markers dynamically through the `setParents()' method,
-it is generally advisable to set the parents when the marker is created.
+While it is possible to add or remove parent markers dynamically through the `setParents()' method,
+it is generally advisable to set the parents when the marker is created.
This is for efficiency and performance reasons.
-It is also worth noting that markers without parents are more efficient to evaluate
-than markers with multiple parents. It is generally a good idea to avoid
+It is also worth noting that markers without parents are more efficient to evaluate
+than markers with multiple parents. It is generally a good idea to avoid
complex hierarchies of markers where possible.
+
+[#complete-example]
+== Complete example
+
+To try the examples on this page:
+
+* add
+{antora-examples-url}/manual/markers/MarkerExample.java[MarkerExample.java]
+to the `src/main/java/example` folder of your project,
+* add
+{antora-examples-url}/manual/markers/log4j2.xml[log4j2.xml]
+to the `src/main/resources` folder of your project.