Skip to content

Commit

Permalink
Fix: Ensuring that the name generated in opentelemetry matches the en…
Browse files Browse the repository at this point in the history
…dpoint being called

Replacing the deprecated combinedWith

Importing specific method instead of using *

Organizing imports
  • Loading branch information
jcuero committed Nov 18, 2024
1 parent 19ee291 commit e3dda7e
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import io.smallrye.common.vertx.VertxContext;
import io.smallrye.stork.api.ServiceInstance;
import io.vertx.core.Context;
import io.vertx.core.Vertx;

public class ClientRequestContextImpl implements ResteasyReactiveClientRequestContext {

Expand All @@ -63,16 +62,10 @@ public ClientRequestContextImpl(RestClientRequestContext restClientRequestContex
this.headersMap = new ClientRequestHeadersMap(); //restClientRequestContext.requestHeaders.getHeaders()
this.providers = new ProvidersImpl(restClientRequestContext);

// TODO This needs to be challenged:
// Always create a duplicated context because each REST Client invocation must have its own context
// A separate context allows integrations like OTel to create a separate Span for each invocation (expected)
Context ctxt = Vertx.currentContext();
if (ctxt != null && VertxContext.isDuplicatedContext(ctxt)) {
this.context = ctxt;
} else {
Context current = client.vertx.getOrCreateContext();
this.context = VertxContext.createNewDuplicatedContext(current);
}
Context current = client.vertx.getOrCreateContext();
this.context = VertxContext.createNewDuplicatedContext(current);
restClientRequestContext.properties.put(VERTX_CONTEXT_PROPERTY, context);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,27 @@ public HandlerChain(boolean captureStacktrace, int maxChunkSize, boolean followR
this.clientErrorHandler = new ClientErrorHandler(loggingScope);
}

private HandlerChain(ClientRestHandler clientCaptureCurrentContextRestHandler,
ClientRestHandler clientSwitchToRequestContextRestHandler, ClientRestHandler clientSendHandler,
ClientRestHandler clientSetResponseEntityRestHandler, ClientRestHandler clientResponseCompleteRestHandler,
ClientRestHandler clientErrorHandler) {
this.clientCaptureCurrentContextRestHandler = clientCaptureCurrentContextRestHandler;
this.clientSwitchToRequestContextRestHandler = clientSwitchToRequestContextRestHandler;
this.clientSendHandler = clientSendHandler;
this.clientSetResponseEntityRestHandler = clientSetResponseEntityRestHandler;
this.clientResponseCompleteRestHandler = clientResponseCompleteRestHandler;
this.clientErrorHandler = clientErrorHandler;
}

private HandlerChain newInstance() {
return new HandlerChain(clientCaptureCurrentContextRestHandler, clientSwitchToRequestContextRestHandler,
clientSendHandler, clientSetResponseEntityRestHandler, clientResponseCompleteRestHandler, clientErrorHandler);
}

HandlerChain setPreClientSendHandler(ClientRestHandler preClientSendHandler) {
this.preClientSendHandler = preClientSendHandler;
return this;
HandlerChain newHandlerChain = newInstance();
newHandlerChain.preClientSendHandler = preClientSendHandler;
return newHandlerChain;
}

ClientRestHandler[] createHandlerChain(ConfigurationImpl configuration) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jboss.resteasy.reactive.client.impl;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.Collections;
Expand All @@ -20,11 +21,12 @@ public class HandlerChainTest {
@Test
public void preSendHandlerIsAlwaysFirst() throws Exception {

var chain = new HandlerChain(false, 8096, true, LoggingScope.NONE, Collections.emptyMap(), new DefaultClientLogger());
var initialChain = new HandlerChain(false, 8096, true, LoggingScope.NONE, Collections.emptyMap(),
new DefaultClientLogger());

ClientRestHandler preHandler = ctx -> {
};
chain.setPreClientSendHandler(preHandler);
HandlerChain chain = initialChain.setPreClientSendHandler(preHandler);

var config = new ConfigurationImpl(RuntimeType.CLIENT);
ClientRequestFilter testReqFilter = ctx -> {
Expand All @@ -41,6 +43,9 @@ public void preSendHandlerIsAlwaysFirst() throws Exception {

// Ensure pre-send is the very first
assertEquals(handlers[0], preHandler);

// Ensure a chain is created when a pre-send handler is set
assertNotSame(initialChain, chain);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ public Uni<String> helloMultipleUsingCombine() {
.combinedWith((s, s2) -> s + " and " + s2);
}

@GET
@Path("/multiple-combine-different-paths")
public Uni<String> helloMultipleUsingCombineDifferentPaths() {
return Uni.combine().all().unis(
client.helloGetUniDelay(),
client.helloGet("Naruto"),
client.helloGet("Goku"),
client.helloGetUniExecutor())
.with((s, s2, s3, s4) -> s + " and " + s2 + " and " + s3 + " and " + s4);
}

@POST
public Uni<String> helloPost(String body) {
Span span = tracer.spanBuilder("helloPost").startSpan();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,12 @@ interface ReactiveRestClient {

@POST
Uni<String> helloPost(String body);

@GET
@Path("/hello-get-uni-executor")
Uni<String> helloGetUniExecutor();

@GET
@Path("/hello-get-uni-delay")
Uni<String> helloGetUniDelay();
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,92 @@ void multipleUsingCombine() {
assertEquals("helloGet", gokuInternal.get("name"));
}

@Test
void multipleUsingCombineDifferentPaths() {
given()
.when()
.get("/reactive/multiple-combine-different-paths")
.then()
.statusCode(200)
.body(equalTo("helloGetUniDelay and Hello Naruto and Hello Goku and helloGetUniExecutor"));

await().atMost(5, SECONDS).until(() -> getSpans().size() == 13);

List<Map<String, Object>> spans = getSpans();
assertEquals(13, spans.size());
assertEquals(1, spans.stream().map(map -> map.get("traceId")).collect(toSet()).size());

// First span is the call getting into the server. It does not have a parent span.
Map<String, Object> parent = getSpanByKindAndParentId(spans, SERVER, "0000000000000000");

// We should get 2 client spans originated by the server
List<Map<String, Object>> clientSpans = getSpansByKindAndParentId(spans, CLIENT, parent.get("spanId"));
assertEquals(4, clientSpans.size());

// Each client calls the server and programmatically create a span, so each have a server and an internal span

// helloGetUniDelay Span
Optional<Map<String, Object>> helloGetUniDelaySpan = clientSpans.stream()
.filter(map -> ((String) ((Map<?, ?>) map.get("attributes")).get(URL_FULL.getKey()))
.contains("/hello-get-uni-delay"))
.findFirst();
assertTrue(helloGetUniDelaySpan.isPresent());
Map<String, Object> helloGetUniDelay = helloGetUniDelaySpan.get();
assertEquals("GET /reactive/hello-get-uni-delay", helloGetUniDelay.get("name"));

Map<String, Object> helloGetUniDelayServer = getSpanByKindAndParentId(spans, SERVER, helloGetUniDelay.get("spanId"));
assertEquals("/reactive/hello-get-uni-delay",
((Map<?, ?>) helloGetUniDelayServer.get("attributes")).get(URL_PATH.getKey()));
Map<String, Object> helloGetUniDelayInternal = getSpanByKindAndParentId(spans, INTERNAL,
helloGetUniDelayServer.get("spanId"));
assertEquals("helloGetUniDelay", helloGetUniDelayInternal.get("name"));

// Naruto Span
Optional<Map<String, Object>> narutoSpan = clientSpans.stream()
.filter(map -> ((String) ((Map<?, ?>) map.get("attributes")).get(URL_FULL.getKey())).contains("Naruto"))
.findFirst();
assertTrue(narutoSpan.isPresent());
Map<String, Object> naruto = narutoSpan.get();
assertEquals("GET /reactive", naruto.get("name"));

Map<String, Object> narutoServer = getSpanByKindAndParentId(spans, SERVER, naruto.get("spanId"));
assertEquals("/reactive", ((Map<?, ?>) narutoServer.get("attributes")).get(URL_PATH.getKey()));
assertEquals("name=Naruto", ((Map<?, ?>) narutoServer.get("attributes")).get(URL_QUERY.getKey()));
Map<String, Object> narutoInternal = getSpanByKindAndParentId(spans, INTERNAL, narutoServer.get("spanId"));
assertEquals("helloGet", narutoInternal.get("name"));

// Goku Span
Optional<Map<String, Object>> gokuSpan = clientSpans.stream()
.filter(map -> ((String) ((Map<?, ?>) map.get("attributes")).get(URL_FULL.getKey())).contains("Goku"))
.findFirst();
assertTrue(gokuSpan.isPresent());
Map<String, Object> goku = gokuSpan.get();
assertEquals("GET /reactive", goku.get("name"));

Map<String, Object> gokuServer = getSpanByKindAndParentId(spans, SERVER, goku.get("spanId"));
assertEquals("/reactive", ((Map<?, ?>) gokuServer.get("attributes")).get(URL_PATH.getKey()));
assertEquals("name=Goku", ((Map<?, ?>) gokuServer.get("attributes")).get(URL_QUERY.getKey()));
Map<String, Object> gokuInternal = getSpanByKindAndParentId(spans, INTERNAL, gokuServer.get("spanId"));
assertEquals("helloGet", gokuInternal.get("name"));

// helloGetUniDelay Span
Optional<Map<String, Object>> helloGetUniExecutorSpan = clientSpans.stream()
.filter(map -> ((String) ((Map<?, ?>) map.get("attributes")).get(URL_FULL.getKey()))
.contains("/hello-get-uni-executor"))
.findFirst();
assertTrue(helloGetUniExecutorSpan.isPresent());
Map<String, Object> helloGetUniExecutor = helloGetUniExecutorSpan.get();
assertEquals("GET /reactive/hello-get-uni-executor", helloGetUniExecutor.get("name"));

Map<String, Object> helloGetUniExecutorServer = getSpanByKindAndParentId(spans, SERVER,
helloGetUniExecutor.get("spanId"));
assertEquals("/reactive/hello-get-uni-executor",
((Map<?, ?>) helloGetUniExecutorServer.get("attributes")).get(URL_PATH.getKey()));
Map<String, Object> helloGetUniExecutorInternal = getSpanByKindAndParentId(spans, INTERNAL,
helloGetUniExecutorServer.get("spanId"));
assertEquals("helloGetUniExecutor", helloGetUniExecutorInternal.get("name"));
}

@Test
public void securedInvalidCredential() {
given().auth().preemptive().basic("scott", "reader2").when().get("/foo/secured/item/something")
Expand Down

0 comments on commit e3dda7e

Please sign in to comment.