Skip to content

Commit 7ee5033

Browse files
Add trace validation to testcontainer example (#451)
replaces #424 --------- Co-authored-by: Jay DeLuca <jaydeluca4@gmail.com>
1 parent e715cee commit 7ee5033

3 files changed

Lines changed: 42 additions & 21 deletions

File tree

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,41 @@
11
# Using Testcontainers
22

3-
The provided code demonstrates how to use **Testcontainers** with **Grafana's LGTM stack** to test OpenTelemetry metrics in a Java application. Here's a step-by-step explanation:
3+
The provided code demonstrates how to use **Testcontainers** with **Grafana's LGTM stack** to test OpenTelemetry metrics
4+
in a Java application. Here's a step-by-step explanation:
45

56
1. **Set Up the Testcontainers Environment**:
67

7-
- The `@Testcontainers` annotation enables the Testcontainers extension for JUnit 5.
8-
- The `@Container` annotation is used to define a `LgtmStackContainer` that runs the Grafana LGTM stack in a Docker container.
8+
- The `@Testcontainers` annotation enables the Testcontainers extension for JUnit 5.
9+
- The `@Container` annotation is used to define a `LgtmStackContainer` that runs the Grafana LGTM stack in a Docker
10+
container.
911

1012
2. **Configure OpenTelemetry**:
1113

12-
- In the `@BeforeEach` method, system properties are set to configure the OpenTelemetry exporter to send metrics to the LGTM stack running in the container.
14+
- In the `@BeforeEach` method, system properties are set to configure the OpenTelemetry exporter to send metrics to
15+
the LGTM stack running in the container.
1316

1417
3. **Run the Application**:
1518

16-
- The `OtelApp` class initializes OpenTelemetry and generates a custom metric (`sold_items`) with attributes (e.g., `tenant`).
19+
- The `OtelApp` class initializes OpenTelemetry and generates a custom metric (`sold_items`) with attributes (e.g.,
20+
`tenant`) as well as a span representing the block the code.
1721

18-
4. **Test the Metrics Export**:
22+
4. **Test Exporting Metrics and Traces**:
1923

20-
- The test method `testExportMetric` runs the application and queries the Prometheus endpoint in the LGTM stack to verify that the metric (`sold_items`) has been exported successfully.
21-
- The `Awaitility` library is used to poll the Prometheus endpoint until the metric is found or a timeout occurs.
24+
- The test method `testExportMetricsAndTraces` runs the application and queries the Prometheus and Tempo endpoints
25+
in the LGTM stack to verify that the metric (`sold_items`) and span have been exported successfully.
26+
- The `Awaitility` library is used to poll the endpoints until the telemetry is found or a timeout occurs.
2227

2328
5. **Debugging with Grafana**:
24-
- The test outputs the Grafana URL (`lgtm.getGrafanaHttpUrl()`) to the console, allowing you to manually inspect the metrics in the Grafana UI.
29+
30+
- The test outputs the Grafana URL (`lgtm.getGrafanaHttpUrl()`) to the console, allowing you to manually inspect the
31+
telemetry in the Grafana UI if needed.
2532

2633
## Example Usage
2734

2835
1. Start the test using `mvn test`.
2936
2. Check the console output for the Grafana URL.
30-
3. Open the Grafana UI, navigate to the Explore tab, and query the metrics.
31-
4. The test will pass if the metric is successfully exported and found in Prometheus.
37+
3. Open the Grafana UI, navigate to the Explore tab, and query the metrics or traces.
38+
4. The test will pass if the metric and span are successfully exported and found in Prometheus and Tempo.
3239

33-
This setup is useful for validating OpenTelemetry instrumentation and ensuring metrics are correctly exported to a monitoring system.
40+
This setup is useful for validating OpenTelemetry instrumentation and ensuring metrics are correctly exported to a
41+
monitoring system.

examples/java/testcontainer/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55

66
<groupId>com.grafana.example</groupId>
7-
<artifactId>testcontaier</artifactId>
7+
<artifactId>testcontainer</artifactId>
88
<version>1.0.0-SNAPSHOT</version>
99

1010
<name>Java Testcontainer Demo</name>

examples/java/testcontainer/src/test/java/com/grafana/example/TestcontainerTest.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,32 @@ void setUp() {
2626
System.setProperty("otel.exporter.otlp.protocol", "http/protobuf");
2727
System.setProperty("otel.resource.attributes", "service.name=otel-java-test");
2828
System.setProperty("otel.metric.export.interval", "1s");
29+
System.setProperty("otel.bsp.schedule.delay", "500ms");
2930
}
3031

3132
@Test
32-
void testExportMetric() {
33-
// Howto:
34-
// 1. The test with a really long timeout
33+
void testExportMetricsAndTraces() throws InterruptedException {
34+
// How to debug:
35+
// 1. Run the test with a really long timeout (update the awaitility argument)
3536
// 2. Go to the Grafana UI
3637
// 3. Open the Explore tab
3738
// 4. Select the Prometheus data source
3839
// 5. Find your metric by name or attribute (e.g. "tenant1")
3940
// 6. Click on the metric to see the details
4041
// 7. Copy the query and paste it into the test
4142
System.out.println("Grafana URL to debug telemetry: " + lgtm.getGrafanaHttpUrl());
42-
4343
var app = new OtelApp();
4444
app.run();
4545

46+
HttpClient client = HttpClient.newHttpClient();
4647
String query =
4748
URLEncoder.encode(
4849
"sold_items_total{job=\"otel-java-test\",service_name=\"otel-java-test\",tenant=\"tenant1\"}",
4950
StandardCharsets.UTF_8);
50-
String prometheusHttpUrl = lgtm.getPromehteusHttpUrl() + "/api/v1/query?query=" + query;
51+
String prometheusHttpUrl = lgtm.getPrometheusHttpUrl() + "/api/v1/query?query=" + query;
5152

52-
HttpClient client = HttpClient.newHttpClient();
5353
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(prometheusHttpUrl)).build();
5454

55-
// Total time: 18.448 s (for the whole test, will take longer when the image needs to be
56-
// downloaded)
5755
await()
5856
.atMost(Duration.ofSeconds(10))
5957
.until(
@@ -63,5 +61,20 @@ void testExportMetric() {
6361
String body = response.body();
6462
return response.statusCode() == 200 && body.contains("sold_items");
6563
});
64+
65+
HttpRequest traceRequest =
66+
HttpRequest.newBuilder()
67+
.uri(URI.create(String.format("%s/api/search", lgtm.getTempoUrl())))
68+
.build();
69+
70+
await()
71+
.atMost(Duration.ofSeconds(10))
72+
.until(
73+
() -> {
74+
HttpResponse<String> response =
75+
client.send(traceRequest, HttpResponse.BodyHandlers.ofString());
76+
String body = response.body();
77+
return response.statusCode() == 200 && body.contains("otel-java-test");
78+
});
6679
}
6780
}

0 commit comments

Comments
 (0)