Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions modules/grafana/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,13 @@ dependencies {
testImplementation 'io.opentelemetry:opentelemetry-api'
testImplementation 'io.opentelemetry:opentelemetry-sdk'
testImplementation 'io.opentelemetry:opentelemetry-exporter-otlp'

testImplementation project(':junit-jupiter')
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.0'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.3'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.0'
}

test {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class LgtmStackContainer extends GenericContainer<LgtmStackContainer> {

private static final int OTLP_HTTP_PORT = 4318;

private static final int LOKI_PORT = 3100;

private static final int TEMPO_PORT = 3200;

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

public String getLokiUrl() {
return "http://" + getHost() + ":" + getMappedPort(LOKI_PORT);
}

public String getOtlpHttpUrl() {
return "http://" + getHost() + ":" + getMappedPort(OTLP_HTTP_PORT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@
import io.micrometer.registry.otlp.OtlpMeterRegistry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.awaitility.Awaitility;
import org.junit.Test;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import uk.org.webcompere.systemstubs.SystemStubs;

import java.time.Duration;
Expand All @@ -27,71 +33,27 @@

public class LgtmStackContainerTest {

@Test
public void shouldPublishMetricAndTrace() throws Exception {
try ( // container {
LgtmStackContainer lgtm = new LgtmStackContainer("grafana/otel-lgtm:0.11.0")
// }
) {
lgtm.start();

String version = RestAssured
.get(String.format("http://%s:%s/api/health", lgtm.getHost(), lgtm.getMappedPort(3000)))
.jsonPath()
.get("version");
assertThat(version).isEqualTo("11.6.0");

generateTrace(lgtm);

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

Awaitility
.given()
.pollInterval(Duration.ofSeconds(2))
.atMost(Duration.ofSeconds(5))
.ignoreExceptions()
.untilAsserted(() -> {
Response response = RestAssured
.given()
.queryParam("query", "test_counter_total{job=\"testcontainers\"}")
.get(String.format("%s/api/v1/query", lgtm.getPrometheusHttpUrl()))
.prettyPeek()
.thenReturn();
assertThat(response.getStatusCode()).isEqualTo(200);
assertThat(response.body().jsonPath().getList("data.result[0].value")).contains("2");
});

Awaitility
.given()
.pollInterval(Duration.ofSeconds(2))
.atMost(Duration.ofSeconds(5))
.ignoreExceptions()
.untilAsserted(() -> {
Response response = RestAssured
.given()
.get(String.format("%s/api/search", lgtm.getTempoUrl()))
.prettyPeek()
.thenReturn();
assertThat(response.getStatusCode()).isEqualTo(200);
assertThat(response.body().jsonPath().getString("traces[0].rootServiceName"))
.isEqualTo("test-service");
});
}
}
private static final LgtmStackContainer lgtm = new LgtmStackContainer("grafana/otel-lgtm:0.11.1");

private static OpenTelemetrySdk openTelemetry;

@BeforeAll
static void setup() {
lgtm.start();
OtlpGrpcSpanExporter spanExporter = OtlpGrpcSpanExporter
.builder()
.setTimeout(Duration.ofSeconds(1))
.setEndpoint(lgtm.getOtlpGrpcUrl())
.build();

private void generateTrace(LgtmStackContainer lgtm) {
OtlpGrpcSpanExporter exporter = OtlpGrpcSpanExporter
OtlpGrpcLogRecordExporter logExporter = OtlpGrpcLogRecordExporter
.builder()
.setTimeout(Duration.ofSeconds(1))
.setEndpoint(lgtm.getOtlpGrpcUrl())
.build();

BatchSpanProcessor spanProcessor = BatchSpanProcessor
.builder(exporter)
.builder(spanExporter)
.setScheduleDelay(500, TimeUnit.MILLISECONDS)
.build();

Expand All @@ -101,13 +63,94 @@ private void generateTrace(LgtmStackContainer lgtm) {
.setResource(Resource.create(Attributes.of(AttributeKey.stringKey("service.name"), "test-service")))
.build();

OpenTelemetrySdk openTelemetry = OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build();
SdkLoggerProvider loggerProvider = SdkLoggerProvider
.builder()
.addLogRecordProcessor(SimpleLogRecordProcessor.create(logExporter))
.build();

openTelemetry =
OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).setLoggerProvider(loggerProvider).build();
}

@AfterAll
static void cleanup() {
openTelemetry.shutdown();
lgtm.stop();
}

@Test
void shouldPublishMetric() throws Exception {
String version = RestAssured
.get(String.format("http://%s:%s/api/health", lgtm.getHost(), lgtm.getMappedPort(3000)))
.jsonPath()
.get("version");
assertThat(version).isEqualTo("12.0.0");

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

Awaitility
.given()
.pollInterval(Duration.ofSeconds(2))
.atMost(Duration.ofSeconds(5))
.ignoreExceptions()
.untilAsserted(() -> {
Response response = RestAssured
.given()
.queryParam("query", "test_counter_total{job=\"testcontainers\"}")
.get(String.format("%s/api/v1/query", lgtm.getPrometheusHttpUrl()))
.prettyPeek()
.thenReturn();
assertThat(response.getStatusCode()).isEqualTo(200);
assertThat(response.body().jsonPath().getList("data.result[0].value")).contains("2");
});
}

@Test
void shouldPublishLog() {
Logger logger = openTelemetry.getSdkLoggerProvider().loggerBuilder("test").build();
logger.logRecordBuilder().setBody("Test log!").setAttribute(AttributeKey.stringKey("job"), "test-job").emit();

Awaitility
.given()
.pollInterval(Duration.ofSeconds(2))
.atMost(Duration.ofSeconds(5))
.ignoreExceptions()
.untilAsserted(() -> {
Response response = RestAssured
.given()
.queryParam("query", "{service_name=\"unknown_service:java\"}")
.get(String.format("%s/loki/api/v1/query_range", lgtm.getLokiUrl()))
.prettyPeek()
.thenReturn();
assertThat(response.getStatusCode()).isEqualTo(200);
assertThat(response.body().jsonPath().getString("data.result[0].values[0][1]")).isEqualTo("Test log!");
});
}

@Test
void shouldPublishTrace() {
Tracer tracer = openTelemetry.getTracer("test");
Span span = tracer.spanBuilder("test").startSpan();
span.end();

openTelemetry.shutdown();
Awaitility
.given()
.pollInterval(Duration.ofSeconds(2))
.atMost(Duration.ofSeconds(5))
.ignoreExceptions()
.untilAsserted(() -> {
Response response = RestAssured
.given()
.get(String.format("%s/api/search", lgtm.getTempoUrl()))
.prettyPeek()
.thenReturn();
assertThat(response.getStatusCode()).isEqualTo(200);
assertThat(response.body().jsonPath().getString("traces[0].rootServiceName")).isEqualTo("test-service");
});
}

private static OtlpConfig createOtlpConfig(LgtmStackContainer lgtm) {
Expand Down
Loading