Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.smoketest;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.util.JsonFormat;
import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest;
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest;
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
import io.opentelemetry.testing.internal.armeria.client.WebClient;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class GroovyTestTelemetryRetriever {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

final WebClient client;

GroovyTestTelemetryRetriever(int backendPort) {
client = WebClient.of("http://localhost:" + backendPort);
}

void clearTelemetry() {
client.get("/clear").aggregate().join();
}

Collection<ExportTraceServiceRequest> waitForTraces() {
return waitForTelemetry("get-traces", ExportTraceServiceRequest::newBuilder);
}

Collection<ExportMetricsServiceRequest> waitForMetrics() {
return waitForTelemetry("get-metrics", ExportMetricsServiceRequest::newBuilder);
}

Collection<ExportLogsServiceRequest> waitForLogs() {
return waitForTelemetry("get-logs", ExportLogsServiceRequest::newBuilder);
}

@SuppressWarnings({"unchecked", "InterruptedExceptionSwallowed"})
private <T extends GeneratedMessage, B extends GeneratedMessage.Builder<?>>
Collection<T> waitForTelemetry(String path, Supplier<B> builderConstructor) {
try {
String content = waitForContent(path);

return StreamSupport.stream(OBJECT_MAPPER.readTree(content).spliterator(), false)
.map(
jsonNode -> {
B builder = builderConstructor.get();
// TODO: Register parser into object mapper to avoid de -> re -> deserialize.
try {
String json = OBJECT_MAPPER.writeValueAsString(jsonNode);
JsonFormat.parser().merge(json, builder);
} catch (Exception e) {
throw new IllegalStateException(e);
}
return (T) builder.build();
})
.collect(Collectors.toList());
} catch (Exception e) {
throw new IllegalStateException(e);
}
}

@SuppressWarnings("SystemOut")
private String waitForContent(String path) throws InterruptedException {
long previousSize = 0;
long deadline = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(30);
String content = "[]";
while (System.currentTimeMillis() < deadline) {
content = client.get(path).aggregate().join().contentUtf8();
if (content.length() > 2 && content.length() == previousSize) {
break;
}
previousSize = content.length();
System.out.println("Current content size $previousSize");
TimeUnit.MILLISECONDS.sleep(500);
}

return content;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.smoketest;

import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import org.junit.jupiter.api.extension.ExtensionContext;

/**
* JUnit 5 extension for writing smoke tests that use a {@link TelemetryRetriever} to retrieve
* telemetry data from the fake backend.
*
* <p>Example usage:
*
* <pre>
* class MySmokeTest implements TelemetryRetrieverProvider {
* {@literal @}RegisterExtension
* static final InstrumentationExtension testing = SmokeTestInstrumentationExtension.create();
*
* {@literal @}Test
* void test() {
* // test code ...
*
* var spans = testing.spans();
* // assertions on collected spans ...
* }
* }
* </pre>
*/
public class SmokeTestInstrumentationExtension extends InstrumentationExtension {
private SmokeTestInstrumentationExtension() {
super(SmokeTestRunner.instance());
}

public static SmokeTestInstrumentationExtension create() {
return new SmokeTestInstrumentationExtension();
}

@Override
public void beforeEach(ExtensionContext extensionContext) {
Object testInstance = extensionContext.getRequiredTestInstance();

if (!(testInstance instanceof TelemetryRetrieverProvider)) {
throw new AssertionError(
"SmokeTestInstrumentationExtension can only be applied to a subclass of "
+ "TelemetryRetrieverProvider");
}

SmokeTestRunner smokeTestRunner = (SmokeTestRunner) getTestRunner();
smokeTestRunner.setTelemetryRetriever(
((TelemetryRetrieverProvider) testInstance).getTelemetryRetriever());

super.beforeEach(extensionContext);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.smoketest;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.util.List;

/**
* An implementation of {@link InstrumentationTestRunner} that uses {@link TelemetryRetriever} to
* fetch traces, metrics and logs from the fake backend.
*/
public class SmokeTestRunner extends InstrumentationTestRunner {

private static final SmokeTestRunner INSTANCE = new SmokeTestRunner();

private TelemetryRetriever telemetryRetriever;

public static SmokeTestRunner instance() {
return INSTANCE;
}

private SmokeTestRunner() {
super(OpenTelemetry.noop());
}

void setTelemetryRetriever(TelemetryRetriever telemetryRetriever) {
this.telemetryRetriever = telemetryRetriever;
}

@Override
public void beforeTestClass() {}

@Override
public void afterTestClass() {}

@Override
public void clearAllExportedData() {
telemetryRetriever.clearTelemetry();
}

@Override
public OpenTelemetry getOpenTelemetry() {
throw new UnsupportedOperationException();
}

@Override
public List<SpanData> getExportedSpans() {
return telemetryRetriever.waitForTraces();
}

@Override
public List<MetricData> getExportedMetrics() {
return telemetryRetriever.waitForMetrics();
}

@Override
public List<LogRecordData> getExportedLogRecords() {
return telemetryRetriever.waitForLogs();
}

@Override
public boolean forceFlushCalled() {
throw new UnsupportedOperationException();
}
}

This file was deleted.

Loading