Skip to content

Commit 0249da7

Browse files
committed
Fix #458
1 parent 54597bc commit 0249da7

File tree

2 files changed

+79
-3
lines changed

2 files changed

+79
-3
lines changed

micrometer-core/src/main/java/io/micronaut/configuration/metrics/binder/web/ServerRequestMeterRegistryFilter.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,20 @@
1818
import io.micrometer.core.instrument.MeterRegistry;
1919
import io.micronaut.configuration.metrics.annotation.RequiresMetrics;
2020
import io.micronaut.context.annotation.Requires;
21+
import io.micronaut.http.HttpAttributes;
2122
import io.micronaut.http.HttpRequest;
2223
import io.micronaut.http.MutableHttpResponse;
2324
import io.micronaut.http.annotation.Filter;
2425
import io.micronaut.http.filter.HttpServerFilter;
2526
import io.micronaut.http.filter.ServerFilterChain;
27+
import io.micronaut.http.uri.UriMatchTemplate;
28+
import io.micronaut.web.router.UriRoute;
29+
import io.micronaut.web.router.UriRouteMatch;
2630
import org.reactivestreams.Publisher;
2731

2832
import java.util.Optional;
2933

3034
import static io.micronaut.core.util.StringUtils.FALSE;
31-
import static io.micronaut.http.HttpAttributes.URI_TEMPLATE;
3235

3336
/**
3437
* Registers the timers and meters for each request.
@@ -56,8 +59,13 @@ public ServerRequestMeterRegistryFilter(MeterRegistry meterRegistry) {
5659
}
5760

5861
private String resolvePath(HttpRequest<?> request) {
59-
Optional<String> route = request.getAttribute(URI_TEMPLATE, String.class);
60-
return route.orElseGet(request::getPath);
62+
Optional<String> routeInfo = request.getAttribute(HttpAttributes.ROUTE_INFO, UriRouteMatch.class)
63+
.map(UriRouteMatch::getRoute)
64+
.map(UriRoute::getUriMatchTemplate)
65+
.map(UriMatchTemplate::toPathString);
66+
67+
return routeInfo.orElseGet(() -> request.getAttribute(HttpAttributes.URI_TEMPLATE).map(Object::toString)
68+
.orElse(request.getUri().toString()));
6169
}
6270

6371
/**

micrometer-core/src/test/groovy/io/micronaut/configuration/metrics/binder/web/HttpMetricsSpec.groovy

+68
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
11
package io.micronaut.configuration.metrics.binder.web
22

33
import groovy.transform.InheritConstructors
4+
import io.micrometer.common.lang.NonNull
45
import io.micrometer.core.instrument.MeterRegistry
56
import io.micrometer.core.instrument.Timer
67
import io.micrometer.core.instrument.distribution.HistogramSnapshot
78
import io.micrometer.core.instrument.search.MeterNotFoundException
89
import io.micronaut.context.ApplicationContext
10+
import io.micronaut.core.util.CollectionUtils
911
import io.micronaut.http.HttpResponse
1012
import io.micronaut.http.annotation.Controller
1113
import io.micronaut.http.annotation.Error
1214
import io.micronaut.http.annotation.Get
1315
import io.micronaut.http.client.annotation.Client
1416
import io.micronaut.http.client.exceptions.HttpClientResponseException
17+
import io.micronaut.http.uri.UriBuilder
1518
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
1625
import spock.lang.Specification
1726
import spock.lang.Unroll
1827

28+
import javax.validation.constraints.NotBlank
29+
1930
import static io.micronaut.configuration.metrics.micrometer.MeterRegistryFactory.MICRONAUT_METRICS_BINDERS
2031
import static io.micronaut.configuration.metrics.micrometer.MeterRegistryFactory.MICRONAUT_METRICS_ENABLED
2132
import static io.micronaut.http.HttpStatus.CONFLICT
@@ -152,6 +163,36 @@ class HttpMetricsSpec extends Specification {
152163
(WebMetricsPublisher.ENABLED) | false
153164
}
154165

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+
155196
@Client('/')
156197
static interface TestClient {
157198
@Get
@@ -208,6 +249,33 @@ class HttpMetricsSpec extends Specification {
208249
}
209250
}
210251

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+
211279
@InheritConstructors
212280
static class MyException extends RuntimeException {
213281
}

0 commit comments

Comments
 (0)