diff --git a/spring-geode-docs/spring-geode-docs.gradle b/spring-geode-docs/spring-geode-docs.gradle
index 8161ed67..b94f0299 100644
--- a/spring-geode-docs/spring-geode-docs.gradle
+++ b/spring-geode-docs/spring-geode-docs.gradle
@@ -46,7 +46,10 @@ asciidoctor {
'docs-src-dir' : rootProject.projectDir.path + '/spring-geode-docs/src/main/java',
'docs-resources-dir' : rootProject.projectDir.path + '/spring-geode-docs/src/main/resources',
'examples-dir' : rootProject.projectDir.path + '/spring-geode-examples',
- 'samples-dir' : rootProject.projectDir.path + '/spring-geode-samples'
+ 'samples-dir' : rootProject.projectDir.path + '/spring-geode-samples',
+ 'starter-logging-dir' : rootProject.projectDir.path + '/spring-geode-starter-logging',
+ 'starter-logging-src-dir' : rootProject.projectDir.path + '/spring-geode-starter-logging/src/main/src',
+ 'starter-logging-resources-dir' : rootProject.projectDir.path + '/spring-geode-starter-logging/src/main/resources'
}
javadoc {
diff --git a/spring-geode-docs/src/docs/asciidoc/index.adoc b/spring-geode-docs/src/docs/asciidoc/index.adoc
index eab7c4ed..8d794540 100644
--- a/spring-geode-docs/src/docs/asciidoc/index.adoc
+++ b/spring-geode-docs/src/docs/asciidoc/index.adoc
@@ -235,6 +235,7 @@ include::functions.adoc[]
include::continuous-query.adoc[]
include::data-serialization.adoc[]
include::security.adoc[]
+include::logging.adoc[]
include::actuator.adoc[]
include::session.adoc[]
include::cloudfoundry.adoc[]
diff --git a/spring-geode-docs/src/docs/asciidoc/logging.adoc b/spring-geode-docs/src/docs/asciidoc/logging.adoc
new file mode 100644
index 00000000..7c7bc5f5
--- /dev/null
+++ b/spring-geode-docs/src/docs/asciidoc/logging.adoc
@@ -0,0 +1,368 @@
+[[geode-logging]]
+== Logging
+
+Apache Geode `1.9.2` was modularized to separate its use of the Apache Log4j API to log output in Geode code from
+the underlying implementation of logging, which uses Apache Log4j as the logging provider by default.
+
+Prior to `1.9.2`, the Apache Log4j API (i.e. `log4j-api`) along with the Apache Log4j provider (i.e. `log4j-core`)
+were automatically pulled in by Apache Geode core (i.e. `org.apache.geode:geode-core`) thereby making it problematic
+to change logging providers when using Apache Geode in Spring Boot applications.
+
+However, now, in order to get any log output from Apache Geode whatsoever, Apache Geode requires a logging provider on
+your Spring Boot application classpath. Consequently, this also means the old Apache Geode `Properties`,
+e.g. `log-level` no longer have any effect, regardless of whether the property (e.g. `log-level`) is specified in
+`gemfire.properties`, in Spring Boot `application.properties` or even as a JVM System Property, `-Dgemfire.log-level`.
+
+TIP: Refer to Apache Geode's {apache-geode-docs}/reference/topics/gemfire_properties.html[Documentation]
+for a complete list of valid `Properties`, including the `Properties` used to configure logging.
+
+Unfortunately, this also means the _Spring Data for Apache Geode & Pivotal GemFire_ (SDG)
+{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLogging.html[`@EnableLogging`]
+annotation no longer has any effect on Apache Geode or Pivotal GemFire logging either and is the reason it has been
+https://jira.spring.io/browse/DATAGEODE-299[deprecated]. The reason `@EnableLogging` no longer has any effect on
+logging is because this annotation's attributes and associated SDG properties indirectly sets the corresponding
+Apache Geode or Pivotal GemFire properties, which again, are useless from Apache Geode `1.9.2` onward.
+
+By way of example, and to make this concrete, **none** of the following approaches have any effect on Apache Geode
+or Pivotal GemFire logging:
+
+.Command-line configuration
+[source,txt]
+----
+$ java -classpath ...:/path/to/MySpringBootApacheGeodeClientCacheApplication.jar -Dgemfire.log-level=DEBUG
+ example.app.MySpringBootApacheGeodeClientCacheApplication
+----
+
+.Externalized configuration using Apache Geode `gemfire.properties`
+[source,properties]
+----
+# Apache Geode/Pivotal GemFire only/specific properties
+log-level=INFO
+----
+
+.Externalized configuration using Spring Boot `application.properties`
+[source,properties]
+----
+spring.data.gemfire.cache.log-level=DEBUG
+----
+
+Or:
+
+[source,properties]
+----
+spring.data.gemfire.logging.level=DEBUG
+----
+
+.Java configuration using SDG's `@EnableLogging` annotation
+[source,java]
+----
+@SpringBootApplication
+@EnableLogging(logLevel = "DEBUG")
+class MySpringBootApacheGeodeClientApplication {
+ // ...
+}
+----
+
+That is to say, none of the approaches above have any effect without the **new** SBDG logging starter.
+
+[[geode-logging-configuration]]
+=== Configure Apache Geode & Pivotal GemFire Logging
+
+So, how do you configure logging for Apache Geode and Pivotal GemFire?
+
+Effectively, 3 things are required to get Apache Geode or Pivotal GemFire to log output:
+
+1) First, you must declare a logging provider on your Spring Boot application classpath (e.g. _Logback_).
+
+2) (optional) Next, you must declare an adapter, or bridge JAR, between Log4j and your logging provider if your declared
+logging provider is not Apache Log4j.
+
+For example, if you use the SLF4J API to log output from your Spring Boot application along with _Logback_ as your
+logging provider/implementation, then you must include the `org.apache.logging.log4j.log4j-to-slf4j` adapter/bridge JAR
+dependency as well.
+
+Internally, Apache Geode uses the Apache Log4j API to log output from Geode components. Therefore, you must bridge Log4j
+to any other logging provider (e.g. _Logback_) that is not Log4j (i.e. `log4j-core`). If you are using Log4j as your
+logging provider then you do not need to declare an adapter/bridge JAR on your Spring Boot application classpath.
+
+3) Finally, you must supply logging provider configuration to configure Loggers, Appenders, log levels, etc.
+
+For example, when using _Logback_, you must provide a `logback.xml` configuration file on your Spring Boot application
+classpath, or in the filesystem. Alternatively, you can use other means to configure your logging provider and get
+Apache Geode to log output.
+
+NOTE: Apache Geode's `geode-log4j` module covers the required configuration for steps 1-3 above and uses Apache Log4j
+(i.e. `org.apache.logging.log4j:log4j-core`) as the logging provider. The `geode-log4j` module even provides a default,
+`log4j2.xml` configuration file to configure Loggers, Appenders and log levels for Apache Geode.
+
+If you declare Spring Boot's own `org.springframework.boot:spring-boot-starter-logging` on your application classpath
+then this will cover Steps 1 and 2 above.
+
+The `spring-boot-starter-logging` dependency declares _Logback_ as the logging provider and automatically adapts,
+or bridges `java.util.logging` (JUL) and Apache Log4j to SLF4J. However, you still need to supply logging provider
+configuration, such as a `logback.xml` file for _Logback_, to configure logging not only for your Spring Boot
+application, but also for Apache Geode as well.
+
+SBDG has simplified the setup of Apache Geode and Pivotal GemFire logging. Simply declare the
+`org.springframework.geode:spring-geode-starter-logging` dependency on your Spring Boot application classpath!
+
+Unlike Apache Geode's default Log4j XML configuration file (i.e. `log4j2.xml`), SBDG's provided `logback.xml`
+configuration file is properly parameterized enabling you to adjust log levels as well as add Appenders.
+
+In addition, SBDG's provided _Logback_ configuration uses templates so you can compose your own logging configuration
+while still "including" snippets from SBDG's provided logging configuration metadata, such as Loggers and Appenders.
+
+[[geode-logging-configuration-log-levels]]
+==== Configuring Log Levels
+
+One of the most common logging tasks is to adjust the log-level of one or more Loggers, or the ROOT Logger. However,
+a user may only want to adjust the log-level for specific components of his/her Spring Boot application, such as for
+Apache Geode, by setting the log-level for only the Logger that logs Apache Geode events.
+
+SBDG's _Logback_ configuration defines 3 Loggers to control the log output from Apache Geode:
+
+.Apache Geode Loggers by name
+[source,xml]
+----
+
+
+
+----
+
+The `com.gemstone.gemfire` Logger is a legacy Logger covering old Pivotal GemFire bits still present in Apache Geode
+for backwards compatibility reasons. This Logger's use should be largely unnecessary.
+
+The `org.apache.geode` Logger is the primary Logger used to control log output from all Apache Geode components
+during the runtime operation of Apache Geode. Both this Logger and the legacy `com.gemstone.gemfire` Logger default
+log output to `INFO`.
+
+The `org.jgroups` Logger is used to log output from Apache Geode's message distribution and membership system.
+Apache Geode uses JGroups for membership and message distribution between peer members (nodes) in the cluster
+(distributed system). By default, JGroups log messages are logged at `ERROR`.
+
+The log-level for the `com.gemstone.gemfire` and `org.apache.geode` Loggers are configured with the
+`spring.boot.data.gemfire.log.level` property. The `org.jgroups` Logger is independently configured with the
+`spring.boot.data.gemfire.jgroups.log.level` property.
+
+The SBDG logging properties can be set on the command-line as JVM System Properties when running
+your Spring Boot application:
+
+.Setting the log-level from the command-line
+[source,text]
+----
+$ java -classpath ...:/path/to/MySpringBootApplication.jar -Dspring.boot.data.gemfire.log.level=DEBUG
+ package.to.MySpringBootApplicationClass
+----
+
+NOTE: Setting JVM System Properties using `$ java -jar MySpringBootApplication.jar -Dspring.boot.data.gemfire.log.level=DEBUG`
+is not supported by the Java Runtime Environment (JRE).
+
+Alternatively, you can configure and control Apache Geode logging in Spring Boot `application.properties`:
+
+.Setting the log-level in `application.properties`
+[source,properties]
+----
+spring.boot.data.gemfire.log.level=DEBUG
+----
+
+For backwards compatibility, SBDG additionally supports the old _Spring Data for Apache Geode_ (SDG) logging properties
+as well, using either:
+
+`spring.data.gemfire.cache.log-level=DEBUG`
+
+Or:
+
+`spring.data.gemfire.logging.level=DEBUG`
+
+If you previously used either of these SDG based logging properties, they will continue to work as designed in
+SBDG `1.3` or later.
+
+[[geode-logging-configuration-composition]]
+==== Composing Logging Configuration
+
+As mentioned earlier, SBDG allows you to compose your own logging configuration from SBDG's default, provided _Logback_
+configuration metadata.
+
+SBDG conveniently bundles the Loggers and Appenders from SBDG's logging starter into a template file that you can
+include into your own, custom _Logback_ XML configuration file.
+
+The _Logback_ template file appears as follows:
+
+.logback-include.xml
+[source,xml]
+----
+include::{starter-logging-resources-dir}/logback-include.xml[]
+----
+
+Then, this Logback configuration snippet can be included in an application-specific, _Logback_ XML configuration file
+as follows:
+
+.logback.xml
+[source,xml]
+----
+include::{starter-logging-resources-dir}/logback.xml[]
+----
+
+
+[[geode-logging-slf4j-logback-api-support]]
+=== SLF4J & Logback API Support
+
+SBDG provides additional support when working with the SLF4J and _Logback_ APIs. This support is available when you
+declare the `org.springframework.geode:spring-geode-starter-logging` dependency on your Spring Boot application
+classpath.
+
+One of the main supporting classes from the `spring-geode-starter-logger`
+is the `org.springframework.geode.logging.slf4j.logback.LogbackSupport` class. This class provides methods to:
+
+* Resolve a reference to the _Logback_ `LoggingContext`
+* Resolve the SLF4J ROOT `Logger` as a _Logback_ `Logger`
+* Lookup `Appenders` by name and required type
+* Add/Remove `Appenders` to `Loggers`
+* And even reset the state of the _Logback_ logging system, which can prove to be most useful during testing
+
+`LogbackSupport` can even suppress the auto-configuration of _Logback_ performed by Spring Boot on startup,
+another useful utility during automated testing.
+
+In addition to the `LogbackSupport` class, SBDG also provides some custom _Logback_ `Appenders`.
+
+[[geode-logging-slf4j-logback-api-support-appender-composite]]
+==== CompositeAppender
+
+The `org.springframework.geode.logging.slf4j.logback.CompositeAppender` class is an implementation of _Logback_
+`Appender` and the https://en.wikipedia.org/wiki/Composite_pattern[Composite Software Design Pattern].
+
+`CompositeAppender` enables developers to compose multiple `Appenders` and use them as if they were a single `Appender`.
+
+For example, you could compose both the _Logback_ `ConsoleAppender` and `FileAppender` into one using:
+
+.Composing multiple `Appenders`
+[source,java]
+----
+ConsoleAppender consoleAppender = ...;
+
+FileAppender fileAppender = ...;
+
+Appender compositeAppender = CompositeAppender.compose(consoleAppender, fileAppender);
+
+// do something with the compositeAppender
+----
+
+You could then add the `CompositeAppender` to a "named" `Logger` by doing:
+
+.Register `CompositeAppender` on "named" `Logger`
+[source,java]
+----
+Logger namedLogger = LoggerFactory.getLogger("loggerName");
+
+LogbackSupport.toLogbackLogger(namedLogger)
+ .ifPresent(it -> LogbackSupport.addAppender(it, compositeAppender));
+----
+
+In this case, the "named" `Logger` will log events (or log messages) to both the _Console_ and _File_ `Appenders`.
+
+It is simple to compose an array or `Iterable` of `Appenders` by using either the
+`CompositeAppender.compose(:Appender[])` method or the `CompositeAppender.compose(:Iterable>)` method.
+
+[[geode-logging-slf4j-logback-api-support-appender-delegate]]
+==== DelegatingAppender
+
+The `org.springframework.geode.logging.slf4j.logback.DelegatingAppender` is a pass-through _Logback_ `Appender`
+implementation wrapping another _Logback_ `Appender`, or collection of `Appenders` doing actual work, like the
+`ConsoleAppender`, a `FileAppender` or a `SocketAppender`, etc. By default, the `DelegatingAppender` delegates
+to the `NOPAppender` thereby doing no actual work.
+
+By default, SBDG registers the `org.springframework.geode.logging.slfj4.logback.DelegatingAppender` with
+the ROOT `Logger`, which can be useful for testing purposes.
+
+With a reference to a `DelegatingAppender`, you can add any `Appender` as the delegate, even a `CompositeAppender`:
+
+.Add `ConsoleAppender` as the "delegate" for the `DelegatingAppender`
+[source,java]
+----
+ConsoleAppender consoleAppender = new ConsoleAppender();
+
+LogbackSupport.resolveLoggerContext().ifPresent(consoleAppender::setContext);
+
+consoleAppender.setImmediateFlush(true);
+consoleAppender.start();
+
+LogbackSupport.resolveRootLogger()
+ .flatMap(LogbackSupport::toLogbackLogger)
+ .flatMap(rootLogger -> LogbackSupport.resolveAppender(rootLogger,
+ LogbackSupport.DELEGATE_APPENDER_NAME, DelegatingAppender.class))
+ .ifPresent(delegateAppender -> delegateAppender.setAppender(consoleAppender));
+----
+
+[[geode-logging-slf4j-logback-api-support-appender-string]]
+==== StringAppender
+
+The `org.springframework.geode.logging.slf4j.logback.StringAppender` stores log message in-memory, appended to
+a `String`.
+
+The `StringAppender` is very useful for testing purposes. For instance, you can use the `StringAppender` to assert that
+a `Logger` used by certain application components logged messages at the appropriately configured log level while other
+log messages were not logged.
+
+For example:
+
+.`StringAppender` in Action
+[source,java]
+----
+class ApplicationComponent {
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ public void someMethod() {
+ logger.debug("Some debug message");
+ // ...
+ }
+
+ public void someOtherMethod() {
+ logger.info("Some info message");
+ }
+}
+
+// Assuming the ApplicationComponent Logger was configured with log-level 'INFO', then...
+class ApplicationComponentUnitTests {
+
+ private final ApplicationComponent applicationComponent = new ApplicationComponent();
+
+ private final Logger logger = LoggerFactory.getLogger(ApplicationComponent.class);
+
+ private StringAppender stringAppender;
+
+ @Before
+ public void setup() {
+
+ LogbackSupport.toLogbackLogger(logger)
+ .map(Logger::getLevel)
+ .ifPresent(level -> assertThat(level).isEqualTo(Level.INFO));
+
+ stringAppender = new StringAppender.Builder()
+ .applyTo(logger)
+ .build();
+ }
+
+ @Test
+ public void someMethodDoesNotLogDebugMessage() {
+
+ applicationComponent.someMethod();
+
+ assertThat(stringAppender.getLogOutput).doesNotContain("Some debug message");
+ }
+
+ @Test
+ public void someOtherMethodLogsInfoMessage() {
+
+ applicationComponent.someOtherMethod();
+
+ assertThat(stringAppender.getLogOutput()).contains("Some info message");
+ }
+}
+----
+
+There are many other uses for the `StringAppender` and it can be used safely in a multi-Threaded context by calling
+`StringAppender.Builder.useSynchronization()`.
+
+When combined with other SBDG provided `Appenders` in conjunction with the `LogbackSupport` class, you have a lot of
+power both in application code as well as your tests.