Skip to content

Commit

Permalink
Test OpenTelemetry invocation of Camel routes from JAX-RS services
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesnetherton committed Jul 13, 2021
1 parent 5e07d0c commit 9344d52
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 44 deletions.
34 changes: 34 additions & 0 deletions integration-tests/opentelemetry/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-direct</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-opentelemetry</artifactId>
Expand All @@ -53,6 +57,10 @@
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-platform-http</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-timer</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
Expand All @@ -79,6 +87,19 @@
</dependency>

<!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory -->
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-direct-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-opentelemetry-deployment</artifactId>
Expand All @@ -105,6 +126,19 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-timer-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<profiles>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,26 @@
*/
package org.apache.camel.quarkus.component.opentelemetry.it;

import java.util.Map;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
import io.opentelemetry.sdk.trace.data.SpanData;
import org.apache.camel.ProducerTemplate;

@Path("/opentelemetry")
@ApplicationScoped
public class OpenTelemetryResource {

@Inject
InMemorySpanExporter exporter;
ProducerTemplate producerTemplate;

@Path("/spans")
@Path("/trace")
@GET
@Produces(MediaType.APPLICATION_JSON)
public JsonArray getSpans() {
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();

for (SpanData span : exporter.getFinishedSpanItems()) {

Map<AttributeKey<?>, Object> attributes = span.getAttributes().asMap();
if (attributes.containsKey(AttributeKey.stringKey("component"))) {
JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
objectBuilder.add("spanId", span.getSpanId());
objectBuilder.add("traceId", span.getTraceId());

attributes.forEach((k, v) -> objectBuilder.add(String.valueOf(k), v.toString()));

arrayBuilder.add(objectBuilder.build());
}
}

return arrayBuilder.build();
@Produces(MediaType.TEXT_PLAIN)
public String traceRoute() {
return producerTemplate.requestBody("direct:start", null, String.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,11 @@ public void configure() throws Exception {

from("platform-http:/opentelemetry/test/trace/filtered")
.setBody(constant("GET: /opentelemetry/test/trace/filtered"));

from("direct:start")
.setBody().constant("Traced direct:start");

from("timer:filtered?repeatCount=5&delay=-1")
.setBody().constant("Route filtered from tracing");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.quarkus.component.opentelemetry.it;

import java.util.Map;

import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter;
import io.opentelemetry.sdk.trace.data.SpanData;

@Path("/opentelemetry/exporter")
public class SpanExporterResource {

@Inject
InMemorySpanExporter exporter;

@Path("/spans")
@GET
@Produces(MediaType.APPLICATION_JSON)
public JsonArray getSpans() {
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();

for (SpanData span : exporter.getFinishedSpanItems()) {
if (span.getName().contains("exporter")) {
// Ignore any trace events on this resource
continue;
}

Map<AttributeKey<?>, Object> attributes = span.getAttributes().asMap();
JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
objectBuilder.add("spanId", span.getSpanId());
objectBuilder.add("traceId", span.getTraceId());
objectBuilder.add("parentId", span.getParentSpanId());

attributes.forEach((k, v) -> objectBuilder.add(String.valueOf(k), v.toString()));

arrayBuilder.add(objectBuilder.build());
}

return arrayBuilder.build();
}

@POST
@Path("/spans/reset")
public void resetSpanExporter() {
exporter.reset();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@
## limitations under the License.
## ---------------------------------------------------------------------------

quarkus.camel.opentelemetry.exclude-patterns = platform-http:/opentelemetry/test/trace/filtered
# TODO: Reinstate this when platform-http route excludes are fixed
# https://github.com/apache/camel-quarkus/issues/2897
#quarkus.camel.opentelemetry.exclude-patterns = platform-http:/opentelemetry/test/trace/filtered

quarkus.camel.opentelemetry.exclude-patterns = timer:filtered*
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,23 @@

import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import io.restassured.path.json.JsonPath;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

@QuarkusTest
class OpenTelemetryTest {

@AfterEach
public void afterEach() {
RestAssured.post("/opentelemetry/exporter/spans/reset")
.then()
.statusCode(204);
}

@Test
public void testTraceRoute() {
// Generate messages
Expand All @@ -40,21 +48,15 @@ public void testTraceRoute() {

// No spans should be recorded for this route as they are excluded by camel.opentelemetry.exclude-patterns in
// application.properties
RestAssured.get("/opentelemetry/test/trace/filtered")
.then()
.statusCode(200);
// TODO: Reinstate this when platform-http route excludes are fixed. For now, a timer endpoint stands in for filter tests
// https://github.com/apache/camel-quarkus/issues/2897
// RestAssured.get("/opentelemetry/test/trace/filtered")
// .then()
// .statusCode(200);
}

// Retrieve recorded spans
JsonPath jsonPath = RestAssured.given()
.get("/opentelemetry/spans")
.then()
.statusCode(200)
.extract()
.body()
.jsonPath();

List<Map<String, String>> spans = jsonPath.get();
List<Map<String, String>> spans = getSpans();
assertEquals(5, spans.size());

for (Map<String, String> span : spans) {
Expand All @@ -65,4 +67,28 @@ public void testTraceRoute() {
assertTrue(span.get("http.url").endsWith("/opentelemetry/test/trace/"));
}
}

@Test
public void testTracedCamelRouteInvokedFromJaxRsService() {
RestAssured.get("/opentelemetry/trace")
.then()
.statusCode(200)
.body(equalTo("Traced direct:start"));

// Verify the span hierarchy is JAX-RS Service -> Direct Endpoint
List<Map<String, String>> spans = getSpans();
assertEquals(2, spans.size());
assertEquals(spans.get(0).get("parentId"), spans.get(1).get("spanId"));
}

private List<Map<String, String>> getSpans() {
return RestAssured.given()
.get("/opentelemetry/exporter/spans")
.then()
.statusCode(200)
.extract()
.body()
.jsonPath()
.get();
}
}

0 comments on commit 9344d52

Please sign in to comment.