-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add some opentelemetry coverage tests (#1749)
- Loading branch information
1 parent
7b12a56
commit a1ec8a3
Showing
9 changed files
with
272 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 62 additions & 1 deletion
63
.../amqp-reactive/src/test/java/io/quarkus/ts/messaging/amqpreactive/ProdAmqpReactiveIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,81 @@ | ||
package io.quarkus.ts.messaging.amqpreactive; | ||
|
||
import static org.awaitility.Awaitility.await; | ||
import static org.hamcrest.Matchers.is; | ||
|
||
import java.time.Duration; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import org.hamcrest.Matcher; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import io.quarkus.test.bootstrap.AmqService; | ||
import io.quarkus.test.bootstrap.JaegerService; | ||
import io.quarkus.test.bootstrap.RestService; | ||
import io.quarkus.test.scenarios.QuarkusScenario; | ||
import io.quarkus.test.services.AmqContainer; | ||
import io.quarkus.test.services.JaegerContainer; | ||
import io.quarkus.test.services.QuarkusApplication; | ||
import io.quarkus.test.services.containers.model.AmqProtocol; | ||
import io.restassured.response.Response; | ||
|
||
@QuarkusScenario | ||
public class ProdAmqpReactiveIT extends BaseAmqpReactiveIT { | ||
|
||
@JaegerContainer(expectedLog = "\"Health Check state change\",\"status\":\"ready\"") | ||
static final JaegerService jaeger = new JaegerService(); | ||
|
||
@AmqContainer(image = "${amqbroker.image}", protocol = AmqProtocol.AMQP) | ||
static AmqService amq = new AmqService(); | ||
|
||
@QuarkusApplication | ||
static RestService app = new RestService() | ||
.withProperty("amqp-host", amq::getAmqpHost) | ||
.withProperty("amqp-port", () -> "" + amq.getPort()); | ||
.withProperty("amqp-port", () -> "" + amq.getPort()) | ||
.withProperty("quarkus.otel.exporter.otlp.traces.endpoint", jaeger::getCollectorUrl); | ||
|
||
private Response resp; | ||
|
||
@Test | ||
public void testContextPropagation() { | ||
int pageLimit = 10; | ||
String operationName = "GET /price"; | ||
String lookback = "1h"; | ||
String serviceName = "messaging-amqp-reactive"; | ||
await().atMost(5, TimeUnit.SECONDS).pollInterval(Duration.ofSeconds(1)).untilAsserted(() -> { | ||
thenRetrieveTraces(operationName, lookback, pageLimit, serviceName); | ||
thenTraceSpanSizeMustBe(is(1)); | ||
verifyStandardSourceCodeAttributesArePresent(operationName); | ||
|
||
}); | ||
} | ||
|
||
private void thenRetrieveTraces(String operationName, String lookback, int pageLimit, String serviceName) { | ||
resp = app.given().when() | ||
.queryParam("operation", operationName) | ||
.queryParam("lookback", lookback) | ||
.queryParam("limit", pageLimit) | ||
.queryParam("service", serviceName) | ||
.get(jaeger.getTraceUrl()) | ||
.then().log().all().extract().response(); | ||
} | ||
|
||
private void thenTraceSpanSizeMustBe(Matcher<?> matcher) { | ||
resp.then().body("data[0].spans.size()", matcher); | ||
} | ||
|
||
private void verifyStandardSourceCodeAttributesArePresent(String operationName) { | ||
verifyAttributeValue(operationName, "code.namespace", PriceResource.class.getName()); | ||
verifyAttributeValue(operationName, "code.function", "price"); | ||
} | ||
|
||
private void verifyAttributeValue(String operationName, String attributeName, String attributeValue) { | ||
resp.then().body(getGPathForOperationAndAttribute(operationName, attributeName), is(attributeValue)); | ||
} | ||
|
||
private static String getGPathForOperationAndAttribute(String operationName, String attribute) { | ||
return String.format("data[0].spans.find { it.operationName == '%s' }.tags.find { it.key == '%s' }.value", | ||
operationName, attribute); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
...ntelemetry-reactive/src/main/java/io/quarkus/ts/opentelemetry/reactive/AdminResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package io.quarkus.ts.opentelemetry.reactive; | ||
|
||
import jakarta.annotation.security.RolesAllowed; | ||
import jakarta.ws.rs.GET; | ||
import jakarta.ws.rs.Path; | ||
import jakarta.ws.rs.core.Context; | ||
import jakarta.ws.rs.core.SecurityContext; | ||
|
||
@Path("/admin") | ||
@RolesAllowed("admin") | ||
public class AdminResource { | ||
|
||
@GET | ||
public String get(@Context SecurityContext security) { | ||
return "Hello, admin " + security.getUserPrincipal().getName(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
...oring/opentelemetry/src/test/java/io/quarkus/ts/opentelemetry/DevModeOpenTelemetryIT.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package io.quarkus.ts.opentelemetry; | ||
|
||
import static io.quarkus.test.utils.AwaitilityUtils.untilAsserted; | ||
import static org.awaitility.Awaitility.await; | ||
import static org.hamcrest.Matchers.empty; | ||
import static org.hamcrest.Matchers.greaterThan; | ||
import static org.hamcrest.Matchers.is; | ||
|
||
import java.nio.file.Paths; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.function.Function; | ||
|
||
import org.apache.http.HttpStatus; | ||
import org.jboss.logging.Logger; | ||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.api.MethodOrderer; | ||
import org.junit.jupiter.api.Order; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.TestMethodOrder; | ||
|
||
import io.quarkus.test.bootstrap.DevModeQuarkusService; | ||
import io.quarkus.test.bootstrap.JaegerService; | ||
import io.quarkus.test.scenarios.QuarkusScenario; | ||
import io.quarkus.test.services.DevModeQuarkusApplication; | ||
import io.quarkus.test.services.JaegerContainer; | ||
import io.restassured.response.Response; | ||
|
||
@QuarkusScenario | ||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) | ||
public class DevModeOpenTelemetryIT { | ||
|
||
private static final Logger LOG = Logger.getLogger(DevModeOpenTelemetryIT.class); | ||
private static final String APPLICATION_PROPERTIES = Paths.get("src", "main", "resources", "application.properties") | ||
.toFile() | ||
.getPath(); | ||
private static final String TRACES_ENABLE_PROPERTY = "quarkus.otel.traces.enabled="; | ||
|
||
private static final int PAGE_LIMIT = 10; | ||
private static volatile String previousLiveReloadLogEntry = null; | ||
|
||
@JaegerContainer(expectedLog = "\"Health Check state change\",\"status\":\"ready\"") | ||
static final JaegerService jaeger = new JaegerService(); | ||
|
||
@DevModeQuarkusApplication(classes = { PingPongService.class, PingResource.class, | ||
PongResource.class }) | ||
static DevModeQuarkusService otel = (DevModeQuarkusService) new DevModeQuarkusService() | ||
.withProperty("quarkus.otel.exporter.otlp.traces.endpoint", jaeger::getCollectorUrl); | ||
|
||
@Test | ||
@Order(2) | ||
void checkTraces() { | ||
String operationName = "GET /hello"; | ||
modifyAppPropertiesAndWait(props -> props.replace(getOtelEnabledProperty(false), getOtelEnabledProperty(true))); | ||
await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { | ||
doRequest(); | ||
Response response = thenRetrieveTraces(PAGE_LIMIT, "1h", "pingpong", operationName); | ||
response.then() | ||
.body("data.size()", greaterThan(0)); | ||
}); | ||
} | ||
|
||
@Test | ||
@Order(1) | ||
void checkThereIsNoTracesAfterRestart() { | ||
String operationName = "GET /hello"; | ||
modifyAppPropertiesAndWait(props -> props.replace(getOtelEnabledProperty(true), getOtelEnabledProperty(false))); | ||
|
||
await().atMost(30, TimeUnit.SECONDS).untilAsserted(() -> { | ||
doRequest(); | ||
Response response = thenRetrieveTraces(PAGE_LIMIT, "1h", "pingpong", operationName); | ||
response.then() | ||
.body("data", empty()); | ||
}); | ||
} | ||
|
||
private Response thenRetrieveTraces(int pageLimit, String lookBack, String serviceName, String operationName) { | ||
Response response = otel.given() | ||
.when() | ||
.queryParam("operation", operationName) | ||
.queryParam("lookback", lookBack) | ||
.queryParam("limit", pageLimit) | ||
.queryParam("service", serviceName) | ||
.get(jaeger.getTraceUrl()); | ||
LOG.info("Traces --> " + response.asPrettyString()); | ||
return response; | ||
} | ||
|
||
private static void doRequest() { | ||
otel.given() | ||
.get("/hello") | ||
.then() | ||
.statusCode(HttpStatus.SC_OK) | ||
.body(is("pong")); | ||
} | ||
|
||
private static String getOtelEnabledProperty(boolean enabled) { | ||
return TRACES_ENABLE_PROPERTY + enabled; | ||
} | ||
|
||
private static void modifyAppPropertiesAndWait(Function<String, String> transformProperties) { | ||
otel.modifyFile(APPLICATION_PROPERTIES, transformProperties); | ||
untilAsserted(() -> { | ||
// just waiting won't do the trick, we need to ping Quarkus as well | ||
doRequest(); | ||
String logEntry = otel | ||
.getLogs() | ||
.stream() | ||
.filter(entry -> entry.contains("Live reload total time") | ||
&& (previousLiveReloadLogEntry == null || !previousLiveReloadLogEntry.equals(entry))) | ||
.findAny() | ||
.orElse(null); | ||
if (logEntry != null) { | ||
previousLiveReloadLogEntry = logEntry; | ||
} else { | ||
Assertions.fail(); | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters