
io.opentelemetry.instrumentation.testing.InstrumentationTestRunner Maven / Gradle / Ivy
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.testing;
import static org.awaitility.Awaitility.await;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil;
import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable;
import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier;
import io.opentelemetry.sdk.logs.data.LogData;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.testing.assertj.TraceAssert;
import io.opentelemetry.sdk.testing.assertj.TracesAssert;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import org.awaitility.core.ConditionTimeoutException;
/**
* This interface defines a common set of operations for interaction with OpenTelemetry SDK and
* traces & metrics exporters.
*
* @see LibraryTestRunner
* @see AgentTestRunner
*/
public abstract class InstrumentationTestRunner {
private final TestInstrumenters testInstrumenters;
protected InstrumentationTestRunner(OpenTelemetry openTelemetry) {
testInstrumenters = new TestInstrumenters(openTelemetry);
}
public abstract void beforeTestClass();
public abstract void afterTestClass();
public abstract void clearAllExportedData();
public abstract OpenTelemetry getOpenTelemetry();
public abstract List getExportedSpans();
public abstract List getExportedMetrics();
public abstract List getExportedLogs();
public abstract boolean forceFlushCalled();
/** Return a list of all captured traces, where each trace is a sorted list of spans. */
public final List> traces() {
return TelemetryDataUtil.groupTraces(getExportedSpans());
}
public final List> waitForTraces(int numberOfTraces) {
try {
return TelemetryDataUtil.waitForTraces(
this::getExportedSpans, numberOfTraces, 20, TimeUnit.SECONDS);
} catch (TimeoutException | InterruptedException e) {
throw new AssertionError("Error waiting for " + numberOfTraces + " traces", e);
}
}
@SafeVarargs
@SuppressWarnings("varargs")
public final void waitAndAssertTraces(Consumer... assertions) {
waitAndAssertTraces(Arrays.asList(assertions));
}
public final > void waitAndAssertTraces(Iterable assertions) {
List assertionsList = new ArrayList<>();
assertions.forEach(assertionsList::add);
try {
await()
.untilAsserted(
() -> {
List> traces = waitForTraces(assertionsList.size());
TracesAssert.assertThat(traces).hasTracesSatisfyingExactly(assertionsList);
});
} catch (ConditionTimeoutException e) {
// Don't throw this failure since the stack is the awaitility thread, causing confusion.
// Instead, just assert one more time on the test thread, which will fail with a better stack
// trace.
// TODO(anuraaga): There is probably a better way to do this.
List> traces = waitForTraces(assertionsList.size());
TracesAssert.assertThat(traces).hasTracesSatisfyingExactly(assertionsList);
}
}
/**
* Runs the provided {@code callback} inside the scope of an INTERNAL span with name {@code
* spanName}.
*/
public final void runWithSpan(String spanName, ThrowingRunnable callback)
throws E {
runWithSpan(
spanName,
() -> {
callback.run();
return null;
});
}
/**
* Runs the provided {@code callback} inside the scope of an INTERNAL span with name {@code
* spanName}.
*/
public final T runWithSpan(
String spanName, ThrowingSupplier callback) throws E {
return testInstrumenters.runWithSpan(spanName, callback);
}
/**
* Runs the provided {@code callback} inside the scope of an CLIENT span with name {@code
* spanName}.
*/
public final void runWithClientSpan(
String spanName, ThrowingRunnable callback) throws E {
runWithClientSpan(
spanName,
() -> {
callback.run();
return null;
});
}
/**
* Runs the provided {@code callback} inside the scope of an CLIENT span with name {@code
* spanName}.
*/
public final T runWithClientSpan(
String spanName, ThrowingSupplier callback) throws E {
return testInstrumenters.runWithClientSpan(spanName, callback);
}
/**
* Runs the provided {@code callback} inside the scope of an CLIENT span with name {@code
* spanName}.
*/
public final void runWithServerSpan(
String spanName, ThrowingRunnable callback) throws E {
runWithServerSpan(
spanName,
() -> {
callback.run();
return null;
});
}
/**
* Runs the provided {@code callback} inside the scope of an CLIENT span with name {@code
* spanName}.
*/
public final T runWithServerSpan(
String spanName, ThrowingSupplier callback) throws E {
return testInstrumenters.runWithServerSpan(spanName, callback);
}
/** Runs the provided {@code callback} inside the scope of a non-recording span. */
public final T runWithNonRecordingSpan(ThrowingSupplier callback)
throws E {
return testInstrumenters.runWithNonRecordingSpan(callback);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy