Skip to content

Commit e6965ea

Browse files
committed
Add further integration tests for InstrumentedEE10Handler metrics
1 parent 65c242a commit e6965ea

File tree

6 files changed

+228
-39
lines changed

6 files changed

+228
-39
lines changed

metrics-jetty12-ee10/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,5 +135,11 @@
135135
<version>${slf4j.version}</version>
136136
<scope>test</scope>
137137
</dependency>
138+
<dependency>
139+
<groupId>org.awaitility</groupId>
140+
<artifactId>awaitility</artifactId>
141+
<version>${awaitility.version}</version>
142+
<scope>test</scope>
143+
</dependency>
138144
</dependencies>
139145
</project>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package io.dropwizard.metrics.jetty12.ee10;
2+
3+
import com.codahale.metrics.MetricRegistry;
4+
import org.eclipse.jetty.client.HttpClient;
5+
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
6+
import org.eclipse.jetty.server.Handler;
7+
import org.eclipse.jetty.server.Server;
8+
import org.eclipse.jetty.server.ServerConnector;
9+
import org.junit.After;
10+
import org.junit.Before;
11+
12+
import static com.codahale.metrics.annotation.ResponseMeteredLevel.ALL;
13+
14+
abstract class AbstractIntegrationTest {
15+
16+
protected final HttpClient client = new HttpClient();
17+
protected final MetricRegistry registry = new MetricRegistry();
18+
protected final Server server = new Server();
19+
protected final ServerConnector connector = new ServerConnector(server);
20+
protected final InstrumentedEE10Handler handler = new InstrumentedEE10Handler(registry, null, ALL);
21+
protected final ServletContextHandler servletContextHandler = new ServletContextHandler();
22+
23+
@Before
24+
public void setUp() throws Exception {
25+
handler.setName("handler");
26+
27+
// builds the following handler chain:
28+
// ServletContextHandler -> InstrumentedHandler -> TestHandler
29+
// the ServletContextHandler is needed to utilize servlet related classes
30+
servletContextHandler.setHandler(getHandler());
31+
servletContextHandler.insertHandler(handler);
32+
server.setHandler(servletContextHandler);
33+
34+
server.addConnector(connector);
35+
server.start();
36+
client.start();
37+
}
38+
39+
@After
40+
public void tearDown() throws Exception {
41+
server.stop();
42+
client.stop();
43+
}
44+
45+
protected String uri(String path) {
46+
return "http://localhost:" + connector.getLocalPort() + path;
47+
}
48+
49+
protected abstract Handler getHandler();
50+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package io.dropwizard.metrics.jetty12.ee10;
2+
3+
import com.codahale.metrics.Counter;
4+
import com.codahale.metrics.Meter;
5+
import com.codahale.metrics.MetricRegistry;
6+
import jakarta.servlet.AsyncContext;
7+
import jakarta.servlet.DispatcherType;
8+
import jakarta.servlet.http.HttpServletRequest;
9+
import jakarta.servlet.http.HttpServletResponse;
10+
import org.eclipse.jetty.client.CompletableResponseListener;
11+
import org.eclipse.jetty.client.ContentResponse;
12+
import org.eclipse.jetty.client.Request;
13+
import org.eclipse.jetty.client.Response;
14+
import org.eclipse.jetty.ee10.servlet.ServletHandler;
15+
import org.eclipse.jetty.server.Handler;
16+
import org.junit.Test;
17+
18+
import java.util.EnumSet;
19+
import java.util.concurrent.CompletableFuture;
20+
import java.util.concurrent.TimeUnit;
21+
22+
import static org.assertj.core.api.Assertions.assertThat;
23+
import static org.assertj.core.api.Assertions.assertThatNoException;
24+
import static org.awaitility.Awaitility.await;
25+
26+
public class AsyncTest extends AbstractIntegrationTest {
27+
28+
@Override
29+
protected Handler getHandler() {
30+
return new ServletHandler();
31+
}
32+
33+
@Test
34+
public void testAsyncTimeout() throws Exception {
35+
servletContextHandler.addFilter((request, response, chain) -> {
36+
AsyncContext asyncContext = request.startAsync();
37+
asyncContext.setTimeout(1);
38+
}, "/*", EnumSet.allOf(DispatcherType.class));
39+
40+
client.GET(uri("/"));
41+
Meter asyncTimeouts = registry.meter(MetricRegistry.name(ServletHandler.class, "handler.async-timeouts"));
42+
assertThat(asyncTimeouts.getCount()).isEqualTo(1L);
43+
44+
client.GET(uri("/"));
45+
assertThat(asyncTimeouts.getCount()).isEqualTo(2L);
46+
}
47+
48+
@Test
49+
public void testActiveSuspended() {
50+
servletContextHandler.addFilter((request, response, chain) -> {
51+
AsyncContext asyncContext = request.startAsync();
52+
asyncContext.start(() -> {
53+
try {
54+
Thread.sleep(1000);
55+
} catch (InterruptedException interruptedException) {
56+
Thread.currentThread().interrupt();
57+
}
58+
asyncContext.complete();
59+
});
60+
}, "/*", EnumSet.allOf(DispatcherType.class));
61+
62+
Counter activeSuspended = registry.counter(MetricRegistry.name(ServletHandler.class, "handler.active-suspended"));
63+
Request request = client.POST(uri("/"));
64+
CompletableResponseListener completableResponseListener = new CompletableResponseListener(request);
65+
CompletableFuture<ContentResponse> asyncResponse = completableResponseListener.send();
66+
assertThatNoException().isThrownBy(() -> {
67+
await()
68+
.atMost(750, TimeUnit.MILLISECONDS)
69+
.until(() -> activeSuspended.getCount() == 1L);
70+
asyncResponse.get();
71+
});
72+
assertThat(activeSuspended.getCount()).isEqualTo(0L);
73+
}
74+
75+
@Test
76+
public void testAsyncDispatches() throws Exception {
77+
servletContextHandler.addFilter((request, response, chain) -> {
78+
if (!(request instanceof HttpServletRequest)) {
79+
throw new IllegalStateException("Expecting ServletRequest to be an instance of HttpServletRequest");
80+
}
81+
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
82+
if ("/".equals(httpServletRequest.getRequestURI())) {
83+
AsyncContext asyncContext = request.startAsync();
84+
asyncContext.dispatch("/dispatch");
85+
return;
86+
}
87+
if ("/dispatch".equals(httpServletRequest.getRequestURI())) {
88+
AsyncContext asyncContext = request.startAsync();
89+
if (!(response instanceof HttpServletResponse)) {
90+
throw new IllegalStateException("Expecting ServletResponse to be an instance of HttpServletResponse");
91+
}
92+
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
93+
httpServletResponse.setStatus(204);
94+
asyncContext.complete();
95+
return;
96+
}
97+
throw new UnsupportedOperationException("Only '/' and '/dispatch' are valid paths");
98+
}, "/*", EnumSet.allOf(DispatcherType.class));
99+
100+
ContentResponse contentResponse = client.GET(uri("/"));
101+
assertThat(contentResponse).isNotNull().extracting(Response::getStatus).isEqualTo(204);
102+
Meter asyncDispatches = registry.meter(MetricRegistry.name(ServletHandler.class, "handler.async-dispatches"));
103+
assertThat(asyncDispatches.getCount()).isEqualTo(1L);
104+
}
105+
}

metrics-jetty12-ee10/src/test/java/io/dropwizard/metrics/jetty12/ee10/InstrumentedEE10HandlerTest.java

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,13 @@
22

33
import com.codahale.metrics.MetricRegistry;
44
import org.eclipse.jetty.client.ContentResponse;
5-
import org.eclipse.jetty.client.HttpClient;
65
import org.eclipse.jetty.ee10.servlet.DefaultServlet;
7-
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
86
import org.eclipse.jetty.ee10.servlet.ServletContextRequest;
97
import org.eclipse.jetty.ee10.servlet.ServletHandler;
8+
import org.eclipse.jetty.server.Handler;
109
import org.eclipse.jetty.server.Request;
1110
import org.eclipse.jetty.server.Response;
12-
import org.eclipse.jetty.server.Server;
13-
import org.eclipse.jetty.server.ServerConnector;
1411
import org.eclipse.jetty.util.Callback;
15-
import org.junit.After;
16-
import org.junit.Before;
1712
import org.junit.Ignore;
1813
import org.junit.Test;
1914

@@ -32,39 +27,15 @@
3227
import static org.assertj.core.api.Assertions.assertThat;
3328
import static org.assertj.core.api.Assertions.assertThatCode;
3429

35-
public class InstrumentedEE10HandlerTest {
36-
private final HttpClient client = new HttpClient();
37-
private final MetricRegistry registry = new MetricRegistry();
38-
private final Server server = new Server();
39-
private final ServerConnector connector = new ServerConnector(server);
40-
private final InstrumentedEE10Handler handler = new InstrumentedEE10Handler(registry, null, ALL);
30+
public class InstrumentedEE10HandlerTest extends AbstractIntegrationTest {
4131

42-
@Before
43-
public void setUp() throws Exception {
44-
handler.setName("handler");
45-
46-
TestHandler testHandler = new TestHandler();
32+
@Override
33+
protected Handler getHandler() {
34+
InstrumentedEE10HandlerTest.TestHandler testHandler = new InstrumentedEE10HandlerTest.TestHandler();
4735
// a servlet handler needs a servlet mapping, else the request will be short-circuited
4836
// so use the DefaultServlet here
4937
testHandler.addServletWithMapping(DefaultServlet.class, "/");
50-
51-
// builds the following handler chain:
52-
// ServletContextHandler -> InstrumentedHandler -> TestHandler
53-
// the ServletContextHandler is needed to utilize servlet related classes
54-
ServletContextHandler servletContextHandler = new ServletContextHandler();
55-
servletContextHandler.setHandler(testHandler);
56-
servletContextHandler.insertHandler(handler);
57-
server.setHandler(servletContextHandler);
58-
59-
server.addConnector(connector);
60-
server.start();
61-
client.start();
62-
}
63-
64-
@After
65-
public void tearDown() throws Exception {
66-
server.stop();
67-
client.stop();
38+
return testHandler;
6839
}
6940

7041
@Test
@@ -183,10 +154,6 @@ private void assertResponseTimesValid() {
183154
.getSnapshot().getMedian()).isGreaterThan(0.0).isLessThan(TimeUnit.SECONDS.toNanos(1));
184155
}
185156

186-
private String uri(String path) {
187-
return "http://localhost:" + connector.getLocalPort() + path;
188-
}
189-
190157
private String metricName() {
191158
return MetricRegistry.name(TestHandler.class.getName(), "handler");
192159
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package io.dropwizard.metrics.jetty12.ee10;
2+
3+
import com.codahale.metrics.Meter;
4+
import com.codahale.metrics.MetricRegistry;
5+
import org.eclipse.jetty.client.ContentResponse;
6+
import org.eclipse.jetty.client.StringRequestContent;
7+
import org.eclipse.jetty.ee10.servlet.DefaultServlet;
8+
import org.eclipse.jetty.ee10.servlet.ServletHandler;
9+
import org.eclipse.jetty.server.Handler;
10+
import org.eclipse.jetty.server.Request;
11+
import org.eclipse.jetty.server.Response;
12+
import org.eclipse.jetty.util.Callback;
13+
import org.junit.Test;
14+
15+
import java.io.BufferedReader;
16+
import java.io.InputStream;
17+
import java.io.InputStreamReader;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
21+
public class ResponseStatusTest extends AbstractIntegrationTest {
22+
23+
@Override
24+
protected Handler getHandler() {
25+
ServletHandler servletHandler = new ResponseStatusHandler();
26+
servletHandler.addServletWithMapping(DefaultServlet.class, "/");
27+
return servletHandler;
28+
}
29+
30+
@Test
31+
public void testResponseCodes() throws Exception {
32+
33+
for (int i = 2; i <= 5; i++) {
34+
String status = String.format("%d00", i);
35+
ContentResponse contentResponse = client.POST(uri("/"))
36+
.body(new StringRequestContent(status))
37+
.headers(headers -> headers.add("Content-Type", "text/plain"))
38+
.send();
39+
assertThat(contentResponse).isNotNull().satisfies(response ->
40+
assertThat(response.getStatus()).hasToString(status));
41+
42+
Meter meter = registry.meter(MetricRegistry.name(ResponseStatusHandler.class, String.format("handler.%dxx-responses", i)));
43+
assertThat(meter.getCount()).isEqualTo(1L);
44+
}
45+
}
46+
47+
private static class ResponseStatusHandler extends ServletHandler {
48+
@Override
49+
public boolean handle(Request request, Response response, Callback callback) throws Exception {
50+
try (InputStream inputStream = Request.asInputStream(request);
51+
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
52+
String status = bufferedReader.readLine();
53+
int statusCode = Integer.parseInt(status);
54+
response.setStatus(statusCode);
55+
callback.succeeded();
56+
return true;
57+
}
58+
}
59+
}
60+
}

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
<errorprone.version>2.24.1</errorprone.version>
7171
<errorprone.javac.version>9+181-r4173-1</errorprone.javac.version>
7272
<servlet6.version>6.0.0</servlet6.version>
73+
<awaitility.version>4.2.0</awaitility.version>
7374

7475
<sonar.projectKey>dropwizard_metrics</sonar.projectKey>
7576
<sonar.organization>dropwizard</sonar.organization>

0 commit comments

Comments
 (0)