| <?xml version="1.0"?> | 
 | <!-- | 
 |  | 
 |     Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. | 
 |  | 
 |     This program and the accompanying materials are made available under the | 
 |     terms of the Eclipse Public License v. 2.0, which is available at | 
 |     http://www.eclipse.org/legal/epl-2.0. | 
 |  | 
 |     This Source Code may also be made available under the following Secondary | 
 |     Licenses when the conditions for such availability set forth in the | 
 |     Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | 
 |     version 2 with the GNU Classpath Exception, which is available at | 
 |     https://www.gnu.org/software/classpath/license.html. | 
 |  | 
 |     SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | 
 |  | 
 | --> | 
 |  | 
 | <!DOCTYPE chapter [<!ENTITY % ents SYSTEM "jersey.ent" > %ents;]> | 
 | <chapter xmlns="http://docbook.org/ns/docbook" | 
 |          version="5.0" | 
 |          xml:lang="en" | 
 |          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | 
 |          xmlns:xi="http://www.w3.org/2001/XInclude" | 
 |          xmlns:xlink="http://www.w3.org/1999/xlink" | 
 |          xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd | 
 |                              http://www.w3.org/1999/xlink http://www.w3.org/1999/xlink.xsd" | 
 |          xml:id="monitoring_tracing"> | 
 |     <title>Monitoring and Diagnostics</title> | 
 |     <section xml:id="monitoring"> | 
 |         <title>Monitoring Jersey Applications</title> | 
 |         <section> | 
 |             <title>Introduction</title> | 
 |             <important> | 
 |                 <para> | 
 |                     Jersey monitoring support has been released as a <emphasis>beta release</emphasis> in Jersey 2.1 version. | 
 |                     As such, the exposed monitoring public APIs and functionality described in this section may change in the | 
 |                     future Jersey releases. | 
 |                 </para> | 
 |             </important> | 
 |             <para> | 
 |                 Jersey provides functionality for monitoring JAX-RS/Jersey applications. Application monitoring is useful | 
 |                 when you need to identify the performance hot-spots in your JAX-RS application, observe | 
 |                 execution statistics of particular resources or listen to application | 
 |                 or request lifecycle events. Note that this functionality is Jersey-specific extension to JAX-RS API. | 
 |             </para> | 
 |             <para> | 
 |                 Jersey monitoring support is divided into three functional areas: | 
 |  | 
 |                 <variablelist> | 
 |                     <varlistentry> | 
 |                         <term>Event Listeners</term> | 
 |                         <listitem> | 
 |                             <para> | 
 |                                 Event listeners allow users to receive and process a predefined set of events that occur during | 
 |                                 an application lifecycle (such as application initialization, application destroy) as well as | 
 |                                 request processing lifecycle events (request started, resource method finished, exception thrown, | 
 |                                 etc.). This feature is always enabled in Jersey server runtime and is leveraged by the other | 
 |                                 monitoring features. | 
 |                             </para> | 
 |                         </listitem> | 
 |                     </varlistentry> | 
 |                     <varlistentry> | 
 |                         <term>Monitoring Statistics</term> | 
 |                         <listitem> | 
 |                             <para> | 
 |                                 Jersey can be configured to process lifecycle events in order to expose a wide range of | 
 |                                 runtime monitoring statistics to the end user. The statistics are accessible trough an injectable | 
 |                                 &jersey.server.monitoring.MonitoringStatistics; interface. The statistics provide general information | 
 |                                 about the application as well as fine-grained execution statistics on particular resources and sub | 
 |                                 resources and exposed URIs. For performance reasons, this functionality must be explicitly enabled | 
 |                                 prior using. | 
 |                             </para> | 
 |                         </listitem> | 
 |                     </varlistentry> | 
 |                     <varlistentry> | 
 |                         <term>JMX MBeans with statistics</term> | 
 |                         <listitem> | 
 |                             <para> | 
 |                                 In addition to the injectable &lit.jersey.server.monitoring.MonitoringStatistics; data, Jersey | 
 |                                 is able to expose the statistics as JMX MBeans (for example | 
 |                                 &jersey.server.monitoring.ApplicationMXBean;). | 
 |                                 Jersey monitoring MXBeans can be accessed programmatically using JMX APIs or browsed via JMX-enabled | 
 |                                 tool (<literal>JConsole</literal> for example). This functionality is also disabled by default for | 
 |                                 performance reasons and must be enabled if needed. | 
 |                             </para> | 
 |                         </listitem> | 
 |                     </varlistentry> | 
 |                 </variablelist> | 
 |  | 
 |                 All monitoring related APIs (beta!) can be found in the <literal>jersey-server</literal> module in | 
 |                 <literal>org.glassfish.jersey.server.monitoring</literal> package. Monitoring in Jersey is currently supported on | 
 |                 the server side. | 
 |             </para> | 
 |         </section> | 
 |         <section> | 
 |             <title>Event Listeners</title> | 
 |             <para> | 
 |                 Jersey defines two types of event listeners that you can implement and register with your application: | 
 |  | 
 |                 <itemizedlist> | 
 |                     <listitem> | 
 |                         <para>&jersey.server.monitoring.ApplicationEventListener; for listening to application events, and</para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para>&jersey.server.monitoring.RequestEventListener; for listening to events of request processing.</para> | 
 |                     </listitem> | 
 |                 </itemizedlist> | 
 |  | 
 |                 Only the first type, &lit.jersey.server.monitoring.ApplicationEventListener; | 
 |                 can be directly registered as an application-wide provider. The &lit.jersey.server.monitoring.RequestEventListener; | 
 |                 is designed to be specific to every request and can be only returned from the | 
 |                 &lit.jersey.server.monitoring.ApplicationEventListener; as such. | 
 |             </para> | 
 |             <para> | 
 |                 Let's start with an example. The following examples show simple implementations of Jersey event listeners as well | 
 |                 as a test JAX-RS resource that will be monitored. | 
 |  | 
 |                 <example> | 
 |                     <title>Application event listener</title> | 
 |                     <programlisting language="java" linenumbering="numbered"><![CDATA[public class MyApplicationEventListener | 
 |             implements ApplicationEventListener { | 
 |     private volatile int requestCnt = 0; | 
 |  | 
 |     @Override | 
 |     public void onEvent(ApplicationEvent event) { | 
 |         switch (event.getType()) { | 
 |             case INITIALIZATION_FINISHED: | 
 |                 System.out.println("Application " | 
 |                         + event.getResourceConfig().getApplicationName() | 
 |                         + " was initialized."); | 
 |                 break; | 
 |             case DESTROY_FINISHED: | 
 |                 System.out.println("Application " | 
 |                     + event.getResourceConfig().getApplicationName() destroyed."); | 
 |                 break; | 
 |         } | 
 |     } | 
 |  | 
 |     @Override | 
 |     public RequestEventListener onRequest(RequestEvent requestEvent) { | 
 |         requestCnt++; | 
 |         System.out.println("Request " + requestCnt + " started."); | 
 |         // return the listener instance that will handle this request. | 
 |         return new MyRequestEventListener(requestCnt); | 
 |     } | 
 | }]]></programlisting> | 
 |                 </example> | 
 |  | 
 |                 <example> | 
 |                     <title>Request event listener</title> | 
 |                     <programlisting language="java" linenumbering="numbered"><![CDATA[public class MyRequestEventListener implements RequestEventListener { | 
 |     private final int requestNumber; | 
 |     private final long startTime; | 
 |  | 
 |     public MyRequestEventListener(int requestNumber) { | 
 |         this.requestNumber = requestNumber; | 
 |         startTime = System.currentTimeMillis(); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public void onEvent(RequestEvent event) { | 
 |         switch (event.getType()) { | 
 |             case RESOURCE_METHOD_START: | 
 |                 System.out.println("Resource method " | 
 |                     + event.getUriInfo().getMatchedResourceMethod() | 
 |                         .getHttpMethod() | 
 |                     + " started for request " + requestNumber); | 
 |                 break; | 
 |             case FINISHED: | 
 |                 System.out.println("Request " + requestNumber | 
 |                     + " finished. Processing time " | 
 |                     + (System.currentTimeMillis() - startTime) + " ms."); | 
 |                 break; | 
 |         } | 
 |     } | 
 | }]]></programlisting> | 
 |                 </example> | 
 |  | 
 |                 <example> | 
 |                     <title>Event listener test resource</title> | 
 |                     <programlisting language="java" linenumbering="numbered"><![CDATA[@Path("resource") | 
 | public class TestResource { | 
 |     @GET | 
 |     public String getSomething() { | 
 |         return "get"; | 
 |     } | 
 |  | 
 |     @POST | 
 |     public String postSomething(String entity) { | 
 |         return "post"; | 
 |     } | 
 | }]]></programlisting> | 
 |                 </example> | 
 |             </para> | 
 |  | 
 |             <para> | 
 |                 Once the listeners and the monitored resource are defined, it's time to initialize our application. The following | 
 |                 piece of code shows a &jersey.server.ResourceConfig; that is used to initialize the application (please | 
 |                 note that only &lit.jersey.server.monitoring.ApplicationEventListener; is registered as provider). | 
 |  | 
 |                 <programlisting language="java" linenumbering="numbered"><![CDATA[ResourceConfig resourceConfig = | 
 |             new ResourceConfig(TestResource.class, MyApplicationEventListener.class) | 
 |             .setApplicationName("my-monitored-application");]]></programlisting> | 
 |  | 
 |                 Our example application now contains a simple resource <literal>TestResource</literal> that defines resource methods | 
 |                 for &lit.http.GET; and &lit.http.POST; and a custom <literal>MyApplicationEventListener</literal> event listener. | 
 |             </para> | 
 |             <para> | 
 |                 The registered <literal>MyApplicationEventListener</literal> implements two methods defined by the | 
 |                 &lit.jersey.server.monitoring.ApplicationEventListener; interface. A method <literal>onEvent()</literal> handles | 
 |                 all application lifecycle events. In our case the method handles only 2 application events - initialization | 
 |                 and destroy. Other event types are ignored. All application event types are defined | 
 |                 in &jersey.server.monitoring.ApplicationEvent;<literal>.Type</literal>. The second method <literal>onRequest</literal> | 
 |                 is invoked by Jersey runtime every time a new request is received. The request event type passed to the method | 
 |                 is always <literal>START</literal>. If you want to listen to any other request lifecycle events for the new request, | 
 |                 you are expected to return an instance of &lit.jersey.server.monitoring.RequestEventListener; that will handle the | 
 |                 request. It is important to understand, that the instance will handle only the request for which it has been returned | 
 |                 from an <literal>ApplicationEventListener.onRequest</literal> method and not any other requests. In our case the | 
 |                 returned request event listener keeps information about the request number of the current request and a start time of | 
 |                 the request which is later used to print out the request processing times statistics. This demonstrates the principle | 
 |                 of listening to request events: for one request there is one instance which can be used to hold all the information | 
 |                 about the particular request. In other words, &lit.jersey.server.monitoring.RequestEventListener; is designed to be | 
 |                 implicitly request-scoped. | 
 |             </para> | 
 |             <para> | 
 |                 Jersey represents lifecycle events via &jersey.server.monitoring.RequestEvent; and | 
 |                 &jersey.server.monitoring.ApplicationEvent; types. Instances of these classes contain information | 
 |                 about respective events. The most important information is the event type <literal>Type</literal> retrievable via | 
 |                 <literal>getType()</literal> method, | 
 |                 which identifies the type of the event. Events contain also additional information that is dependent on a particular | 
 |                 event type. This information can be retrieved via event getters. Again, some getters return valid information for all | 
 |                 event types, some are specific to a sub-set of event types. For example, in the | 
 |                 &lit.jersey.server.monitoring.RequestEvent;, the <literal>getExceptionCause()</literal> method returns valid | 
 |                 information only when event type is <literal>ON_EXCEPTION</literal>. On the other hand, | 
 |                 a <literal>getContainerRequest()</literal> can be used to return current request context for any request event type. | 
 |                 See javadoc of events and event types to get familiar with event types and information valid for each event type. | 
 |             </para> | 
 |             <para> | 
 |                 Our <literal>MyRequestEventListener</literal> implementation is focused on processing 2 request events. First, | 
 |                 it listens for an event that is triggered before a resource method is executed. Also, it hooks to a "request finished" | 
 |                 event. As mentioned earlier, the request event <literal>START</literal> is handled only in the | 
 |                 <literal>MyApplicationEventListener</literal>. The <literal>START</literal> event type will never be invoked on | 
 |                 <literal>RequestEventListener</literal>. Therefore the logic for measuring the <literal>startTime</literal> is in the | 
 |                 constructor which is invoked from <literal>MyApplicationEventListener.onRequest()</literal>. An attempt to handling | 
 |                 the request <literal>START</literal> event in a <literal>RequestEventListener.onEvent()</literal> method would be a | 
 |                 mistake. | 
 |             </para> | 
 |             <para> | 
 |                 Let's deploy the application and use a simple test client code to produce some activity in order to spawn new events: | 
 |  | 
 |                 <programlisting language="java" linenumbering="numbered"><![CDATA[target.path("resource").request() | 
 |         .post(Entity.entity("post", MediaType.TEXT_PLAIN_TYPE)); | 
 |     target.path("resource").request().get();]]></programlisting> | 
 |  | 
 |                 In the code above, the <literal>target</literal> is a &jaxrs.client.WebTarget; instance pointing to the application | 
 |                 context root path. Using the <xref linkend="client" />, we invoke &lit.http.GET; and &lit.http.POST; methods | 
 |                 on the <literal>MyResource</literal> JAX-RS resource class that we implemented earlier. | 
 |             </para> | 
 |             <para> | 
 |                 When we start the application, run the test client and then stop the application, the console output for the | 
 |                 deployed server-side application would contain the following output: | 
 |  | 
 |                 <programlisting language="text" linenumbering="unnumbered">Application my-monitored-application was initialized. | 
 | Request 1 started. | 
 | Resource method POST started for request 1 | 
 | Request 1 finished. Processing time 330 ms. | 
 | Request 2 started. | 
 | Resource method GET started for request 2 | 
 | Request 2 finished. Processing time 4 ms. | 
 | Application my-monitored-application destroyed.</programlisting> | 
 |             </para> | 
 |             <section> | 
 |                 <title>Guidelines for implementing Jersey event listeners</title> | 
 |                 <itemizedlist> | 
 |                     <listitem><para> | 
 |                         Implement event listeners as thread safe. While individual events will be arriving serially, | 
 |                         individual listener invocations may occur from different threads. Thus make sure that your listeners | 
 |                         are processing data safely with respect to their | 
 |                         <link xlink:href='&wikipedia.uri;Java_Memory_Model'>Java Memory Model</link> visibility (in the example | 
 |                         above the fields <literal>requestNumber</literal>, <literal>startTime</literal> of | 
 |                         <literal>MyRequestEventListener</literal> are final and therefore the same value is | 
 |                         visible for all threads executing the <literal>onEvent()</literal> method). | 
 |                     </para></listitem> | 
 |                     <listitem><para> | 
 |                         Do not block the thread executing the event listeners by performing long-running tasks. Execution of event | 
 |                         listeners is a part of the standard application and request processing and as such needs to finish as quickly | 
 |                         as possible to avoid negative impact on overall application performance. | 
 |                     </para></listitem> | 
 |                     <listitem><para> | 
 |                         Do not try to modify mutable objects returned from &lit.jersey.server.monitoring.ApplicationEvent; and | 
 |                         &lit.jersey.server.monitoring.RequestEvent; getters to avoid experiencing undefined behavior. | 
 |                         Events listeners should use the information for read only purposes only. Use different techniques like | 
 |                         filters, interceptors or other providers to modify the processing of requests and applications. Even though | 
 |                         modification might be possible and might work as desired now, your code is in risk of producing intermittent | 
 |                         failures or unexpected behaviour (for example after migrating to new Jersey version). | 
 |                     </para></listitem> | 
 |                     <listitem><para> | 
 |                         If you do not want to listen to request events, do not return an empty listener in the | 
 |                         <literal>onRequest()</literal> method. Return <literal>null</literal> instead. Returning empty listener | 
 |                         might have a negative performance impact. Do not rely on JIT optimizing out the empty listener invocation | 
 |                         code. | 
 |                     </para></listitem> | 
 |                     <listitem><para> | 
 |                         If you miss any event type or any detail in the events, let us know via Jersey user mailing list. | 
 |                     </para></listitem> | 
 |                 </itemizedlist> | 
 |             </section> | 
 |             <section> | 
 |                 <title>Monitoring Statistics</title> | 
 |                 <para> | 
 |                     Event listeners described in the previous section are all-purpose facility. For example, you may decide to | 
 |                     use them to measure various execution statistics of your application. While this might be an easy task for simple | 
 |                     statistics like "how much time was spent on execution of each Java method?", nevertheless, if you want to measure | 
 |                     statistics based on URIs and individual resources, the implementation might get rather complex soon, especially | 
 |                     when considering sub-resources and sub-resource locators. To save you the trouble, Jersey provides feature for | 
 |                     collecting events and calculating a pre-defined set of monitoring and execution statistics, including | 
 |                     application configuration, exception mappers execution, minimum/maximum/average execution times for individual | 
 |                     resource methods as well as entire request processing etc. | 
 |                 </para> | 
 |                 <para> | 
 |                     Calculating the monitoring statistics has obviously a performance impact, therefore this feature is | 
 |                     disabled by default. To enable the feature, set the following configuration property to &lit.true;: | 
 |                 </para> | 
 |                 <programlisting language="java" linenumbering="unnumbered">jersey.config.server.monitoring.statistics.enabled=true</programlisting> | 
 |                 <para> | 
 |                     The property description can be found in &jersey.server.ServerProperties.MONITORING_STATISTICS_ENABLED; | 
 |                     This will calculate the statistics. The easiest way how to get statistics is to let Jersey | 
 |                     to inject them. See the following example: | 
 |                 </para> | 
 |                 <example> | 
 |                     <title>Injecting MonitoringStatistics</title> | 
 |                     <programlisting language="java" linenumbering="numbered"><![CDATA[@Path("resource") | 
 | public static class StatisticsResource { | 
 |     @Inject | 
 |     Provider<MonitoringStatistics> monitoringStatisticsProvider; | 
 |  | 
 |     @GET | 
 |     public String getSomething() { | 
 |         final MonitoringStatistics snapshot | 
 |             = monitoringStatisticsProvider.get().snapshot(); | 
 |  | 
 |         final TimeWindowStatistics timeWindowStatistics | 
 |             = snapshot.getRequestStatistics() | 
 |               .getTimeWindowStatistics().get(0l); | 
 |  | 
 |         return "request count: " + timeWindowStatistics.getRequestCount() | 
 |             + ", average request processing [ms]: " | 
 |             + timeWindowStatistics.getAverageDuration(); | 
 |     } | 
 | }}]]></programlisting> | 
 |                 </example> | 
 |                 <para> | 
 |                     &jersey.server.monitoring.MonitoringStatistics; are | 
 |                     injected into the resource using an &jee9.jakarta.inject.Inject; annotation. | 
 |                     Please note the usage of the &jee9.jakarta.inject.Provider; for injection (it will be discussed later). | 
 |                     Firstly, the snapshot of statistics is retrieved by the <literal>snapshot()</literal> method. | 
 |                     The snapshot of statistics is an immutable copy of statistics which does not change over the time. | 
 |                     Additionally, data in a snapshot are consistent. It's recommended to create snapshots before working with | 
 |                     the statistics data and then process the snapshot data. | 
 |                     Working with original non-snapshot data makes sense when data consistency is not important and | 
 |                     performance is of highest concern. While it is currently not the case, the injected non-snapshot data may | 
 |                     be implemented as mutable for performance reasons in a future release of Jersey. | 
 |                 </para> | 
 |                 <para> | 
 |                     The injected monitoring statistics represent the root of the collected statistics hierarchy. The hierarchy | 
 |                     can be traversed to retrieve any partial statistics data. In the example, we retrieve certain request | 
 |                     &jersey.server.monitoring.TimeWindowStatistics; data. In our case, those are the request execution statistics | 
 |                     for a time window defined by long value 0 which means unlimited time window. This means we are retrieving | 
 |                     the global request execution statistics measured since a start of the application. | 
 |                     Finally, request count and average duration from the statistics are used to produce the String response. | 
 |                     When we invoke few &lit.http.GET; requests on the <literal>StatisticsResource</literal>, we get the | 
 |                     following console output: | 
 |                     <programlisting language="text" linenumbering="unnumbered">request count: 1, average request processing [ms]: 260 | 
 | request count: 2, average request processing [ms]: 135 | 
 | request count: 3, average request processing [ms]: 93 | 
 | request count: 4, average request processing [ms]: 73</programlisting> | 
 |                 </para> | 
 |                 <para> | 
 |                     Let's look closer at &jersey.server.monitoring.MonitoringStatistics; interface. | 
 |                     &lit.jersey.server.monitoring.MonitoringStatistics; interface defines getters by which other nested | 
 |                     statistics can be retrieved. All statistics are in the same package and ends with | 
 |                     <literal>Statistics</literal> postfix. Statistics interfaces are the following: | 
 |                     <variablelist> | 
 |                         <varlistentry> | 
 |                             <term>&jersey.server.monitoring.MonitoringStatistics;</term> | 
 |                             <listitem> | 
 |                                 <para>main top level statistics</para> | 
 |                             </listitem> | 
 |                         </varlistentry> | 
 |                         <varlistentry> | 
 |                             <term>&jersey.server.monitoring.ResponseStatistics;</term> | 
 |                             <listitem> | 
 |                                 <para>response statistics (eg. response status codes and their count)</para> | 
 |                             </listitem> | 
 |                         </varlistentry> | 
 |                         <varlistentry> | 
 |                             <term>&jersey.server.monitoring.ResourceStatistics;</term> | 
 |                             <listitem> | 
 |                                 <para>statistics of execution of resources (resource classes or resource URIs)</para> | 
 |                             </listitem> | 
 |                         </varlistentry> | 
 |                         <varlistentry> | 
 |                             <term>&jersey.server.monitoring.ResourceMethodStatistics;</term> | 
 |                             <listitem> | 
 |                                 <para>statistics of execution of resource methods</para> | 
 |                             </listitem> | 
 |                         </varlistentry> | 
 |                         <varlistentry> | 
 |                             <term>&jersey.server.monitoring.ExecutionStatistics;</term> | 
 |                             <listitem> | 
 |                                 <para>statistic of execution of a target (resource, request, resource method)</para> | 
 |                             </listitem> | 
 |                         </varlistentry> | 
 |                         <varlistentry> | 
 |                             <term>&jersey.server.monitoring.TimeWindowStatistics;</term> | 
 |                             <listitem> | 
 |                                 <para>statistics of execution time in specific interval (eg. executions in last 5 minutes)</para> | 
 |                             </listitem> | 
 |                         </varlistentry> | 
 |                     </variablelist> | 
 |                 </para> | 
 |  | 
 |                 <para> | 
 |                     Each time-monitored target contains &lit.jersey.server.monitoring.ExecutionStatistics;. So, for example | 
 |                     resource method contains execution statistics of its execution. Each | 
 |                     &lit.jersey.server.monitoring.ExecutionStatistics; contains multiple | 
 |                     &lit.jersey.server.monitoring.TimeWindowStatistics;. Currently, each | 
 |                     &lit.jersey.server.monitoring.ExecutionStatistics; contains | 
 |                     &lit.jersey.server.monitoring.TimeWindowStatistics; for these time windows: | 
 |  | 
 |                     <itemizedlist> | 
 |                         <listitem><para>0: unlimited=> all execution since start of the application</para></listitem> | 
 |                         <listitem><para>1000: 1s => stats measured in last 1 second</para></listitem> | 
 |                         <listitem><para>15000: 15s => stats measured in last 15 seconds</para></listitem> | 
 |                         <listitem><para>60000: 1min => stats measured in last 1 minute</para></listitem> | 
 |                         <listitem><para>900000: 15min => stats measured in last 15 minutes</para></listitem> | 
 |                         <listitem><para>3600000: 1hour => stats measured in last hour minutes</para></listitem> | 
 |                     </itemizedlist> | 
 |  | 
 |                     All the time window statistics can be retrieved from a <literal>Map<Long, TimeWindowStatistics></literal> | 
 |                     map returned from <literal>ExecutionStatistics.getTimeWindowStatistics()</literal>. Key of the map | 
 |                     is the number of milliseconds of interval (so, for example key 60000 points | 
 |                     to statistics for last one minute). | 
 |                 </para> | 
 |                 <para> | 
 |                     Note, that <literal>snapshot()</literal> method was called in the example only on the top level | 
 |                     &lit.jersey.server.monitoring.MonitoringStatistics;. This produced a snapshot of the entire | 
 |                     tree of statistics and therefore we do not need to call <literal>snapshot()</literal> | 
 |                     on &lit.jersey.server.monitoring.TimeWindowStatistics; again. | 
 |                 </para> | 
 |                 <para> | 
 |                     Statistics are injected using the &jee9.jakarta.inject.Provider;. This is preferred way of | 
 |                     injecting statistics. The reason is simple. Statistics might change over time and contract | 
 |                     of &lit.jersey.server.monitoring.MonitoringStatistics; does not make any assumptions about mutability of | 
 |                     monitoring statistics instances (to allow future optimizations and changes in implementation strategy). In | 
 |                     order to get always latest statistics, we recommend injecting a &jee9.jakarta.inject.Provider; rather than a | 
 |                     direct reference and use its <literal>get()</literal> method to retrieve the latest statistics. For example, | 
 |                     in singleton resources the use of the technique is very important otherwise statistics might correspond | 
 |                     to the time when singleton was firstly created and might not update since that time. | 
 |                 </para> | 
 |                 <section> | 
 |                     <title>Listening to statistics changes</title> | 
 |                     <para> | 
 |                         Statistics are not calculated for each request or each change. Statistics are calculated only | 
 |                         from the collected data in regular intervals for performance reasons (for example once per second). | 
 |                         If you want to be notified about new statistics, register an implementation of | 
 |                         &jersey.server.monitoring.MonitoringStatisticsListener; as one of your custom application providers. | 
 |                         Your listener will be called every time the new statistics are calculated and the updated statistics | 
 |                         data will be passed to the listener method. This is another way of receiving statistics. | 
 |                         See the linked listener API documentation for more information. | 
 |                     </para> | 
 |                 </section> | 
 |             </section> | 
 |             <section> | 
 |                 <title>Monitoring Statistics as MBeans</title> | 
 |                 <para> | 
 |                     Jersey provides feature to expose monitoring statistics as JMX MXBeans. | 
 |                     In order to enable monitoring statistics MXBeans exposure, the | 
 |                     &jersey.server.ServerProperties.MONITORING_STATISTICS_MBEANS_ENABLED; must be set to &lit.true;. | 
 |                 </para> | 
 |                 <programlisting language="java" linenumbering="unnumbered">jersey.config.server.monitoring.statistics.mbeans.enabled=true</programlisting> | 
 |                 <para> | 
 |                     Note that enabling exposure of monitoring MXBeans causes that also the calculation of | 
 |                     &lit.jersey.server.monitoring.MonitoringStatistics; is automatically enabled as the exposed | 
 |                     MXBean statistics are extracted from &lit.jersey.server.monitoring.MonitoringStatistics;. | 
 |                 </para> | 
 |                 <para> | 
 |                     The easiest way is to browse the MXBeans in the JConsole. Open the JConsole | 
 |                     (<literal>$JAVA_HOME/bin/jconsole</literal>). Then connect to the process where JAX-RS application is running | 
 |                     (server on which the application is running). Switch to a MBean tab and in the MBean tree on the left side | 
 |                     find a group <literal>org.glassfish.jersey</literal>. All deployed Jersey applications are located under this | 
 |                     group. If you don't see such this group, then MBeans are not exposed (check the configuration property and | 
 |                     logs if they not contain any exceptions or errors). The following figure is an example of an output from the | 
 |                     JConsole: | 
 |                 </para> | 
 |  | 
 |                 <mediaobject> | 
 |                     <imageobject> | 
 |                         <imagedata fileref="images/monitoring-jsconsole.png" format="PNG" width="100%" scalefit="1" align="center"/> | 
 |                     </imageobject> | 
 |                 </mediaobject> | 
 |  | 
 |                 <para> | 
 |                     Under the root <literal>org.glassfish.jersey</literal> Jersey MBean group you can find your application. | 
 |                     If the server contains more Jersey application, all will be present under the root Jersey the group. In the | 
 |                     screen-shot, the deployed JAX-RS application is named <literal>myApplication</literal> (the name can be defined | 
 |                     via &jersey.server.ResourceConfig; directly or by setting the &jersey.server.ServerProperties.APPLICATION_NAME; | 
 |                     property). | 
 |                     Each application contains <literal>Global</literal>, <literal>Resource</literal> and | 
 |                     <literal>Uris</literal> sub-groups. The <literal>Global</literal> group contains all global | 
 |                     statistics like overall requests statistics of the entire application (<literal>AllRequestTimes</literal>), | 
 |                     configuration of the JAX-RS application (<literal>Configuration</literal>), statistics about | 
 |                     &jaxrs.ext.ExceptionMapper; execution (<literal>ExceptionMapper</literal>) and statistics about | 
 |                     produced responses (<literal>Responses</literal>). | 
 |                 </para> | 
 |                 <para> | 
 |                     <literal>Resources</literal> and <literal>Uris</literal> groups contains monitoring statistics specific to | 
 |                     individual resources. | 
 |                     Statistics in <literal>Resources</literal> are bound to the JAX-RS resource Java classes loaded by the | 
 |                     application. <literal>Uris</literal> contains statistics of resources based on the matched application Uris | 
 |                     (one URI entry represents all methods bound to the particular URI, e.g. <literal>/resource/exception</literal>). | 
 |                     As Jersey provides programmatic resource builders (described in the chapter | 
 |                     <link linkend="resource-builder">"Programmatic API for Building Resources"</link>), one Java resource class | 
 |                     can be an endpoint for resource methods on many different URIs. And also one URI can be served by method from | 
 |                     many different Java classes. Therefore both views are not to be compared 1:1. Instead they provide | 
 |                     different logical views on your JAX-RS application. This monitoring feature can also be helpful when designing | 
 |                     the JAX-RS APIs as it provides nice view on available root application URIs. | 
 |                 </para> | 
 |                 <para> | 
 |                     Both logical views on the resources exposed by application share few common principles. A single resource entry | 
 |                     is always a set of resource methods which are available under the <literal>methods</literal> sub-group. Statistics | 
 |                     can be found in MBeans <literal>MethodTimes</literal> and <literal>RequestTimes</literal>. | 
 |                     <literal>MethodTimes</literal> contains statistics measured on resource methods (duration of execution of a | 
 |                     code of the a resource method), whereas <literal>RequestTimes</literal> contains statistics of an entire request | 
 |                     execution (not only a time of the execution of the resource method but the overall time of the execution of whole | 
 |                     request by Jersey runtime). Another useful information is that statistics directly under resource (not under | 
 |                     the <literal>methods</literal> sub-group) contains summary of statistics for all resource methods grouped in the | 
 |                     resource entry. | 
 |                 </para> | 
 |                 <para>Additional useful details about statistics</para> | 
 |                 <itemizedlist> | 
 |                     <listitem><para><literal>Global->Configuration->Registered(Classes/Instances)</literal>: | 
 |                         registered resource classes and instances by the user (i.e., not added by &jersey.server.ModelProcessor; | 
 |                         during deployment for example). | 
 |                     </para></listitem> | 
 |                     <listitem><para><literal>Global->ExceptionMapper->ExceptionMapperCount</literal>: | 
 |                         map that contains exception mapper classes as keys and number of their execution as values. | 
 |                     </para></listitem> | 
 |                     <listitem><para> | 
 |                         <literal>Global->Responses->ResponseCodesToCountMap</literal>: | 
 |                         map that contains response codes as keys and their total occurrence in responses as values. | 
 |                     </para></listitem> | 
 |                     <listitem><para> | 
 |                         Resource groups contain also entries for resources that were added by Jersey at deployment time using | 
 |                         &lit.jersey.server.ModelProcessor; (for example all &lit.http.OPTIONS; methods, <literal>WADL</literal>). | 
 |                         &lit.http.HEAD; methods are not present in the MXBeans view (even HEAD methods are in resources). | 
 |                     </para></listitem> | 
 |                     <listitem><para> | 
 |                         Execution statistics for different time windows have different update intervals. The shorter the time window, | 
 |                         the shorter the update interval. This causes that immediately after the application start, the shorter time | 
 |                         windows (such as 15 seconds) may contain higher values than longer ones (e.g. 1 hour time window). The reason | 
 |                         is that 1 hour interval will show information that is not up to date and therefore has smaller value. This | 
 |                         inconsistency is not so much significant when application is running longer time. Total unlimited time windows | 
 |                         contains always up-to-date data. This inconsistency will get fixed in a future Jersey release. | 
 |                     </para></listitem> | 
 |                 </itemizedlist> | 
 |                 <para> | 
 |                     MXBeans can be also accessed using JMX. To do so, you would need to use the interfaces of MXBeans. | 
 |                     These interfaces are even useful when working with MXBeans only trough <literal>JConsole</literal> as | 
 |                     they contain Javadocs for each MXBean and attribute. Monitoring MBeans are defined by following interfaces: | 
 |  | 
 |                     <itemizedlist> | 
 |                         <listitem><para> | 
 |                             &jersey.server.monitoring.ApplicationMXBean;: contains configuration statistics | 
 |                         </para></listitem> | 
 |                         <listitem><para> | 
 |                             &jersey.server.monitoring.ExceptionMapperMXBean;: contains statistics of exception mappers | 
 |                         </para></listitem> | 
 |                         <listitem><para> | 
 |                             &jersey.server.monitoring.ResourceMethodMXBean;: contains statistics of resource method | 
 |                         </para></listitem> | 
 |                         <listitem><para> | 
 |                             &jersey.server.monitoring.ResourceMXBean;: contains statistics of resource | 
 |                         </para></listitem> | 
 |                         <listitem><para> | 
 |                             &jersey.server.monitoring.ResponseMXBean;: contains statistics of responses | 
 |                         </para></listitem> | 
 |                     </itemizedlist> | 
 |  | 
 |                     The list does not contain MXBean for the execution and time window statistics. The reason is that | 
 |                     this bean is defined as a &jdk6.DynamicMBean;. Attributes of this dynamic MBean contains | 
 |                     statistics for all time windows available. | 
 |                 </para> | 
 |                 <para> | 
 |                     MXBeans do not reference each other but can be retrieved by their &jdk6.ObjectName;s which | 
 |                     are designed in the way, that final MBean tree looks nicely organized in <emphasis>JConsole</emphasis>. | 
 |                     Each MXBean is uniquely identified by its &lit.jdk6.ObjectName; and properties of | 
 |                     &lit.jdk6.ObjectName; are structured hierarchically, so that each MXBean can be identified to which | 
 |                     parent it belong to (e.g. execution statistics dynamic MXBean belongs to resource method MXBean, which | 
 |                     belongs to resource and which belongs to application). Check the &lit.jdk6.ObjectName;s of | 
 |                     exposed MXBeans to investigate the structure (for example through JConsole). | 
 |                 </para> | 
 |                 <para> | 
 |                     To reiterate, exposing Jersey MXBeans and the calculating monitoring statistics may have an performance impact | 
 |                     on your application and therefore should be enabled only when needed. Also, please note, that Jersey | 
 |                     monitoring is exposing quite a lot of information about the monitored application which might be viewed as | 
 |                     problematic in some cases (e.g. in production server deployments). | 
 |                 </para> | 
 |             </section> | 
 |         </section> | 
 |     </section> | 
 |     <section xml:id="tracing"> | 
 |         <title>Tracing Support</title> | 
 |         <para> | 
 |             Apart from monitoring and collecting application statistics described in <xref linkend="monitoring"/>, Jersey | 
 |             can also provide tracing or diagnostic information about server-side processing of individual requests. | 
 |             This facility may provide vital information when troubleshooting your misbehaving Jersey or JAX-RS application. | 
 |             When enabled, Jersey tracing facility collects useful information from all parts of JAX-RS server-side request | 
 |             processing pipeline: | 
 |             <literal>PreMatchRequestFilter</literal>, <literal>ResourceMatching</literal>, <literal>RequestFilter</literal>, | 
 |             <literal>ReadIntercept</literal>, <literal>MBR</literal>, <literal>Invoke</literal>, | 
 |             <literal>ResponseFilter</literal>, <literal>WriteIntercept</literal>, <literal>MBW</literal>, as well as | 
 |             <literal>ExceptionHandling</literal>. | 
 |         </para> | 
 |         <para> | 
 |             The collected tracing information related to a single request is returned to the requesting client in the HTTP | 
 |             headers of a response for the request. The information is also logged on the server side using a dedicated Java | 
 |             Logger instance. | 
 |         </para> | 
 |         <section xml:id="tracing.configuration"> | 
 |             <title>Configuration options</title> | 
 |             <para> | 
 |                 Tracing support is disabled by default. You can enable it either "globally" for all application requests | 
 |                 or selectively per request. The tracing support activation is controlled by setting the | 
 |                 <literal>jersey.config.server.tracing.type</literal> application configuration property. The property value | 
 |                 is expected to be one of the following: | 
 |  | 
 |                 <itemizedlist> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>OFF</literal> - tracing support is disabled (default value). | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>ON_DEMAND</literal> - tracing support is in a stand-by mode; it is enabled selectively | 
 |                             per request, via a special <literal>X-Jersey-Tracing-Accept</literal> HTTP request header. | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>ALL</literal> - tracing support is enabled for all request. | 
 |                         </para> | 
 |                     </listitem> | 
 |                 </itemizedlist> | 
 |             </para> | 
 |             <para> | 
 |                 The level of detail of the information provided by Jersey tracing facility - the tracing threshold - can be | 
 |                 customized. The tracing threshold can be set at the application level via | 
 |                 <literal>jersey.config.server.tracing.threshold</literal> application configuration property, | 
 |                 or at a request level, via <literal>X-Jersey-Tracing-Threshold</literal> HTTP request header. The request level | 
 |                 configuration overrides any application level setting. There are 3 supported levels of detail for Jersey tracing: | 
 |                 <itemizedlist> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>SUMMARY</literal> - very basic summary information about the main request processing stages. | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>TRACE</literal> - detailed information about activities in all the main request processing | 
 |                             stages (default threshold value). | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>VERBOSE</literal> - most verbose mode that provides extended information similar to | 
 |                             <literal>TRACE</literal> level, however with details on entity providers | 
 |                             (<literal>MBR</literal>/<literal>MBW</literal>) that were skipped during the provider selection | 
 |                             phase for any reason (lower priority, pattern matching, etc). Additionally, in this mode all | 
 |                             received request headers are echoed as part of the tracing information. | 
 |                         </para> | 
 |                     </listitem> | 
 |                 </itemizedlist> | 
 |             </para> | 
 |         </section> | 
 |         <section> | 
 |             <title>Tracing Log</title> | 
 |             <para> | 
 |                 As mentioned earlier, all tracing information is also logged using a dedicated Java Logger. The individual | 
 |                 tracing messages are logged immediately as the tracing events occur. The default name of the tracing logger | 
 |                 is prefixed <literal>org.glassfish.jersey.tracing.</literal> with a default suffix <literal>general</literal>. | 
 |                 This logger name can be customized per request by including a <literal>X-Jersey-Tracing-Logger</literal> | 
 |                 HTTP request header as will be shown later. | 
 |             </para> | 
 |         </section> | 
 |         <section> | 
 |             <title>Configuring tracing support via HTTP request headers</title> | 
 |             <para> | 
 |                 Whenever the tracing support is active (<literal>ON_DEMAND</literal> or <literal>ALL</literal>) you | 
 |                 can customize the tracing behaviour by including one or more of the following request HTTP headers in your | 
 |                 individual requests: | 
 |                 <itemizedlist> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>X-Jersey-Tracing-Accept</literal> - used to enable the tracing support for the particular | 
 |                             request. It is applied only when the application-level tracing support is configured to | 
 |                             <literal>ON_DEMAND</literal> mode. The value of the header is not used by the Jersey tracing | 
 |                             facility and as such it can be any arbitrary (even empty) string. | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>X-Jersey-Tracing-Threshold</literal> - used to override the tracing level of detail. | 
 |                             Allowed values are: <literal>SUMMARY</literal>, <literal>TRACE</literal>, <literal>VERBOSE</literal>. | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>X-Jersey-Tracing-Logger</literal> - used to override the tracing Java logger name suffix. | 
 |                         </para> | 
 |                     </listitem> | 
 |                 </itemizedlist> | 
 |             </para> | 
 |         </section> | 
 |         <section> | 
 |             <title>Format of the HTTP response headers</title> | 
 |             <para> | 
 |                 At the end of request processing all tracing messages are appended to the HTTP response as individual | 
 |                 headers named <literal>X-Jersey-Tracing-</literal><emphasis><literal>nnn</literal></emphasis> where | 
 |                 <emphasis><literal>nnn</literal></emphasis> is index number of message starting at <literal>0</literal>. | 
 |             </para> | 
 |             <para> | 
 |                 Each tracing message is in the following format: <literal>CATEGORY [TIME] TEXT</literal>, e.g. | 
 |                 <screen>X-Jersey-Tracing-007: WI          [85.95 / 183.69 ms | 46.77 %] WriteTo summary: 4 interceptors</screen> | 
 |             </para> | 
 |             <para> | 
 |                 The <literal>CATEGORY</literal> is used to categorize tracing events according to the following | 
 |                 event types: | 
 |                 <itemizedlist> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>START</literal> - start of request processing information | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>PRE-MATCH</literal> - pre-matching request filter processing | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>MATCH</literal> - matching request URI to a resource method | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>REQ-FILTER</literal> - request filter processing | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>RI</literal> - entity reader interceptor processing | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>MBR</literal> - message body reader selection and invocation | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>INVOKE</literal> - resource method invocation | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>RESP-FILTER</literal> - response filter processing | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>WI</literal> - write interceptor processing | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>MBW</literal> - message body writer selection and invocation | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>MVC</literal> - template engine integration | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>EXCEPTION</literal> - exception mapping | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>FINISHED</literal> - processing finish summary | 
 |                         </para> | 
 |                     </listitem> | 
 |                 </itemizedlist> | 
 |             </para> | 
 |             <para> | 
 |                 The <literal>TIME</literal>, if present, is a composite value that consists of 3 parts | 
 |                 <literal>[ duration / time_from_start | total_req_ratio ]</literal>: | 
 |                 <orderedlist> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>duration</literal> - the duration of the current trace event [milliseconds]; | 
 |                             e.g. duration of filter processing | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>time_from_start</literal> - the end time of the current event with respect to | 
 |                             the request processing start time [milliseconds] | 
 |                         </para> | 
 |                     </listitem> | 
 |                     <listitem> | 
 |                         <para> | 
 |                             <literal>total_req_ratio</literal> - the duration of the current event with respect to | 
 |                             the total request processing time [percentage]; this value tells you how significant part | 
 |                             of the whole request processing time has been spent in the processing phase described by | 
 |                             the current event | 
 |                         </para> | 
 |                     </listitem> | 
 |                 </orderedlist> | 
 |                 There are certain tracing events that do not have any duration. In such case, duration values are not set | 
 |                 (<literal>----</literal> literal). | 
 |             </para> | 
 |             <para> | 
 |                 The tracing event <literal>TEXT</literal> is a free-form detailed text information about the | 
 |                 current diagnostic event. | 
 |                 <tip> | 
 |                     <para> | 
 |                         For better identification, instances of JAX-RS components are represented by class name, | 
 |                         identity hash code and <literal>@Priority</literal> value if set, e.g. | 
 |                         <literal>[org.glassfish.jersey.tests.integration.tracing.ContainerResponseFilter5001 @494a8227 #5001]</literal>. | 
 |                     </para> | 
 |                 </tip> | 
 |             </para> | 
 |         </section> | 
 |         <section> | 
 |             <title>Tracing Examples</title> | 
 |             <para> | 
 |                 Example of <literal>SUMMARY</literal> level messages | 
 |                 from <literal>tests/integration/tracing-support</literal> module: | 
 |                 <example> | 
 |                     <title>Summary level messages</title> | 
 |                     <screen linenumbering="numbered"><![CDATA[$ curl -i http://localhost:9998/ALL/root/sub-resource-locator/sub-resource-method -H content-type:application/x-jersey-test --data '-=#[LKR]#=-' -H X-Jersey-Tracing-Threshold:SUMMARY -H accept:application/x-jersey-test -X POST | 
 |  | 
 | X-Jersey-Tracing-000: START       [ ---- /  ---- ms |  ---- %] baseUri=[http://localhost:9998/ALL/] requestUri=[http://localhost:9998/ALL/root/sub-resource-locator/sub-resource-method] method=[POST] authScheme=[n/a] accept=[application/x-jersey-test] accept-encoding=n/a accept-charset=n/a accept-language=n/a content-type=[application/x-jersey-test] content-length=[11] | 
 | X-Jersey-Tracing-001: PRE-MATCH   [ 0.01 /  0.68 ms |  0.01 %] PreMatchRequest summary: 2 filters | 
 | X-Jersey-Tracing-002: MATCH       [ 8.44 /  9.15 ms |  4.59 %] RequestMatching summary | 
 | X-Jersey-Tracing-003: REQ-FILTER  [ 0.01 /  9.20 ms |  0.00 %] Request summary: 2 filters | 
 | X-Jersey-Tracing-004: RI          [86.14 / 95.49 ms | 46.87 %] ReadFrom summary: 3 interceptors | 
 | X-Jersey-Tracing-005: INVOKE      [ 0.04 / 95.70 ms |  0.02 %] Resource [org.glassfish.jersey.tests.integration.tracing.SubResource @901a4f3] method=[public org.glassfish.jersey.tests.integration.tracing.Message org.glassfish.jersey.tests.integration.tracing.SubResource.postSub(org.glassfish.jersey.tests.integration.tracing.Message)] | 
 | X-Jersey-Tracing-006: RESP-FILTER [ 0.01 / 96.55 ms |  0.00 %] Response summary: 2 filters | 
 | X-Jersey-Tracing-007: WI          [85.95 / 183.69 ms | 46.77 %] WriteTo summary: 4 interceptors | 
 | X-Jersey-Tracing-008: FINISHED    [ ---- / 183.79 ms |  ---- %] Response status: 200/SUCCESSFUL|OK]]></screen> | 
 |                 </example> | 
 |             </para> | 
 |             <para> | 
 |                 Example <literal>TRACE</literal> level messages of <literal>jersey-mvc-jsp</literal> integration, | 
 |                 from <literal>examples/bookstore-webapp</literal> module: | 
 |                 <example> | 
 |                     <title>On demand request, snippet of MVC JSP forwarding</title> | 
 |                     <screen linenumbering="numbered"><![CDATA[$ curl -i http://localhost:9998/items/3/tracks/0 -H X-Jersey-Tracing-Accept:whatever | 
 |  | 
 | ... | 
 | X-Jersey-Tracing-033: WI          [ 0.00 / 23.39 ms |  0.02 %] [org.glassfish.jersey.server.mvc.internal.TemplateMethodInterceptor @141bcd49 #4000] BEFORE context.proceed() | 
 | X-Jersey-Tracing-034: WI          [ 0.01 / 23.42 ms |  0.02 %] [org.glassfish.jersey.filter.LoggingFilter @2d427def #-2147483648] BEFORE context.proceed() | 
 | X-Jersey-Tracing-035: MBW         [ ---- / 23.45 ms |  ---- %] Find MBW for type=[org.glassfish.jersey.server.mvc.internal.ImplicitViewable] genericType=[org.glassfish.jersey.server.mvc.internal.ImplicitViewable] mediaType=[[jakarta.ws.rs.core.MediaType @7bfbfeae]] annotations=[] | 
 | X-Jersey-Tracing-036: MBW         [ ---- / 23.52 ms |  ---- %] [org.glassfish.jersey.server.mvc.internal.ViewableMessageBodyWriter @78b353d4] IS writeable | 
 | X-Jersey-Tracing-037: MVC         [ ---- / 24.05 ms |  ---- %] Forwarding view to JSP page [/org/glassfish/jersey/examples/bookstore/webapp/resource/Track/index.jsp], model [org.glassfish.jersey.examples.bookstore.webapp.resource.Track @3937f594] | 
 | X-Jersey-Tracing-038: MBW         [ 1.09 / 24.63 ms |  4.39 %] WriteTo by [org.glassfish.jersey.server.mvc.internal.ViewableMessageBodyWriter @78b353d4] | 
 | X-Jersey-Tracing-039: WI          [ 0.00 / 24.67 ms |  0.01 %] [org.glassfish.jersey.filter.LoggingFilter @2d427def #-2147483648] AFTER context.proceed() | 
 | X-Jersey-Tracing-040: WI          [ 0.00 / 24.70 ms |  0.01 %] [org.glassfish.jersey.server.mvc.internal.TemplateMethodInterceptor @141bcd49 #4000] AFTER context.proceed() | 
 | ...]]></screen> | 
 |                 </example> | 
 |             </para> | 
 |         </section> | 
 |     </section> | 
 | </chapter> |