-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
1,388 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>io.dropwizard.metrics</groupId> | ||
<artifactId>metrics-parent</artifactId> | ||
<version>4.2.20-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>metrics-jetty12-ee10</artifactId> | ||
<name>Metrics Integration for Jetty 12.x and higher with Jakarta EE 10</name> | ||
<packaging>bundle</packaging> | ||
<description> | ||
A set of extensions for Jetty 12.x and higher which provide instrumentation of thread pools, connector | ||
metrics, and application latency and utilization. This module uses the Servlet API from Jakarta EE 10. | ||
</description> | ||
|
||
<properties> | ||
<javaModuleName>io.dropwizard.metrics.jetty12.ee10</javaModuleName> | ||
|
||
<maven.compiler.source>17</maven.compiler.source> | ||
<maven.compiler.target>17</maven.compiler.target> | ||
|
||
<slf4j.version>2.0.7</slf4j.version> | ||
</properties> | ||
|
||
<dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>io.dropwizard.metrics</groupId> | ||
<artifactId>metrics-bom</artifactId> | ||
<version>${project.version}</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-bom</artifactId> | ||
<version>${jetty12.version}</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty.ee10</groupId> | ||
<artifactId>jetty-ee10-bom</artifactId> | ||
<version>${jetty12.version}</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
<version>${slf4j.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>net.bytebuddy</groupId> | ||
<artifactId>byte-buddy</artifactId> | ||
<version>${byte-buddy.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>jakarta.servlet</groupId> | ||
<artifactId>jakarta.servlet-api</artifactId> | ||
<version>${servlet6.version}</version> | ||
</dependency> | ||
</dependencies> | ||
</dependencyManagement> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>io.dropwizard.metrics</groupId> | ||
<artifactId>metrics-core</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.dropwizard.metrics</groupId> | ||
<artifactId>metrics-annotation</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.dropwizard.metrics</groupId> | ||
<artifactId>metrics-jetty12</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-server</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-util</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty.ee10</groupId> | ||
<artifactId>jetty-ee10-servlet</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>jakarta.servlet</groupId> | ||
<artifactId>jakarta.servlet-api</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
<version>${slf4j.version}</version> | ||
<scope>runtime</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>${junit.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.assertj</groupId> | ||
<artifactId>assertj-core</artifactId> | ||
<version>${assertj.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
<version>${mockito.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-client</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.eclipse.jetty</groupId> | ||
<artifactId>jetty-http</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-simple</artifactId> | ||
<version>${slf4j.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
173 changes: 173 additions & 0 deletions
173
...etty12-ee10/src/main/java/io/dropwizard/metrics/jetty12/ee10/InstrumentedEE10Handler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package io.dropwizard.metrics.jetty12.ee10; | ||
|
||
import com.codahale.metrics.MetricRegistry; | ||
import com.codahale.metrics.annotation.ResponseMeteredLevel; | ||
import io.dropwizard.metrics.jetty12.AbstractInstrumentedHandler; | ||
import jakarta.servlet.AsyncEvent; | ||
import jakarta.servlet.AsyncListener; | ||
import org.eclipse.jetty.ee10.servlet.AsyncContextState; | ||
import org.eclipse.jetty.ee10.servlet.ServletApiRequest; | ||
import org.eclipse.jetty.ee10.servlet.ServletApiResponse; | ||
import org.eclipse.jetty.ee10.servlet.ServletContextRequest; | ||
import org.eclipse.jetty.ee10.servlet.ServletRequestState; | ||
import org.eclipse.jetty.server.Handler; | ||
import org.eclipse.jetty.server.Request; | ||
import org.eclipse.jetty.server.Response; | ||
import org.eclipse.jetty.util.Callback; | ||
|
||
import java.io.IOException; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import static com.codahale.metrics.annotation.ResponseMeteredLevel.COARSE; | ||
|
||
/** | ||
* A Jetty {@link Handler} which records various metrics about an underlying {@link Handler} | ||
* instance. This {@link Handler} requires a {@link org.eclipse.jetty.ee10.servlet.ServletContextHandler} to be present. | ||
* For correct behaviour, the {@link org.eclipse.jetty.ee10.servlet.ServletContextHandler} should be before this handler | ||
* in the handler chain. To achieve this, one can use | ||
* {@link org.eclipse.jetty.ee10.servlet.ServletContextHandler#insertHandler(Singleton)}. | ||
*/ | ||
public class InstrumentedEE10Handler extends AbstractInstrumentedHandler { | ||
private AsyncListener listener; | ||
|
||
/** | ||
* Create a new instrumented handler using a given metrics registry. | ||
* | ||
* @param registry the registry for the metrics | ||
*/ | ||
public InstrumentedEE10Handler(MetricRegistry registry) { | ||
super(registry, null); | ||
} | ||
|
||
/** | ||
* Create a new instrumented handler using a given metrics registry. | ||
* | ||
* @param registry the registry for the metrics | ||
* @param prefix the prefix to use for the metrics names | ||
*/ | ||
public InstrumentedEE10Handler(MetricRegistry registry, String prefix) { | ||
super(registry, prefix, COARSE); | ||
} | ||
|
||
/** | ||
* Create a new instrumented handler using a given metrics registry. | ||
* | ||
* @param registry the registry for the metrics | ||
* @param prefix the prefix to use for the metrics names | ||
* @param responseMeteredLevel the level to determine individual/aggregate response codes that are instrumented | ||
*/ | ||
public InstrumentedEE10Handler(MetricRegistry registry, String prefix, ResponseMeteredLevel responseMeteredLevel) { | ||
super(registry, prefix, responseMeteredLevel); | ||
} | ||
|
||
@Override | ||
protected void doStart() throws Exception { | ||
super.doStart(); | ||
|
||
this.listener = new AsyncAttachingListener(); | ||
} | ||
|
||
@Override | ||
protected void doStop() throws Exception { | ||
super.doStop(); | ||
} | ||
|
||
@Override | ||
public boolean handle(Request request, Response response, Callback callback) throws Exception { | ||
ServletContextRequest servletContextRequest = Request.as(request, ServletContextRequest.class); | ||
|
||
// only handle servlet requests with the InstrumentedHandler | ||
// because it depends on the ServletRequestState | ||
if (servletContextRequest == null) { | ||
return super.handle(request, response, callback); | ||
} | ||
|
||
activeDispatches.inc(); | ||
|
||
final long start; | ||
final ServletRequestState state = servletContextRequest.getServletRequestState(); | ||
if (state.isInitial()) { | ||
// new request | ||
activeRequests.inc(); | ||
start = Request.getTimeStamp(request); | ||
state.addListener(listener); | ||
} else { | ||
// resumed request | ||
start = System.currentTimeMillis(); | ||
activeSuspended.dec(); | ||
if (state.getState() == ServletRequestState.State.HANDLING) { | ||
asyncDispatches.mark(); | ||
} | ||
} | ||
|
||
boolean handled = false; | ||
|
||
try { | ||
handled = super.handle(request, response, callback); | ||
} finally { | ||
final long now = System.currentTimeMillis(); | ||
final long dispatched = now - start; | ||
|
||
activeDispatches.dec(); | ||
dispatches.update(dispatched, TimeUnit.MILLISECONDS); | ||
|
||
if (state.isSuspended()) { | ||
activeSuspended.inc(); | ||
} else if (state.isInitial()) { | ||
updateResponses(request, response, start, handled); | ||
} | ||
// else onCompletion will handle it. | ||
} | ||
|
||
return handled; | ||
} | ||
|
||
private class AsyncAttachingListener implements AsyncListener { | ||
|
||
@Override | ||
public void onTimeout(AsyncEvent event) throws IOException {} | ||
|
||
@Override | ||
public void onStartAsync(AsyncEvent event) throws IOException { | ||
event.getAsyncContext().addListener(new InstrumentedAsyncListener()); | ||
} | ||
|
||
@Override | ||
public void onError(AsyncEvent event) throws IOException {} | ||
|
||
@Override | ||
public void onComplete(AsyncEvent event) throws IOException {} | ||
}; | ||
|
||
private class InstrumentedAsyncListener implements AsyncListener { | ||
private final long startTime; | ||
|
||
InstrumentedAsyncListener() { | ||
this.startTime = System.currentTimeMillis(); | ||
} | ||
|
||
@Override | ||
public void onTimeout(AsyncEvent event) throws IOException { | ||
asyncTimeouts.mark(); | ||
} | ||
|
||
@Override | ||
public void onStartAsync(AsyncEvent event) throws IOException { | ||
} | ||
|
||
@Override | ||
public void onError(AsyncEvent event) throws IOException { | ||
} | ||
|
||
@Override | ||
public void onComplete(AsyncEvent event) throws IOException { | ||
final AsyncContextState state = (AsyncContextState) event.getAsyncContext(); | ||
final ServletApiRequest request = (ServletApiRequest) state.getRequest(); | ||
final ServletApiResponse response = (ServletApiResponse) state.getResponse(); | ||
updateResponses(request.getRequest(), response.getResponse(), startTime, true); | ||
if (!state.getServletChannelState().isSuspended()) { | ||
activeSuspended.dec(); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.