Skip to content

Commit 8ea2b28

Browse files
authored
Merge pull request #50344 from brunobat/ws-next-onopen-test
Refactor and add test for onOpen exception on WS Next
2 parents 8f6d1c4 + 424e667 commit 8ea2b28

File tree

3 files changed

+157
-12
lines changed

3 files changed

+157
-12
lines changed

extensions/micrometer/runtime/src/main/java/io/quarkus/micrometer/runtime/binder/websockets/WebSocketMetricConstants.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ private WebSocketMetricConstants() {
1717
public static final String SERVER_CONNECTION_OPENED = "quarkus.websockets.server.connections.opened";
1818

1919
/**
20-
* Counts number of times that opening of a WebSocket server connection resulted in error.
20+
* Counts number of times that opening of a WebSocket server connection resulted in error, therefore closing the connection.
2121
*/
2222
public static final String SERVER_CONNECTION_ON_OPEN_ERROR = "quarkus.websockets.server.connections.onopen.errors";
2323

2424
/**
25-
* Counts number of times that opening of a WebSocket client connection resulted in error.
25+
* Counts number of times that opening of a WebSocket client connection resulted in error, therefore closing the connection.
2626
*/
27-
public static final String CLIENT_CONNECTION_OPENED_ERROR = "quarkus.websockets.client.connections.opened.errors";
27+
public static final String CLIENT_CONNECTION_ON_OPEN_ERROR = "quarkus.websockets.client.connections.onopen.errors";
2828

2929
/**
3030
* Counts all the WebSockets client closed connections.

extensions/micrometer/runtime/src/main/java/io/quarkus/micrometer/runtime/binder/websockets/WebSocketMetricsInterceptorProducerImpl.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ public WebSocketMetricsInterceptor createServerMetricsInterceptor() {
4343
.builder(WebSocketMetricConstants.SERVER_CONNECTION_OPENED)
4444
.description("Number of opened server connections.")
4545
.withRegistry(meterRegistry);
46-
final Meter.MeterProvider<Counter> connectionOpeningFailedCounter = Counter
46+
final Meter.MeterProvider<Counter> connectionOnOpenErrorsCounter = Counter
4747
.builder(WebSocketMetricConstants.SERVER_CONNECTION_ON_OPEN_ERROR)
4848
.description("Number of failures occurred when opening server connection failed.")
4949
.withRegistry(meterRegistry);
5050
return new WebSocketMetricsInterceptorImpl(messagesCounter, bytesCounter, closedConnectionCounter, serverErrorsCounter,
51-
connectionOpenCounter, connectionOpeningFailedCounter);
51+
connectionOpenCounter, connectionOnOpenErrorsCounter);
5252
}
5353

5454
@Override
@@ -73,12 +73,12 @@ public WebSocketMetricsInterceptor createClientMetricsInterceptor() {
7373
.builder(WebSocketMetricConstants.CLIENT_CONNECTION_OPENED)
7474
.description("Number of opened client connections.")
7575
.withRegistry(meterRegistry);
76-
final Meter.MeterProvider<Counter> connectionOpeningFailedCounter = Counter
77-
.builder(WebSocketMetricConstants.CLIENT_CONNECTION_OPENED_ERROR)
76+
final Meter.MeterProvider<Counter> connectionOnOpenErrorsCounter = Counter
77+
.builder(WebSocketMetricConstants.CLIENT_CONNECTION_ON_OPEN_ERROR)
7878
.description("Number of failures occurred when opening client connection failed.")
7979
.withRegistry(meterRegistry);
8080
return new WebSocketMetricsInterceptorImpl(messagesCounter, bytesCounter, closedConnectionCounter, clientErrorsCounter,
81-
connectionOpenCounter, connectionOpeningFailedCounter);
81+
connectionOpenCounter, connectionOnOpenErrorsCounter);
8282
}
8383

8484
private static final class WebSocketMetricsInterceptorImpl implements WebSocketMetricsInterceptor {
@@ -88,18 +88,18 @@ private static final class WebSocketMetricsInterceptorImpl implements WebSocketM
8888
private final Meter.MeterProvider<Counter> closedConnectionCounter;
8989
private final Meter.MeterProvider<Counter> errorsCounter;
9090
private final Meter.MeterProvider<Counter> connectionOpenCounter;
91-
private final Meter.MeterProvider<Counter> connectionOpeningFailedCounter;
91+
private final Meter.MeterProvider<Counter> connectionOnOpenErrorsCounter;
9292

9393
private WebSocketMetricsInterceptorImpl(Meter.MeterProvider<Counter> messagesCounter,
9494
Meter.MeterProvider<Counter> bytesCounter, Meter.MeterProvider<Counter> closedConnectionCounter,
9595
Meter.MeterProvider<Counter> errorsCounter, Meter.MeterProvider<Counter> connectionOpenCounter,
96-
Meter.MeterProvider<Counter> connectionOpeningFailedCounter) {
96+
Meter.MeterProvider<Counter> connectionOnOpenErrorsCounter) {
9797
this.messagesCounter = messagesCounter;
9898
this.bytesCounter = bytesCounter;
9999
this.closedConnectionCounter = closedConnectionCounter;
100100
this.errorsCounter = errorsCounter;
101101
this.connectionOpenCounter = connectionOpenCounter;
102-
this.connectionOpeningFailedCounter = connectionOpeningFailedCounter;
102+
this.connectionOnOpenErrorsCounter = connectionOnOpenErrorsCounter;
103103
}
104104

105105
@Override
@@ -126,7 +126,7 @@ public void onConnectionOpened(String route) {
126126

127127
@Override
128128
public void onConnectionOpeningFailed(String route) {
129-
connectionOpeningFailedCounter.withTag(URI_TAG_KEY, route).increment();
129+
connectionOnOpenErrorsCounter.withTag(URI_TAG_KEY, route).increment();
130130
}
131131

132132
@Override
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package io.quarkus.websockets.next.test.telemetry;
2+
3+
import static io.quarkus.websockets.next.test.telemetry.MetricsAsserter.assertServerConnectionClosedTotal;
4+
import static io.quarkus.websockets.next.test.telemetry.MetricsAsserter.assertServerConnectionOpenedTotal;
5+
import static io.quarkus.websockets.next.test.telemetry.MetricsAsserter.assertServerConnectionOpeningFailedTotal;
6+
import static io.quarkus.websockets.next.test.telemetry.MetricsAsserter.assertServerErrorTotal;
7+
import static org.junit.jupiter.api.Assertions.assertFalse;
8+
import static org.junit.jupiter.api.Assertions.assertTrue;
9+
10+
import java.net.URI;
11+
import java.time.Duration;
12+
import java.util.List;
13+
14+
import jakarta.inject.Inject;
15+
16+
import org.awaitility.Awaitility;
17+
import org.jboss.shrinkwrap.api.asset.StringAsset;
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.extension.RegisterExtension;
20+
21+
import io.quarkus.builder.Version;
22+
import io.quarkus.logging.Log;
23+
import io.quarkus.maven.dependency.Dependency;
24+
import io.quarkus.test.QuarkusUnitTest;
25+
import io.quarkus.test.common.http.TestHTTPResource;
26+
import io.quarkus.websockets.next.OnError;
27+
import io.quarkus.websockets.next.OnOpen;
28+
import io.quarkus.websockets.next.WebSocket;
29+
import io.quarkus.websockets.next.WebSocketClient;
30+
import io.quarkus.websockets.next.WebSocketClientConnection;
31+
import io.quarkus.websockets.next.WebSocketConnector;
32+
import io.restassured.RestAssured;
33+
import io.restassured.response.ValidatableResponse;
34+
35+
public class MicrometerWebSocketsStandaloneTest {
36+
37+
@RegisterExtension
38+
public static final QuarkusUnitTest test = new QuarkusUnitTest()
39+
.withApplicationRoot(root -> root
40+
.addClasses(MetricsAsserter.class)
41+
.addAsResource(new StringAsset("""
42+
bounce-endpoint.prefix-responses=true
43+
quarkus.websockets-next.server.metrics.enabled=true
44+
quarkus.websockets-next.client.metrics.enabled=true
45+
"""), "application.properties"))
46+
.setForcedDependencies(
47+
List.of(Dependency.of("io.quarkus", "quarkus-micrometer-registry-prometheus-deployment",
48+
Version.getVersion())));
49+
50+
@Inject
51+
WebSocketConnector<ErroneousClient_OnConnectError> onConnectErrorClient;
52+
53+
@Inject
54+
WebSocketConnector<ErroneousClient_OnConnectErrorHandler> onConnectErrorHandlerClient;
55+
56+
@TestHTTPResource("/")
57+
URI baseUri;
58+
59+
static ValidatableResponse getMetrics() {
60+
return RestAssured.given().get("/q/metrics").then().statusCode(200);
61+
}
62+
63+
@Test
64+
public void testServerEndpoint_OnConnectionError() {
65+
WebSocketClientConnection connection = onConnectErrorClient.baseUri(baseUri).connectAndAwait();
66+
Awaitility.await().atMost(Duration.ofSeconds(2)).untilAsserted(() -> {
67+
// Connection closing is async and takes some time
68+
assertFalse(connection.isOpen(),
69+
"Runtime exception happened on server side and connection is still open");
70+
});
71+
72+
Awaitility.await().atMost(Duration.ofSeconds(5)).untilAsserted(() -> {
73+
getMetrics()
74+
.body(assertServerConnectionOpeningFailedTotal("/on-connect-error", 1))
75+
.body(assertServerErrorTotal("/on-connect-error", 1))
76+
.body(assertServerConnectionOpenedTotal("/on-connect-error", 1))
77+
.body(assertServerConnectionClosedTotal("/on-connect-error", 1));
78+
});
79+
}
80+
81+
@Test
82+
public void testServerEndpoint_OnConnectionErrorHandler() {
83+
WebSocketClientConnection connection = onConnectErrorHandlerClient.baseUri(baseUri).connectAndAwait();
84+
Awaitility.await().atMost(Duration.ofSeconds(2)).untilAsserted(() -> {
85+
// Connection closing will never close because there is an OnError handler.
86+
assertTrue(connection.isOpen(), "Should never close");
87+
});
88+
89+
Awaitility.await().atMost(Duration.ofSeconds(5)).untilAsserted(() -> {
90+
getMetrics()
91+
.body(assertServerConnectionOpeningFailedTotal("/with-on-connect-error-handler", 0))
92+
.body(assertServerErrorTotal("/with-on-connect-error-handler", 1))
93+
.body(assertServerConnectionOpenedTotal("/with-on-connect-error-handler", 1))
94+
.body(assertServerConnectionClosedTotal("/with-on-connect-error-handler", 0));
95+
96+
});
97+
}
98+
99+
// ----------------------- SERVERS -------------------------------
100+
101+
@WebSocket(path = "/on-connect-error")
102+
public static class OnConnectErrorEndpoint {
103+
104+
@OnOpen()
105+
public void onOpen() {
106+
Log.info("onOpen throwing exception");
107+
throw new RuntimeException("Crafted exception - Websocket failed to open");
108+
}
109+
}
110+
111+
@WebSocket(path = "/with-on-connect-error-handler")
112+
public static class OnConnectErrorHandlerEndpoint {
113+
114+
@OnOpen()
115+
public void onOpen() {
116+
Log.info("onOpen throwing exception");
117+
throw new RuntimeException("Crafted exception - Websocket failed to open");
118+
}
119+
120+
@OnError
121+
public void onError(Exception failure) {
122+
Log.warnv("Error handled: {0}", failure.getMessage());
123+
}
124+
}
125+
126+
// ------------------------- CLIENTS -------------------------------
127+
128+
@WebSocketClient(path = "/on-connect-error")
129+
public static class ErroneousClient_OnConnectError {
130+
131+
@OnOpen()
132+
public void onOpen() {
133+
Log.info("client onOpen");
134+
}
135+
}
136+
137+
@WebSocketClient(path = "/with-on-connect-error-handler")
138+
public static class ErroneousClient_OnConnectErrorHandler {
139+
140+
@OnOpen()
141+
public void onOpen() {
142+
Log.info("client onOpen");
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)