diff --git a/documentation/jetty-documentation/pom.xml b/documentation/jetty-documentation/pom.xml
index 881dbcdd16b..517a3244587 100644
--- a/documentation/jetty-documentation/pom.xml
+++ b/documentation/jetty-documentation/pom.xml
@@ -168,7 +168,6 @@
org.eclipse.jetty
jetty-servlets
- ${project.version}
org.eclipse.jetty
diff --git a/documentation/jetty-documentation/src/main/asciidoc/old_docs/logging/chapter.adoc b/documentation/jetty-documentation/src/main/asciidoc/old_docs/logging/chapter.adoc
index 7e0e2f58c5c..d37895e8f8e 100644
--- a/documentation/jetty-documentation/src/main/asciidoc/old_docs/logging/chapter.adoc
+++ b/documentation/jetty-documentation/src/main/asciidoc/old_docs/logging/chapter.adoc
@@ -18,6 +18,5 @@ This chapter discusses various options for configuring logging.
include::configuring-jetty-logging.adoc[]
include::default-logging-with-stderrlog.adoc[]
-include::configuring-jetty-request-logs.adoc[]
include::configuring-logging-modules.adoc[]
include::example-logback-centralized-logging.adoc[]
diff --git a/documentation/jetty-documentation/src/main/asciidoc/old_docs/logging/configuring-jetty-request-logs.adoc b/documentation/jetty-documentation/src/main/asciidoc/old_docs/logging/configuring-jetty-request-logs.adoc
deleted file mode 100644
index 7227f4970c9..00000000000
--- a/documentation/jetty-documentation/src/main/asciidoc/old_docs/logging/configuring-jetty-request-logs.adoc
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
-//
-// This program and the accompanying materials are made available under the
-// terms of the Eclipse Public License v. 2.0 which is available at
-// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
-// which is available at https://www.apache.org/licenses/LICENSE-2.0.
-//
-// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-// ========================================================================
-//
-
-[[configuring-jetty-request-logs]]
-=== Configuring Jetty Request Logs
-
-Request logs are a record of the requests that the server has processed.
-There is one entry per request received, and commonly in the standard NCSA format, so you can use tools like http://en.wikipedia.org/wiki/Webalizer[Webalizer] to analyze them conveniently.
-
-[[constructing-request-log-entry]]
-==== Constructing a Request Log Entry
-
-A standard request log entry includes the client IP address, date, method, URL, result, size, referrer, user agent and latency.
-For example:
-
-....
-123.4.5.6 - - [20/Jul/2016:10:16:17 +0000]
- "GET /jetty/tut/XmlConfiguration.html HTTP/1.1"
- 200 76793 "http://localhost:8080/jetty/tut/logging.html"
- "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040614 Firefox/0.8" 342
-....
-
-[[implementing-request-log]]
-==== Implementing a Request Log
-
-Jetty provides an implementation called `NCSARequestLog` which supports the NCSA format in files that will roll over on a daily basis.
-
-The http://logback.qos.ch/[Logback Project] offers http://logback.qos.ch/access.html[another implementation] of a `RequestLog` interface, providing rich and powerful HTTP-access log functionality.
-
-If neither of these options meets your needs, you can implement a custom request logger by implementing Jetty's link:{JDURL}/org/eclipse/jetty/server/RequestLog.html[`RequestLog.java`] interface and plugging it in similar to the `NCSARequestLog`, as shown below.
-
-[[configuring-request-log]]
-==== Configuring the Request Log module
-
-To enable the Request Log module for the entire server via the Jetty distribution, it first needs to be enabled on the command line:
-
-[source,screen,subs="{sub-order}"]
-----
-[my-base]$ java -jar /path/to/jetty-home/start.jar --add-to-start=requestlog
-
-INFO: requestlog initialised in ${jetty.base}/start.d/requestlog.ini
-MKDIR: ${jetty.base}/logs
-INFO: Base directory was modified
-----
-
-The above command will add a new `requestlog.ini` file to your link:#start-vs-startd[`{$jetty.base}/start.d` directory].
-
-____
-[NOTE]
-By default, request logs are not set to be appended, meaning a the log file is wiped clean upon sever restart.
-You can change this setting by editing the `requestlog.ini` and un-commenting the line that reads `jetty.requestlog.append=true`.
-____
-
-The equivalent code for embedded usages of Jetty is:
-
-[source, java, subs="{sub-order}"]
-----
-NCSARequestLog requestLog = new NCSARequestLog("/var/logs/jetty/jetty-yyyy_mm_dd.request.log");
-requestLog.setAppend(true);
-requestLog.setExtended(false);
-requestLog.setLogTimeZone("GMT");
-requestLog.setLogLatency(true);
-requestLog.setRetainDays("90");
-
-server.setRequestLog(requestLog);
-----
-
-This configures a request log in `{$jetty.home}/logs` with filenames including the date.
-Existing log files are appended to and the extended NCSA format is used in the GMT time zone.
-
-The above configuration enables Log Latency, which is the amount of time it took the server to handle the request.
-This value is measured in milliseconds and is appended to the the log file for each request.
-
-You can also customize the number of days you wish to keep request logs.
-By default, log files are kept for 90 days before being deleted.
-The value for `retainDays` (xml) or `setRetainDays` (Java) should be configured as _1 + n_ days.
-For example, if you wanted to keep the logs for the current day and the day prior you would set the `retainDays` (or `setRetainDays`) value to 2.
-
-
-[[request-log-custom-writer]]
-==== Introducing RequestLog.Writer
-
-The concept of a `RequestLog.Writer`, introduced in Jetty 9.4.15, manages the writing to a log the string generated by the `RequestLog`.
-This allows the `CustomRequestLog` to match the functionality of other `RequestLogger` implementations by plugging in any `RequestLog.Writer` and a custom format string.
-Jetty currently has implementations of `RequestLog.Writer`, `RequestLogWriter`, `AsyncRequestLogWriter`, and `Slf4jRequestLogWriter`.
-
-So, the way to create an asynchronous `RequestLog` using the extended NCSA format has been changed from:
-
-`new AsyncNcsaRequestLog(filename)`
-
-to:
-
-`new CustomRequestLog(new AsyncRequestLogWriter(filename), CustomRequestLog.EXTENDED_NCSA_FORMAT)`
-
-Additionally, there are now two settings for the log timezone to be configured.
-There is the configuration for logging the request time, which is set in the `timeZone` parameter in the `%t` format code of the string, given in the format `%{format|timeZone|locale}t`.
-
-The other `timeZone` parameter relates to the generation of the log file name (both at creation and roll over).
-This is configured in the `requestlog` module file, or can be used as a setter on `RequestLogWriter` via XML.
-
-Both timezones are set to GMT by default.
-
-[[configuring-separate-request-log-for-web-application]]
-==== Configuring a Separate Request Log For a Web Application
-
-To configure a separate request log for specific a web application, add the following to the context XML file.
-
-[source, xml, subs="{sub-order}"]
-----
-
- ...
-
-
-
-
-
- /test-yyyy_mm_dd.request.log
- yyyy_MM_dd
- GMT
- 90
- true
- true
-
-
-
-
-
- ...
-
-----
diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/http/server-http-handler.adoc b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/http/server-http-handler.adoc
index f001341d575..77acd975706 100644
--- a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/http/server-http-handler.adoc
+++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/http/server-http-handler.adoc
@@ -24,7 +24,7 @@ An `org.eclipse.jetty.server.Handler` is the component that processes incoming H
* nested, where one `Handler` invokes the next, nested, `Handler`
** `HandlerWrapper` implements this behavior
-The `HandlerCollection` behavior (invoking _all_ handlers) is useful when for example the last `Handler` is a logging `Handler` that logs the request(that may have been modified by previous handlers).
+The `HandlerCollection` behavior (invoking _all_ handlers) is useful when for example the last `Handler` is a logging `Handler` that logs the request (that may have been modified by previous handlers).
The `HandlerList` behavior (invoking handlers up to the first that calls `Request.setHandled(true)`) is useful when each handler processes a different URIs or a different virtual hosts: ``Handler``s are invoked one after the other until one matches the URI or virtual host.
diff --git a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/http/server-http.adoc b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/http/server-http.adoc
index 310566bbc56..e6f293ebc2c 100644
--- a/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/http/server-http.adoc
+++ b/documentation/jetty-documentation/src/main/asciidoc/programming-guide/server/http/server-http.adoc
@@ -71,7 +71,7 @@ Read xref:pg-server-http-handler[this section] for further details about ``Handl
If you are interested in writing your server application based on the Servlet APIs, jump to xref:pg-server-http-handler-use-servlet[this section].
[[pg-server-http-request-processing]]
-==== Server Request Processing
+==== Request Processing
The Jetty HTTP request processing is outlined below in the diagram below.
You may want to refer to the xref:pg-arch-io[Jetty I/O architecture] for additional information about the classes mentioned below.
@@ -153,6 +153,49 @@ Server applications can register `HttpChannel.Listener` by adding them as xref:p
include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[tags=httpChannelListener]
----
+[[pg-server-http-request-logging]]
+==== Request Logging
+
+HTTP requests and responses can be logged to provide data that can be later analyzed with other tools.
+These tools can provide information such as the most frequently accessed request URIs, the response status codes, the request/response content lengths, geographical information about the clients, etc.
+
+The default request/response log line format is the link:https://en.wikipedia.org/wiki/Common_Log_Format[NCSA Format] extended with referrer data and user-agent data.
+
+[NOTE]
+====
+Typically, the extended NCSA format is the is enough and it's the standard used and understood by most log parsing tools and monitoring tools.
+
+To customize the request/response log line format see the link:{javadoc-url}/org/eclipse/jetty/server/CustomRequestLog.html[`CustomRequestLog` javadocs].
+====
+
+Request logging can be enabled at the server level, or at the web application context level.
+
+The request logging output can be directed to an SLF4J logger named `"org.eclipse.jetty.server.RequestLog"` at `INFO` level, and therefore to any logging library implementation of your choice (see also xref:pg-troubleshooting-logging[this section] about logging).
+
+[source,java,indent=0]
+----
+include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[tags=serverRequestLogSLF4J]
+----
+
+Alternatively, the request logging output can be directed to a daily rolling file of your choice, and the file name must contain `yyyy_MM_dd` so that rolled over files retain their date:
+
+[source,java,indent=0]
+----
+include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[tags=serverRequestLogFile]
+----
+
+For maximum flexibility, you can log to multiple ``RequestLog``s using class `RequestLog.Collection`, for example by logging with different formats or to different outputs.
+
+You can use `CustomRequestLog` with a custom `RequestLog.Writer` to direct the request logging output to your custom targets (for example, an RDBMS).
+You can implement your own `RequestLog` if you want to have functionalities that are not implemented by `CustomRequestLog`.
+
+Request logging can also be enabled at the web application context level, using `RequestLogHandler` (see xref:pg-server-http-handler[this section] about how to organize Jetty ``Handler``s) to wrap a web application `Handler`:
+
+[source,java,indent=0]
+----
+include::../../{doc_code}/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java[tags=contextRequestLog]
+----
+
include::server-http-connector.adoc[]
include::server-http-handler.adoc[]
include::server-http-security.adoc[]
diff --git a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java
index 4f56d21c2a5..6a59797ffc1 100644
--- a/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java
+++ b/documentation/jetty-documentation/src/main/java/org/eclipse/jetty/docs/programming/server/http/HTTPServerDocs.java
@@ -16,6 +16,7 @@ package org.eclipse.jetty.docs.programming.server.http;
import java.io.IOException;
import java.nio.file.Path;
import java.util.EnumSet;
+import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.DispatcherType;
@@ -40,14 +41,17 @@ import org.eclipse.jetty.rewrite.handler.RedirectRegexRule;
import org.eclipse.jetty.rewrite.handler.RewriteHandler;
import org.eclipse.jetty.rewrite.handler.RewriteRegexRule;
import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.CustomRequestLog;
import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.ProxyConnectionFactory;
import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.RequestLogWriter;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.Slf4jRequestLogWriter;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
@@ -56,6 +60,7 @@ import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.HandlerWrapper;
+import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.server.handler.SecuredRedirectHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
@@ -155,6 +160,57 @@ public class HTTPServerDocs
// end::httpChannelListener[]
}
+ public void serverRequestLogSLF4J()
+ {
+ // tag::serverRequestLogSLF4J[]
+ Server server = new Server();
+
+ // Sets the RequestLog to log to an SLF4J logger named "org.eclipse.jetty.server.RequestLog" at INFO level.
+ server.setRequestLog(new CustomRequestLog(new Slf4jRequestLogWriter(), CustomRequestLog.EXTENDED_NCSA_FORMAT));
+ // end::serverRequestLogSLF4J[]
+ }
+
+ public void serverRequestLogFile()
+ {
+ // tag::serverRequestLogFile[]
+ Server server = new Server();
+
+ // Use a file name with the pattern 'yyyy_MM_dd' so rolled over files retain their date.
+ RequestLogWriter logWriter = new RequestLogWriter("/var/log/yyyy_MM_dd.jetty.request.log");
+ // Retain rolled over files for 2 weeks.
+ logWriter.setRetainDays(14);
+ // Log times are in the current time zone.
+ logWriter.setTimeZone(TimeZone.getDefault().getID());
+
+ // Set the RequestLog to log to the given file, rolling over at midnight.
+ server.setRequestLog(new CustomRequestLog(logWriter, CustomRequestLog.EXTENDED_NCSA_FORMAT));
+ // end::serverRequestLogFile[]
+ }
+
+ public void contextRequestLog()
+ {
+ // tag::contextRequestLog[]
+ Server server = new Server();
+
+ // Create a first ServletContextHandler for your main application.
+ ServletContextHandler mainContext = new ServletContextHandler();
+ mainContext.setContextPath("/main");
+
+ // Create a RequestLogHandler to log requests for your main application.
+ RequestLogHandler requestLogHandler = new RequestLogHandler();
+ requestLogHandler.setRequestLog(new CustomRequestLog());
+ // Wrap the main application with the request log handler.
+ requestLogHandler.setHandler(mainContext);
+
+ // Create a second ServletContextHandler for your other application.
+ // No request logging for this application.
+ ServletContextHandler otherContext = new ServletContextHandler();
+ mainContext.setContextPath("/other");
+
+ server.setHandler(new HandlerList(requestLogHandler, otherContext));
+ // end::contextRequestLog[]
+ }
+
public void configureConnector() throws Exception
{
// tag::configureConnector[]