Skip to content

Commit 88a95e0

Browse files
committed
add Exemplar support for OpenTelemetry tracing (review)
1 parent 126b32b commit 88a95e0

File tree

13 files changed

+293
-87
lines changed

13 files changed

+293
-87
lines changed

Diff for: integration_tests/exemplars_otel/pom.xml

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>io.prometheus</groupId>
8+
<artifactId>integration_tests</artifactId>
9+
<version>0.10.1-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>exemplars_otel</artifactId>
13+
<name>Integration Test - Exemplars with OpenTelemetry</name>
14+
15+
<properties>
16+
<otel.version>1.1.0</otel.version>
17+
</properties>
18+
19+
<dependencies>
20+
<dependency>
21+
<groupId>io.prometheus</groupId>
22+
<artifactId>simpleclient</artifactId>
23+
<version>${project.version}</version>
24+
<exclusions>
25+
<!-- uncomment the following to verify manually that simpleclient still works if the tracers are excluded -->
26+
<!--
27+
<exclusion>
28+
<groupId>io.prometheus</groupId>
29+
<artifactId>tracer_common</artifactId>
30+
</exclusion>
31+
-->
32+
<exclusion>
33+
<groupId>io.prometheus</groupId>
34+
<artifactId>tracer_otel_agent</artifactId>
35+
</exclusion>
36+
<!--
37+
<exclusion>
38+
<groupId>io.prometheus</groupId>
39+
<artifactId>tracer_otel</artifactId>
40+
</exclusion>
41+
-->
42+
</exclusions>
43+
</dependency>
44+
<dependency>
45+
<groupId>io.opentelemetry</groupId>
46+
<artifactId>opentelemetry-api</artifactId>
47+
<version>${otel.version}</version>
48+
</dependency>
49+
<dependency>
50+
<groupId>io.opentelemetry</groupId>
51+
<artifactId>opentelemetry-sdk</artifactId>
52+
<version>${otel.version}</version>
53+
</dependency>
54+
<dependency>
55+
<groupId>io.prometheus</groupId>
56+
<artifactId>simpleclient_httpserver</artifactId>
57+
<version>${project.version}</version>
58+
</dependency>
59+
<dependency>
60+
<groupId>com.squareup.okhttp3</groupId>
61+
<artifactId>okhttp</artifactId>
62+
<version>4.9.1</version>
63+
</dependency>
64+
<dependency>
65+
<groupId>org.testcontainers</groupId>
66+
<artifactId>testcontainers</artifactId>
67+
<scope>test</scope>
68+
</dependency>
69+
<dependency>
70+
<groupId>ch.qos.logback</groupId>
71+
<artifactId>logback-classic</artifactId>
72+
<version>1.1.2</version>
73+
</dependency>
74+
</dependencies>
75+
76+
<build>
77+
<finalName>${artifactId}</finalName>
78+
<plugins>
79+
<plugin>
80+
<groupId>org.apache.maven.plugins</groupId>
81+
<artifactId>maven-compiler-plugin</artifactId>
82+
<configuration>
83+
<source>1.8</source>
84+
<target>1.8</target>
85+
</configuration>
86+
</plugin>
87+
<plugin>
88+
<groupId>org.apache.maven.plugins</groupId>
89+
<artifactId>maven-failsafe-plugin</artifactId>
90+
<version>2.22.2</version>
91+
<executions>
92+
<execution>
93+
<id>integration-test</id>
94+
<phase>integration-test</phase>
95+
<goals>
96+
<goal>integration-test</goal>
97+
</goals>
98+
</execution>
99+
<execution>
100+
<id>verify</id>
101+
<phase>verify</phase>
102+
<goals>
103+
<goal>verify</goal>
104+
</goals>
105+
</execution>
106+
</executions>
107+
</plugin>
108+
<plugin>
109+
<groupId>org.apache.maven.plugins</groupId>
110+
<artifactId>maven-shade-plugin</artifactId>
111+
<version>3.2.4</version>
112+
<executions>
113+
<execution>
114+
<phase>package</phase>
115+
<goals>
116+
<goal>shade</goal>
117+
</goals>
118+
<configuration>
119+
<transformers>
120+
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
121+
<mainClass>io.prometheus.it.exemplars_otel.Server</mainClass>
122+
</transformer>
123+
</transformers>
124+
</configuration>
125+
</execution>
126+
</executions>
127+
</plugin>
128+
</plugins>
129+
</build>
130+
131+
<licenses>
132+
<license>
133+
<name>The Apache Software License, Version 2.0</name>
134+
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
135+
<distribution>repo</distribution>
136+
</license>
137+
</licenses>
138+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.prometheus.it.exemplars_otel;
2+
3+
import io.opentelemetry.api.trace.Span;
4+
import io.opentelemetry.api.trace.Tracer;
5+
import io.opentelemetry.sdk.trace.SdkTracerProvider;
6+
import io.prometheus.client.Counter;
7+
import io.prometheus.client.exporter.HTTPServer;
8+
9+
import java.io.IOException;
10+
11+
public class Server {
12+
13+
public static void main(String[] args) throws IOException, InterruptedException {
14+
new HTTPServer(9000);
15+
Counter counter = Counter.build()
16+
.name("test")
17+
.help("help")
18+
.register();
19+
20+
Tracer tracer = SdkTracerProvider.builder().build().get(null);
21+
Span span = tracer.spanBuilder("my span").startSpan();
22+
span.makeCurrent();
23+
counter.inc(1);
24+
span.end();
25+
Thread.currentThread().join(); // sleep forever
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package io.prometheus.it.exemplars_otel;
2+
3+
import okhttp3.OkHttpClient;
4+
import okhttp3.Request;
5+
import okhttp3.Response;
6+
import org.junit.Assert;
7+
import org.junit.Rule;
8+
import org.junit.Test;
9+
import org.testcontainers.containers.GenericContainer;
10+
import org.testcontainers.images.builder.ImageFromDockerfile;
11+
12+
import java.io.IOException;
13+
import java.nio.file.Paths;
14+
import java.util.Arrays;
15+
import java.util.List;
16+
17+
/**
18+
* This is just a smoke test, as completeness is already tested with exemplars_otel_agent
19+
*/
20+
public class ExemplarsOtelIT {
21+
22+
private final OkHttpClient client = new OkHttpClient();
23+
24+
private static class DockerContainer extends GenericContainer<DockerContainer> {
25+
DockerContainer() {
26+
super(new ImageFromDockerfile("exemplars-otel-test")
27+
.withFileFromPath("exemplars_otel.jar", Paths.get("target/exemplars_otel.jar"))
28+
.withFileFromClasspath("Dockerfile", "Dockerfile"));
29+
}
30+
}
31+
32+
@Rule
33+
public DockerContainer dockerContainer = new DockerContainer()
34+
.withExposedPorts(9000);
35+
36+
@Test
37+
public void testExemplars() throws IOException {
38+
List<String> metrics = scrapeMetrics();
39+
boolean found = false;
40+
for (String metric : metrics) {
41+
System.out.println(metric);
42+
if (metric.matches("^test_total 1\\.0 # \\{trace_id=\"[0-9a-f]+\",span_id=\"[0-9a-f]+\"} 1.0 [0-9.]+$")) {
43+
found = true;
44+
}
45+
}
46+
Assert.assertTrue("test_total metric with exemplars not found", found);
47+
}
48+
49+
private List<String> scrapeMetrics() throws IOException {
50+
Request request = new Request.Builder()
51+
.url("http://localhost:" + dockerContainer.getMappedPort(9000) + "/metrics")
52+
.header("Accept", "application/openmetrics-text; version=1.0.0; charset=utf-8")
53+
.build();
54+
try (Response response = client.newCall(request).execute()) {
55+
return Arrays.asList(response.body().string().split("\\n"));
56+
}
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM openjdk:11-jre
2+
RUN mkdir -p /app/
3+
COPY exemplars_otel.jar /app/
4+
CMD java -jar /app/exemplars_otel.jar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<configuration>
2+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3+
<encoder>
4+
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
5+
</encoder>
6+
</appender>
7+
8+
<root level="info">
9+
<appender-ref ref="STDOUT"/>
10+
</root>
11+
12+
<logger name="org.testcontainers" level="INFO"/>
13+
<logger name="com.github.dockerjava" level="WARN"/>
14+
</configuration>

Diff for: integration_tests/exemplars_otel_agent/pom.xml

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
<version>0.10.1-SNAPSHOT</version>
1010
</parent>
1111

12-
<groupId>io.prometheus</groupId>
1312
<artifactId>exemplars_otel_agent</artifactId>
1413
<name>Integration Test - Exemplars with the OpenTelemetry Agent</name>
1514

Diff for: integration_tests/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
</licenses>
2323

2424
<modules>
25+
<module>exemplars_otel</module>
2526
<module>exemplars_otel_agent</module>
2627
<module>example_application</module>
2728
<module>java_versions</module>

Diff for: simpleclient/pom.xml

+6-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@
4040
All transitive dependencies of tracer libraries are scoped as provided and optional at runtime. -->
4141
<dependency>
4242
<groupId>io.prometheus</groupId>
43-
<artifactId>tracer</artifactId>
43+
<artifactId>tracer_otel</artifactId>
44+
<version>${project.version}</version>
45+
</dependency>
46+
<dependency>
47+
<groupId>io.prometheus</groupId>
48+
<artifactId>tracer_otel_agent</artifactId>
4449
<version>${project.version}</version>
4550
</dependency>
4651
<!-- Test Dependencies Follow -->

Diff for: simpleclient/src/main/java/io/prometheus/client/exemplars/ExemplarConfig.java

+1-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package io.prometheus.client.exemplars;
22

3-
import io.prometheus.client.exemplars.tracer.Tracer;
4-
import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier;
5-
63
/**
74
* Static configuration class for Exemplar behavior.
85
*/
@@ -18,12 +15,7 @@ public class ExemplarConfig {
1815

1916
private ExemplarConfig() {
2017
noopExemplarSampler = new NoopExemplarSampler();
21-
SpanContextSupplier spanContextSupplier = Tracer.findSpanContextSupplier();
22-
if (spanContextSupplier != null) {
23-
defaultExemplarSampler = new DefaultExemplarSampler(spanContextSupplier);
24-
} else {
25-
defaultExemplarSampler = noopExemplarSampler;
26-
}
18+
defaultExemplarSampler = new Tracer().initExemplarSampler(noopExemplarSampler);
2719
counterExemplarSampler = defaultExemplarSampler;
2820
histogramExemplarSampler = defaultExemplarSampler;
2921
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package io.prometheus.client.exemplars;
2+
3+
import io.prometheus.client.exemplars.tracer.common.SpanContextSupplier;
4+
import io.prometheus.client.exemplars.tracer.otel.OpenTelemetrySpanContextSupplier;
5+
import io.prometheus.client.exemplars.tracer.otel_agent.OpenTelemetryAgentSpanContextSupplier;
6+
7+
class Tracer {
8+
9+
ExemplarSampler initExemplarSampler(ExemplarSampler noopExemplarSampler) {
10+
try {
11+
Object spanContextSupplier = findSpanContextSupplier();
12+
if (spanContextSupplier != null) {
13+
return new DefaultExemplarSampler((SpanContextSupplier) spanContextSupplier);
14+
}
15+
} catch (NoClassDefFoundError ignored) {
16+
// tracer_common dependency not found
17+
}
18+
return noopExemplarSampler;
19+
}
20+
21+
// Avoid SpanContextSupplier in the method signature so that we can handle the NoClassDefFoundError
22+
// even if the user excluded tracer_common from the classpath.
23+
private Object findSpanContextSupplier() {
24+
try {
25+
if (OpenTelemetrySpanContextSupplier.isAvailable()) {
26+
return new OpenTelemetrySpanContextSupplier();
27+
}
28+
} catch (NoClassDefFoundError ignored) {
29+
// tracer_otel dependency not found
30+
} catch (UnsupportedClassVersionError ignored) {
31+
// OpenTelemetry requires Java 8, but client_java might run on Java 6.
32+
}
33+
try {
34+
if (OpenTelemetryAgentSpanContextSupplier.isAvailable()) {
35+
return new OpenTelemetryAgentSpanContextSupplier();
36+
}
37+
} catch (NoClassDefFoundError ignored) {
38+
// tracer_otel_agent dependency not found
39+
} catch (UnsupportedClassVersionError ignored) {
40+
// OpenTelemetry requires Java 8, but client_java might run on Java 6.
41+
}
42+
return null;
43+
}
44+
}

Diff for: tracer_parent/pom.xml

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
</licenses>
3434

3535
<modules>
36-
<module>tracer</module>
3736
<module>tracer_common</module>
3837
<module>tracer_otel</module>
3938
<module>tracer_otel_agent</module>

Diff for: tracer_parent/tracer/pom.xml

-41
This file was deleted.

0 commit comments

Comments
 (0)