Skip to content

Commit

Permalink
Merge pull request quarkusio#36476 from hiteshkhatri97/add-new-sample…
Browse files Browse the repository at this point in the history
…r-jaeger-remote

Support for jaeger remote sampler
  • Loading branch information
brunobat authored Oct 27, 2023
2 parents 02fe185 + c57586f commit bbdc2ae
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void config() {
assertEquals(TRUE, oTelRuntimeConfig.traces().includeStaticResources());
assertEquals("always_off", oTelBuildConfig.traces().sampler());
assertTrue(oTelRuntimeConfig.traces().samplerArg().isPresent());
assertEquals(2.0d, oTelRuntimeConfig.traces().samplerArg().get());
assertEquals("2.0d", oTelRuntimeConfig.traces().samplerArg().get());
assertEquals(FALSE, otlpExporterBuildConfig.enabled());
assertTrue(otlpExporterRuntimeConfig.traces().legacyEndpoint().isPresent());
assertTrue(otlpExporterRuntimeConfig.traces().headers().isPresent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,16 @@ public interface TracesRuntimeConfig {
Boolean includeStaticResources();

/**
* An argument to the configured tracer if supported, for example a ratio.
* Sampler argument. Depends on the `quarkus.otel.traces.sampler` property.
* Fallbacks to the legacy property <code>quarkus.opentelemetry.tracer.sampler.ratio</code>.
* <p>
* Fallbacks to the legacy property <code>quarkus.opentelemetry.tracer.sampler.ratio</code>
* or defaults to `1.0`.
* When setting the stock sampler to `traceidratio` or `parentbased_traceidratio` you need to set a `double` compatible
* value between `0.0d` and `1.0d`, like `0.01d` or `0.5d`. It is kept as a `String` to allow the flexible customisation of
* alternative samplers.
* <p>
* Defaults to `1.0d`.
*/
@WithName("sampler.arg")
@WithDefault("1.0d")
Optional<Double> samplerArg();
Optional<String> samplerArg();
}
173 changes: 173 additions & 0 deletions integration-tests/opentelemetry-jaeger-remote/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-integration-tests-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>quarkus-integration-test-opentelemetry-jaeger-remote</artifactId>
<name>Quarkus - Integration Tests - Opentelemetry - Jaeger - Remote</name>

<properties>
<javax-ws-rs-api.version>2.1.1</javax-ws-rs-api.version>
</properties>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-opentelemetry</artifactId>
</dependency>

<!-- JAX-RS -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>

<!-- Verify that the client can co-exist with the server -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-reactive-jackson</artifactId>
</dependency>

<!-- Test Dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.activation</groupId>
<artifactId>jakarta.activation</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-zerodep</artifactId>
<scope>test</scope>
</dependency>
<!-- Minimal test dependencies to *-deployment artifacts for consistent build order -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-opentelemetry-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-client-reactive-jackson-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-jaeger-remote-sampler</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-jaeger</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>native-image</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
</profiles>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSamplerProvider
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.opentelemetry.exporter.jaeger.internal.JaegerGrpcSpanExporterProvider
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Setting these for tests explicitly. Not required in normal application
quarkus.application.name=opentelemetry-integration-test-jeager-remote
quarkus.application.version=999-SNAPSHOT

quarkus.otel.traces.sampler=jaeger_remote
quarkus.otel.traces.sampler.arg=endpoint=http://localhost:14250,pollingInterval=5000,initialSamplingRate=1.0
quarkus.otel.traces.exporter=jaeger
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.quarkus.it.opentelemetry.jaeger;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
public class OTelJaegerRemoteIT extends OTelJaegerRemoteTest {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package io.quarkus.it.opentelemetry.jaeger;

import static com.github.dockerjava.api.model.HostConfig.newHostConfig;
import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.time.Duration;

import jakarta.inject.Inject;

import org.awaitility.Awaitility;
import org.eclipse.microprofile.config.ConfigProvider;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.model.ExposedPort;
import com.github.dockerjava.api.model.Ports;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.transport.DockerHttpClient;
import com.github.dockerjava.zerodep.ZerodepDockerHttpClient;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.path.json.JsonPath;

@QuarkusTest
public class OTelJaegerRemoteTest {

private static final int QUERY_PORT = 16686;
private static final int COLLECTOR_PORT = 14250;
private static final int HEALTH_PORT = 14269;
private static final String JAEGER_URL = "http://localhost";
private static final DockerClient dockerClient;
@Inject
OpenTelemetry openTelemetry;

static {
DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder().build();
DockerHttpClient httpClient = new ZerodepDockerHttpClient.Builder()
.dockerHost(config.getDockerHost())
.sslConfig(config.getSSLConfig())
.build();
dockerClient = DockerClientImpl.getInstance(config, httpClient);
if (dockerClient.listContainersCmd().exec().stream()
.noneMatch(container -> container.getNames()[0].equals("/jaeger"))) {
ExposedPort queryPort = ExposedPort.tcp(QUERY_PORT);
ExposedPort collectorPort = ExposedPort.tcp(COLLECTOR_PORT);
ExposedPort hostPort = ExposedPort.tcp(HEALTH_PORT);
Ports portBindings = new Ports();
portBindings.bind(queryPort, Ports.Binding.bindPort(QUERY_PORT));
portBindings.bind(collectorPort, Ports.Binding.bindPort(COLLECTOR_PORT));
portBindings.bind(hostPort, Ports.Binding.bindPort(HEALTH_PORT));
CreateContainerResponse container = dockerClient
.createContainerCmd("ghcr.io/open-telemetry/opentelemetry-java/jaeger:1.32")
.withExposedPorts(queryPort, collectorPort, hostPort)
.withHostConfig(newHostConfig().withPortBindings(portBindings))
.withName("jaeger")
.exec();
dockerClient.startContainerCmd(container.getId()).exec();
}
}

@AfterAll
static void teardown() {
dockerClient.listContainersCmd().exec()
.forEach(container -> {
dockerClient.stopContainerCmd(container.getId()).exec();
dockerClient.removeContainerCmd(container.getId()).exec();
});
}

@Test
void testJaegerRemoteIntegration() {
createTestSpan(openTelemetry);
JsonPath spanData = Awaitility.await()
.atMost(Duration.ofSeconds(30))
.until(this::assertJaegerHaveTrace, spanDataObj -> spanDataObj.get("data[0].spans[0].traceID") != null);
assertNotNull(spanData);
assertNotNull(spanData.get("data[0].spans[0].spanID"));
assertEquals("Test span", spanData.get("data[0].spans[0].operationName"));
assertEquals("Test event", spanData.get("data[0].spans[0].logs[0].fields[0].value"));
assertEquals("opentelemetry-integration-test-jeager-remote", spanData.get("data[0].processes.p1.serviceName"));
}

private void createTestSpan(OpenTelemetry openTelemetry) {
Span span = openTelemetry.getTracer(getClass().getCanonicalName()).spanBuilder("Test span").startSpan();
try (Scope scope = span.makeCurrent()) {
span.addEvent("Test event");
} catch (Throwable t) {
span.recordException(t);
throw t;
} finally {
span.end();
}
}

private JsonPath assertJaegerHaveTrace() {
String serviceName = ConfigProvider.getConfig().getConfigValue("quarkus.application.name").getValue();
String path = String.format("/api/traces?service=%s", serviceName);

return given()
.baseUri(String.format(JAEGER_URL + ":%d", QUERY_PORT))
.contentType("application/json")
.when().get(path)
.body()
.jsonPath();
}

}

0 comments on commit bbdc2ae

Please sign in to comment.