in apm-agent-plugins/apm-spring-webflux/apm-spring-webflux-testapp/src/main/java/co/elastic/apm/agent/springwebflux/testapp/GreetingFunctional.java [51:112]
public RouterFunction<ServerResponse> route(GreetingHandler greetingHandler) {
return RouterFunctions.route()
// 'hello' and 'hello2' are identical, but entry point in builder is not
.route(path("/functional/hello"),
request -> helloGreeting(greetingHandler, request.queryParam("name")))
.route(path("/functional/preauthorized"),
request -> helloGreeting(greetingHandler, Optional.of("elastic")))
.route(path("/functional/username"),
request -> getUsernameFromContext(greetingHandler))
.route(path("/functional/path-username"),
request -> getUsernameFromContext(greetingHandler))
//
.GET("/functional/hello2", accept(MediaType.TEXT_PLAIN),
request -> helloGreeting(greetingHandler, request.queryParam("name")))
// nested routes
.nest(path("/functional/nested"), builder -> builder
.route(method(HttpMethod.GET), request -> nested(greetingHandler, request.methodName()))
.route(method(HttpMethod.POST), request -> nested(greetingHandler, request.methodName()))
)
// path with parameters
.route(path("/functional/with-parameters/{id}"),
request -> helloGreeting(greetingHandler, Optional.of(request.pathVariable("id"))))
// route that supports multiple methods mapping
.route(path("/functional/hello-mapping"),
request -> helloGreeting(greetingHandler, Optional.of(request.methodName())))
// errors and mono corner cases
.GET("/functional/error-handler", accept(MediaType.TEXT_PLAIN), request -> greetingHandler.throwException())
.GET("/functional/error-mono", accept(MediaType.TEXT_PLAIN), request -> greetingHandler.monoError())
.GET("/functional/empty-mono", accept(MediaType.TEXT_PLAIN), request -> greetingHandler.monoEmpty())
// with known transaction duration
.GET("/functional/duration", accept(MediaType.TEXT_PLAIN), request -> response(greetingHandler.duration(getDuration(request))))
// custom transaction name set through API
.GET("/functional/custom-transaction-name", accept(MediaType.TEXT_PLAIN), request -> {
IdImpl transactionId = null;
if (!GlobalTracer.isNoop()) {
ElasticApmTracer tracer = GlobalTracer.get().require(ElasticApmTracer.class);
TransactionImpl transaction = Objects.requireNonNull(tracer.currentTransaction(), "active transaction is required");
// This mimics setting the name through the public API. We cannot use the public API if we want to test span recycling
transaction.withName("user-provided-name", AbstractSpan.PRIORITY_USER_SUPPLIED);
transactionId = transaction.getTraceContext().getId();
}
return response(greetingHandler.helloMessage("transaction=" + transactionId));
})
.GET("/functional/child-flux", accept(MediaType.TEXT_PLAIN), request -> ServerResponse.ok()
.body(greetingHandler.childSpans(getCount(request), getDelay(request), getDuration(request)), String.class
))
.route(path("/functional/child-flux/sse"),
request -> ServerResponse.ok()
.body(greetingHandler.childSpans(getCount(request), getDelay(request), getDuration(request))
.map(greetingHandler::toSSE), ServerSentEvent.class
))
// error handler
.onError(
e -> true, (e, request) -> ServerResponse
.status(request.queryParam("status")
.map(Integer::parseInt)
.orElse(500))
.bodyValue(greetingHandler.exceptionMessage(e))
)
.build();
}