Skip to content

Commit

Permalink
Merge pull request quarkus-qe#706 from michalvavrik/feature/fix-vertx…
Browse files Browse the repository at this point in the history
…webclientit-condition-assertion

Fix `VertxWebClientIT` condition assertion & correct Span operation name
  • Loading branch information
michalvavrik authored Jun 13, 2022
2 parents cfb28f5 + 4564b78 commit b669966
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,33 @@
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static io.restassured.RestAssured.given;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.Objects.requireNonNull;
import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.core.StringContains.containsString;
import static org.hamcrest.text.IsEqualIgnoringCase.equalToIgnoringCase;

import java.io.File;
import java.net.HttpURLConnection;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

import org.apache.http.HttpStatus;
import org.hamcrest.Matcher;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.github.tomakehurst.wiremock.client.WireMock;

import io.quarkus.test.bootstrap.DefaultService;
Expand All @@ -46,6 +51,7 @@ public class VertxWebClientIT {

private static final int REST_PORT = 16686;
private static final int TRACE_PORT = 14250;
private static final String TRACE_PING_PATH = "/trace/ping";

private Response resp;

Expand Down Expand Up @@ -101,38 +107,36 @@ public void getTimeoutWhenResponseItsTooSlow() {
@Test
public void endpointShouldTrace() {
final int pageLimit = 50;
final String expectedOperationName = "trace/ping";
await().atMost(1, TimeUnit.MINUTES).pollInterval(Duration.ofSeconds(1)).untilAsserted(() -> {
whenIMakePingRequest();
thenRetrieveTraces(pageLimit, "1h", getServiceName(), expectedOperationName);
thenRetrieveTraces(pageLimit, "1h", getServiceName(), TRACE_PING_PATH);
thenStatusCodeMustBe(HttpStatus.SC_OK);
thenTraceDataSizeMustBe(greaterThan(0));
thenTraceSpanSizeMustBe(greaterThan(0));
thenTraceSpanTagsSizeMustBe(greaterThan(0));
thenTraceSpansOperationNameMustBe(not(empty()));
thenCheckOperationNamesIsEqualTo(expectedOperationName);
thenCheckOperationNamesIsEqualTo(TRACE_PING_PATH);
});
}

@Test
public void httpClientShouldHaveHisOwnSpan() {
final int pageLimit = 50;
final String expectedOperationName = "trace/ping";
await().atMost(1, TimeUnit.MINUTES).pollInterval(Duration.ofSeconds(1)).untilAsserted(() -> {
whenIMakePingRequest();
thenRetrieveTraces(pageLimit, "1h", getServiceName(), expectedOperationName);
thenRetrieveTraces(pageLimit, "1h", getServiceName(), TRACE_PING_PATH);
thenStatusCodeMustBe(HttpStatus.SC_OK);
thenTraceDataSizeMustBe(greaterThan(0));
thenTraceSpanSizeMustBe(greaterThan(1));
thenTraceSpanTagsSizeMustBe(greaterThan(0));
thenTraceSpansOperationNameMustBe(not(empty()));
thenCheckOperationNamesIsEqualTo(expectedOperationName);
thenCheckOperationNamesIsEqualTo(TRACE_PING_PATH);
});
}

private void whenIMakePingRequest() {
given().when()
.get("/trace/ping")
.get(TRACE_PING_PATH)
.then()
.statusCode(HttpStatus.SC_OK).body(equalToIgnoringCase("ping-pong"));
}
Expand All @@ -142,7 +146,7 @@ private void thenRetrieveTraces(int pageLimit, String lookBack, String serviceNa
.queryParam("limit", pageLimit)
.queryParam("lookback", lookBack)
.queryParam("service", serviceName)
.queryParam("operationName", operationName)
.queryParam("operation", operationName)
.get(jaeger.getRestUrl());
}

Expand All @@ -167,8 +171,21 @@ private void thenTraceSpansOperationNameMustBe(Matcher<?> matcher) {
}

private void thenCheckOperationNamesIsEqualTo(String expectedOperationName) {
List<String> operationNames = resp.then().extract().jsonPath().getList("data.spans.operationName", String.class);
assertThat(operationNames, hasItem(containsString(expectedOperationName)));
var body = resp.then().extract().jsonPath();
IntStream
.range(0, body.getList("data").size())
.mapToObj(i -> body.getList("data[" + i + "].spans", Span.class))
.map(TreeSet::new)
.forEach(spans -> {
var prevSpan = requireNonNull(spans.pollFirst());
// assert that operation of the root span element is the expected one
Assertions.assertEquals(expectedOperationName, prevSpan.operationName);
// assert all other span elements are children (pingRequest endpoint calls pong endpoint and returns result)
for (Span span : spans) {
Assertions.assertTrue(prevSpan.hasChild(span));
prevSpan = span;
}
});
}

@Test
Expand Down Expand Up @@ -199,4 +216,48 @@ private String getServiceName() {
private WireMock wireMockClient() {
return new WireMock(wiremock.getHost().substring("http://".length()), wiremock.getPort());
}

@JsonIgnoreProperties(ignoreUnknown = true)
private static final class Span implements Comparable<Span> {

private static final String SPAN_ID = "spanID";

@JsonProperty
String operationName;

@JsonProperty
String spanID;

private String parentSpanID;

@JsonProperty("references")
void setParentSpanID(List<Map<String, Object>> references) {
// has reference to a parent element -> is not root element
if (nonNull(references) && !references.isEmpty() && nonNull(references.get(0))) {
parentSpanID = (String) references.get(0).get(SPAN_ID);
}
}

@Override
public int compareTo(Span otherSpan) {
// leaf node > branch node > root
if (isRootElement()) {
return -1;
}
if (otherSpan.isRootElement()) {
return 1;
} else {
return hasChild(otherSpan) ? -1 : 1;
}
}

boolean hasChild(Span otherSpan) {
return spanID.equals(otherSpan.parentSpanID);
}

private boolean isRootElement() {
return isNull(parentSpanID);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class OpentelemetryReactiveIT {
@Test
public void testContextPropagation() {
int pageLimit = 10;
String operationName = "ping/pong";
String operationName = "/ping/pong";
String[] operations = new String[] { "/ping/pong", "/hello", "/hello" };

await().atMost(1, TimeUnit.MINUTES).pollInterval(Duration.ofSeconds(1)).untilAsserted(() -> {
Expand All @@ -70,7 +70,7 @@ public void whenDoPingPongRequest() {

private void thenRetrieveTraces(int pageLimit, String lookBack, String serviceName, String operationName) {
resp = given().when()
.queryParam("operationName", operationName)
.queryParam("operation", operationName)
.queryParam("lookback", lookBack)
.queryParam("limit", pageLimit)
.queryParam("service", serviceName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class OpentelemetryIT {
@Test
public void testContextPropagation() {
int pageLimit = 10;
String operationName = "ping/pong";
String operationName = "/ping/pong";
String[] operations = new String[] { "/ping/pong", "/hello", "/hello" };

await().atMost(1, TimeUnit.MINUTES).pollInterval(Duration.ofSeconds(1)).untilAsserted(() -> {
Expand All @@ -70,7 +70,7 @@ public void whenDoPingPongRequest() {

private void thenRetrieveTraces(int pageLimit, String lookBack, String serviceName, String operationName) {
resp = given().when()
.queryParam("operationName", operationName)
.queryParam("operation", operationName)
.queryParam("lookback", lookBack)
.queryParam("limit", pageLimit)
.queryParam("service", serviceName)
Expand Down

0 comments on commit b669966

Please sign in to comment.