Skip to content

Commit

Permalink
Fix RESTEasy classic server templating for observability
Browse files Browse the repository at this point in the history
- Fixes quarkusio#18251
- Add test to Micrometer integration test. Verified not a problem with RESTEasy Reactive
- Add test to OpenTelemetry integration test to very fix for RESTEasy Classic
  • Loading branch information
kenfinnigan committed Sep 3, 2021
1 parent 849b988 commit d57ddba
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.resteasy.deployment;

import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

Expand All @@ -18,6 +19,7 @@
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
import io.quarkus.resteasy.common.spi.ResteasyDotNames;
import io.quarkus.resteasy.runtime.QuarkusRestPathTemplate;
import io.quarkus.resteasy.runtime.QuarkusRestPathTemplateInterceptor;
import io.quarkus.resteasy.server.common.spi.ResteasyJaxrsConfigBuildItem;
Expand Down Expand Up @@ -81,14 +83,22 @@ public void transform(TransformationContext ctx) {

AnnotationInstance annotation = methodInfo.annotation(REST_PATH);
if (annotation == null) {
return;
// Check for @Path on class and not method
if (!isRestEndpointMethod(methodInfo.annotations())) {
return;
}
}
// Don't create annotations for rest clients
if (classInfo.classAnnotation(REGISTER_REST_CLIENT) != null) {
return;
}

StringBuilder stringBuilder = new StringBuilder(slashify(annotation.value().asString()));
StringBuilder stringBuilder;
if (annotation != null) {
stringBuilder = new StringBuilder(slashify(annotation.value().asString()));
} else {
stringBuilder = new StringBuilder();
}

// Look for @Path annotation on the class
annotation = classInfo.classAnnotation(REST_PATH);
Expand Down Expand Up @@ -128,6 +138,19 @@ String slashify(String path) {
return '/' + path;
}

boolean isRestEndpointMethod(List<AnnotationInstance> annotations) {
boolean isRestEndpointMethod = false;

for (AnnotationInstance annotation : annotations) {
if (ResteasyDotNames.JAXRS_METHOD_ANNOTATIONS.contains(annotation.name())) {
isRestEndpointMethod = true;
break;
}
}

return isRestEndpointMethod;
}

private boolean notRequired(Capabilities capabilities,
Optional<MetricsCapabilityBuildItem> metricsCapability) {
return capabilities.isMissing(Capability.RESTEASY) ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.it.micrometer.prometheus;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("template/path/{value}")
public class PathTemplateResource {
@GET
public String get(@PathParam("value") String value) {
return "Received: " + value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ void testAllTheThings() {
.body(containsString("OK"));
}

@Test
@Order(9)
void testTemplatedPathOnClass() {
when().get("/template/path/anything").then().statusCode(200)
.body(containsString("Received: anything"));
}

@Test
@Order(10)
void testPrometheusScrapeEndpoint() {
Expand All @@ -103,6 +110,9 @@ void testPrometheusScrapeEndpoint() {
.body(containsString("uri=\"/message/match/{id}/{sub}\""))
.body(containsString("uri=\"/message/match/{other}\""))

.body(containsString(
"http_server_requests_seconds_count{env=\"test\",method=\"GET\",outcome=\"SUCCESS\",registry=\"prometheus\",status=\"200\",uri=\"/template/path/{value}\""))

// Verify Hibernate Metrics
.body(containsString(
"hibernate_sessions_open_total{entityManagerFactory=\"<default>\",env=\"test\",registry=\"prometheus\",} 2.0"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.it.opentelemetry;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("template/path/{value}")
public class PathTemplateResource {
@GET
public String get(@PathParam("value") String value) {
return "Received: " + value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,43 @@ void testAsyncClientTracing() {
Assertions.assertTrue(clientServerFound);
}

@Test
void testTemplatedPathOnClass() {
resetExporter();

given()
.contentType("application/json")
.when().get("/template/path/something")
.then()
.statusCode(200)
.body(containsString("Received: something"));

Awaitility.await().atMost(Duration.ofMinutes(2)).until(() -> getSpans().size() == 1);
Map<String, Object> spanData = getSpans().get(0);
Assertions.assertNotNull(spanData);
Assertions.assertNotNull(spanData.get("spanId"));

verifyResource(spanData);

Assertions.assertEquals("template/path/{value}", spanData.get("name"));
Assertions.assertEquals(SpanKind.SERVER.toString(), spanData.get("kind"));
Assertions.assertTrue((Boolean) spanData.get("ended"));

Assertions.assertEquals(SpanId.getInvalid(), spanData.get("parent_spanId"));
Assertions.assertEquals(TraceId.getInvalid(), spanData.get("parent_traceId"));
Assertions.assertFalse((Boolean) spanData.get("parent_valid"));
Assertions.assertFalse((Boolean) spanData.get("parent_remote"));

Assertions.assertEquals("GET", spanData.get("attr_http.method"));
Assertions.assertEquals("1.1", spanData.get("attr_http.flavor"));
Assertions.assertEquals("/template/path/something", spanData.get("attr_http.target"));
Assertions.assertEquals(directUrl.getAuthority(), spanData.get("attr_http.host"));
Assertions.assertEquals("http", spanData.get("attr_http.scheme"));
Assertions.assertEquals("200", spanData.get("attr_http.status_code"));
Assertions.assertNotNull(spanData.get("attr_http.client_ip"));
Assertions.assertNotNull(spanData.get("attr_http.user_agent"));
}

private void verifyResource(Map<String, Object> spanData) {
Assertions.assertEquals("opentelemetry-integration-test", spanData.get("resource_service.name"));
Assertions.assertEquals("999-SNAPSHOT", spanData.get("resource_service.version"));
Expand Down

0 comments on commit d57ddba

Please sign in to comment.