|
1 | 1 | package io.micronaut.configuration.metrics.binder.web
|
2 | 2 |
|
3 | 3 | import groovy.transform.InheritConstructors
|
| 4 | +import io.micrometer.common.lang.NonNull |
4 | 5 | import io.micrometer.core.instrument.MeterRegistry
|
5 | 6 | import io.micrometer.core.instrument.Timer
|
6 | 7 | import io.micrometer.core.instrument.distribution.HistogramSnapshot
|
7 | 8 | import io.micrometer.core.instrument.search.MeterNotFoundException
|
8 | 9 | import io.micronaut.context.ApplicationContext
|
| 10 | +import io.micronaut.core.util.CollectionUtils |
9 | 11 | import io.micronaut.http.HttpResponse
|
10 | 12 | import io.micronaut.http.annotation.Controller
|
11 | 13 | import io.micronaut.http.annotation.Error
|
12 | 14 | import io.micronaut.http.annotation.Get
|
13 | 15 | import io.micronaut.http.client.annotation.Client
|
14 | 16 | import io.micronaut.http.client.exceptions.HttpClientResponseException
|
| 17 | +import io.micronaut.http.uri.UriBuilder |
15 | 18 | import io.micronaut.runtime.server.EmbeddedServer
|
| 19 | +import io.micronaut.websocket.WebSocketBroadcaster |
| 20 | +import io.micronaut.websocket.WebSocketClient |
| 21 | +import io.micronaut.websocket.WebSocketSession |
| 22 | +import io.micronaut.websocket.annotation.* |
| 23 | +import org.reactivestreams.Publisher |
| 24 | +import reactor.core.publisher.Flux |
16 | 25 | import spock.lang.Specification
|
17 | 26 | import spock.lang.Unroll
|
18 | 27 |
|
| 28 | +import javax.validation.constraints.NotBlank |
| 29 | + |
19 | 30 | import static io.micronaut.configuration.metrics.micrometer.MeterRegistryFactory.MICRONAUT_METRICS_BINDERS
|
20 | 31 | import static io.micronaut.configuration.metrics.micrometer.MeterRegistryFactory.MICRONAUT_METRICS_ENABLED
|
21 | 32 | import static io.micronaut.http.HttpStatus.CONFLICT
|
@@ -152,6 +163,36 @@ class HttpMetricsSpec extends Specification {
|
152 | 163 | (WebMetricsPublisher.ENABLED) | false
|
153 | 164 | }
|
154 | 165 |
|
| 166 | + void "test websocket"() { |
| 167 | + when: |
| 168 | + EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer, [(MICRONAUT_METRICS_ENABLED): true]) |
| 169 | + MeterRegistry registry = embeddedServer.getApplicationContext().getBean(MeterRegistry) |
| 170 | + createWebSocketClient(embeddedServer.getApplicationContext(), embeddedServer.getPort(), "Travolta") |
| 171 | + |
| 172 | + then: |
| 173 | + registry.get(WebMetricsPublisher.METRIC_HTTP_SERVER_REQUESTS).tags('uri', '/ws/{username}').timer() |
| 174 | + } |
| 175 | + |
| 176 | + @ClientWebSocket |
| 177 | + static abstract class TestWebSocketClient implements AutoCloseable { |
| 178 | + abstract void send(@NonNull @NotBlank String message); |
| 179 | + |
| 180 | + @OnMessage |
| 181 | + void onMessage(String message) {} |
| 182 | + } |
| 183 | + |
| 184 | + |
| 185 | + private TestWebSocketClient createWebSocketClient(ApplicationContext context, int port, String username) { |
| 186 | + WebSocketClient webSocketClient = context.getBean(WebSocketClient.class) |
| 187 | + URI uri = UriBuilder.of("ws://localhost") |
| 188 | + .port(port) |
| 189 | + .path("ws") |
| 190 | + .path("{username}") |
| 191 | + .expand(CollectionUtils.mapOf("username", username)) |
| 192 | + Publisher<TestWebSocketClient> client = webSocketClient.connect(TestWebSocketClient.class, uri) |
| 193 | + return Flux.from(client).blockFirst() |
| 194 | + } |
| 195 | + |
155 | 196 | @Client('/')
|
156 | 197 | static interface TestClient {
|
157 | 198 | @Get
|
@@ -208,6 +249,33 @@ class HttpMetricsSpec extends Specification {
|
208 | 249 | }
|
209 | 250 | }
|
210 | 251 |
|
| 252 | + @ServerWebSocket("/ws/{username}") |
| 253 | + static class TestWSController { |
| 254 | + |
| 255 | + private final WebSocketBroadcaster broadcaster |
| 256 | + |
| 257 | + @OnOpen |
| 258 | + Publisher<String> onOpen(String username, WebSocketSession session) { |
| 259 | + return broadcaster.broadcast(String.format("Joined %s!", username)) |
| 260 | + } |
| 261 | + |
| 262 | + @OnMessage |
| 263 | + Publisher<String> onMessage( |
| 264 | + String username, |
| 265 | + String message, |
| 266 | + WebSocketSession session) { |
| 267 | + return broadcaster.broadcast(String.format("[%s] %s", username, message)) |
| 268 | + } |
| 269 | + |
| 270 | + @OnClose |
| 271 | + Publisher<String> onClose( |
| 272 | + String username, |
| 273 | + WebSocketSession session) { |
| 274 | + return broadcaster.broadcast(String.format("Leaving %s!", username)) |
| 275 | + } |
| 276 | + |
| 277 | + } |
| 278 | + |
211 | 279 | @InheritConstructors
|
212 | 280 | static class MyException extends RuntimeException {
|
213 | 281 | }
|
|
0 commit comments