Skip to content

Commit 8ad5c41

Browse files
Expose Loki in LgtmContainer (#10256)
Co-authored-by: Eddú Meléndez Gonzales <eddu.melendez@gmail.com>
1 parent a2197e1 commit 8ad5c41

File tree

2 files changed

+77
-46
lines changed

2 files changed

+77
-46
lines changed

modules/grafana/src/main/java/org/testcontainers/grafana/LgtmStackContainer.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public class LgtmStackContainer extends GenericContainer<LgtmStackContainer> {
3131

3232
private static final int OTLP_HTTP_PORT = 4318;
3333

34+
private static final int LOKI_PORT = 3100;
35+
3436
private static final int TEMPO_PORT = 3200;
3537

3638
private static final int PROMETHEUS_PORT = 9090;
@@ -42,7 +44,7 @@ public LgtmStackContainer(String image) {
4244
public LgtmStackContainer(DockerImageName image) {
4345
super(image);
4446
image.assertCompatibleWith(DEFAULT_IMAGE_NAME);
45-
withExposedPorts(GRAFANA_PORT, TEMPO_PORT, OTLP_GRPC_PORT, OTLP_HTTP_PORT, PROMETHEUS_PORT);
47+
withExposedPorts(GRAFANA_PORT, TEMPO_PORT, LOKI_PORT, OTLP_GRPC_PORT, OTLP_HTTP_PORT, PROMETHEUS_PORT);
4648
waitingFor(
4749
Wait.forLogMessage(".*The OpenTelemetry collector and the Grafana LGTM stack are up and running.*\\s", 1)
4850
);
@@ -61,6 +63,10 @@ public String getTempoUrl() {
6163
return "http://" + getHost() + ":" + getMappedPort(TEMPO_PORT);
6264
}
6365

66+
public String getLokiUrl() {
67+
return "http://" + getHost() + ":" + getMappedPort(LOKI_PORT);
68+
}
69+
6470
public String getOtlpHttpUrl() {
6571
return "http://" + getHost() + ":" + getMappedPort(OTLP_HTTP_PORT);
6672
}

modules/grafana/src/test/java/org/testcontainers/grafana/LgtmStackContainerTest.java

Lines changed: 70 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
import io.micrometer.registry.otlp.OtlpMeterRegistry;
88
import io.opentelemetry.api.common.AttributeKey;
99
import io.opentelemetry.api.common.Attributes;
10+
import io.opentelemetry.api.logs.Logger;
1011
import io.opentelemetry.api.trace.Span;
1112
import io.opentelemetry.api.trace.Tracer;
13+
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
1214
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
1315
import io.opentelemetry.sdk.OpenTelemetrySdk;
16+
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
17+
import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor;
1418
import io.opentelemetry.sdk.resources.Resource;
1519
import io.opentelemetry.sdk.trace.SdkTracerProvider;
1620
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
@@ -28,86 +32,107 @@
2832
public class LgtmStackContainerTest {
2933

3034
@Test
31-
public void shouldPublishMetricAndTrace() throws Exception {
35+
public void shouldPublishMetricsTracesAndLogs() throws Exception {
3236
try ( // container {
33-
LgtmStackContainer lgtm = new LgtmStackContainer("grafana/otel-lgtm:0.11.0")
37+
LgtmStackContainer lgtm = new LgtmStackContainer("grafana/otel-lgtm:0.11.1")
3438
// }
3539
) {
3640
lgtm.start();
3741

42+
OtlpGrpcSpanExporter spanExporter = OtlpGrpcSpanExporter
43+
.builder()
44+
.setTimeout(Duration.ofSeconds(1))
45+
.setEndpoint(lgtm.getOtlpGrpcUrl())
46+
.build();
47+
48+
OtlpGrpcLogRecordExporter logExporter = OtlpGrpcLogRecordExporter
49+
.builder()
50+
.setTimeout(Duration.ofSeconds(1))
51+
.setEndpoint(lgtm.getOtlpGrpcUrl())
52+
.build();
53+
54+
BatchSpanProcessor spanProcessor = BatchSpanProcessor
55+
.builder(spanExporter)
56+
.setScheduleDelay(500, TimeUnit.MILLISECONDS)
57+
.build();
58+
59+
SdkTracerProvider tracerProvider = SdkTracerProvider
60+
.builder()
61+
.addSpanProcessor(spanProcessor)
62+
.setResource(Resource.create(Attributes.of(AttributeKey.stringKey("service.name"), "test-service")))
63+
.build();
64+
65+
SdkLoggerProvider loggerProvider = SdkLoggerProvider
66+
.builder()
67+
.addLogRecordProcessor(SimpleLogRecordProcessor.create(logExporter))
68+
.build();
69+
70+
OpenTelemetrySdk openTelemetry = OpenTelemetrySdk
71+
.builder()
72+
.setTracerProvider(tracerProvider)
73+
.setLoggerProvider(loggerProvider)
74+
.build();
75+
3876
String version = RestAssured
3977
.get(String.format("http://%s:%s/api/health", lgtm.getHost(), lgtm.getMappedPort(3000)))
4078
.jsonPath()
4179
.get("version");
42-
assertThat(version).isEqualTo("11.6.0");
43-
44-
generateTrace(lgtm);
80+
assertThat(version).isEqualTo("12.0.0");
4581

4682
OtlpConfig otlpConfig = createOtlpConfig(lgtm);
4783
MeterRegistry meterRegistry = SystemStubs
4884
.withEnvironmentVariable("OTEL_SERVICE_NAME", "testcontainers")
4985
.execute(() -> new OtlpMeterRegistry(otlpConfig, Clock.SYSTEM));
5086
Counter.builder("test.counter").register(meterRegistry).increment(2);
5187

88+
Logger logger = openTelemetry.getSdkLoggerProvider().loggerBuilder("test").build();
89+
logger
90+
.logRecordBuilder()
91+
.setBody("Test log!")
92+
.setAttribute(AttributeKey.stringKey("job"), "test-job")
93+
.emit();
94+
95+
Tracer tracer = openTelemetry.getTracer("test");
96+
Span span = tracer.spanBuilder("test").startSpan();
97+
span.end();
98+
5299
Awaitility
53100
.given()
54101
.pollInterval(Duration.ofSeconds(2))
55102
.atMost(Duration.ofSeconds(5))
56103
.ignoreExceptions()
57104
.untilAsserted(() -> {
58-
Response response = RestAssured
105+
Response metricResponse = RestAssured
59106
.given()
60107
.queryParam("query", "test_counter_total{job=\"testcontainers\"}")
61108
.get(String.format("%s/api/v1/query", lgtm.getPrometheusHttpUrl()))
62109
.prettyPeek()
63110
.thenReturn();
64-
assertThat(response.getStatusCode()).isEqualTo(200);
65-
assertThat(response.body().jsonPath().getList("data.result[0].value")).contains("2");
66-
});
111+
assertThat(metricResponse.getStatusCode()).isEqualTo(200);
112+
assertThat(metricResponse.body().jsonPath().getList("data.result[0].value")).contains("2");
67113

68-
Awaitility
69-
.given()
70-
.pollInterval(Duration.ofSeconds(2))
71-
.atMost(Duration.ofSeconds(5))
72-
.ignoreExceptions()
73-
.untilAsserted(() -> {
74-
Response response = RestAssured
114+
Response logResponse = RestAssured
115+
.given()
116+
.queryParam("query", "{service_name=\"unknown_service:java\"}")
117+
.get(String.format("%s/loki/api/v1/query_range", lgtm.getLokiUrl()))
118+
.prettyPeek()
119+
.thenReturn();
120+
assertThat(logResponse.getStatusCode()).isEqualTo(200);
121+
assertThat(logResponse.body().jsonPath().getString("data.result[0].values[0][1]"))
122+
.isEqualTo("Test log!");
123+
124+
Response traceResponse = RestAssured
75125
.given()
76126
.get(String.format("%s/api/search", lgtm.getTempoUrl()))
77127
.prettyPeek()
78128
.thenReturn();
79-
assertThat(response.getStatusCode()).isEqualTo(200);
80-
assertThat(response.body().jsonPath().getString("traces[0].rootServiceName"))
129+
assertThat(traceResponse.getStatusCode()).isEqualTo(200);
130+
assertThat(traceResponse.body().jsonPath().getString("traces[0].rootServiceName"))
81131
.isEqualTo("test-service");
82132
});
83-
}
84-
}
85-
86-
private void generateTrace(LgtmStackContainer lgtm) {
87-
OtlpGrpcSpanExporter exporter = OtlpGrpcSpanExporter
88-
.builder()
89-
.setTimeout(Duration.ofSeconds(1))
90-
.setEndpoint(lgtm.getOtlpGrpcUrl())
91-
.build();
92133

93-
BatchSpanProcessor spanProcessor = BatchSpanProcessor
94-
.builder(exporter)
95-
.setScheduleDelay(500, TimeUnit.MILLISECONDS)
96-
.build();
97-
98-
SdkTracerProvider tracerProvider = SdkTracerProvider
99-
.builder()
100-
.addSpanProcessor(spanProcessor)
101-
.setResource(Resource.create(Attributes.of(AttributeKey.stringKey("service.name"), "test-service")))
102-
.build();
103-
104-
OpenTelemetrySdk openTelemetry = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build();
105-
106-
Tracer tracer = openTelemetry.getTracer("test");
107-
Span span = tracer.spanBuilder("test").startSpan();
108-
span.end();
109-
110-
openTelemetry.shutdown();
134+
openTelemetry.close();
135+
}
111136
}
112137

113138
private static OtlpConfig createOtlpConfig(LgtmStackContainer lgtm) {

0 commit comments

Comments
 (0)