All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension Maven / Gradle / Ivy

There is a newer version: 2.10.0-alpha
Show newest version
/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package io.opentelemetry.instrumentation.testing.junit;

import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.context.ContextStorage;
import io.opentelemetry.instrumentation.testing.InstrumentationTestRunner;
import io.opentelemetry.instrumentation.testing.LibraryTestRunner;
import io.opentelemetry.instrumentation.testing.util.ContextStorageCloser;
import io.opentelemetry.instrumentation.testing.util.ThrowingRunnable;
import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.testing.assertj.LogRecordDataAssert;
import io.opentelemetry.sdk.testing.assertj.MetricAssert;
import io.opentelemetry.sdk.testing.assertj.TraceAssert;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import org.assertj.core.api.ListAssert;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;

public abstract class InstrumentationExtension
    implements BeforeAllCallback, BeforeEachCallback, AfterAllCallback, AfterEachCallback {

  private final InstrumentationTestRunner testRunner;

  protected InstrumentationExtension(InstrumentationTestRunner testRunner) {
    this.testRunner = testRunner;
  }

  @Override
  public void beforeAll(ExtensionContext extensionContext) throws Exception {
    testRunner.beforeTestClass();
  }

  @Override
  public void beforeEach(ExtensionContext extensionContext) {
    testRunner.clearAllExportedData();
  }

  @Override
  public void afterEach(ExtensionContext context) throws Exception {
    ContextStorage storage = ContextStorage.get();
    ContextStorageCloser.close(storage);
  }

  @Override
  public void afterAll(ExtensionContext extensionContext) throws Exception {
    testRunner.clearAllExportedData();
    testRunner.afterTestClass();
  }

  /** Return the {@link OpenTelemetry} instance used to produce telemetry data. */
  public OpenTelemetry getOpenTelemetry() {
    return testRunner.getOpenTelemetry();
  }

  /** Return a list of all captured spans. */
  public List spans() {
    return testRunner.getExportedSpans();
  }

  /** Return a list of all captured metrics. */
  public List metrics() {
    return testRunner.getExportedMetrics();
  }

  /** Return a list of all captured logs. */
  public List logRecords() {
    return testRunner.getExportedLogRecords();
  }

  /**
   * Waits for the assertion applied to all metrics of the given instrumentation and metric name to
   * pass.
   */
  public final void waitAndAssertMetrics(
      String instrumentationName, String metricName, Consumer> assertion) {
    testRunner.waitAndAssertMetrics(instrumentationName, metricName, assertion);
  }

  @SafeVarargs
  public final void waitAndAssertMetrics(
      String instrumentationName, Consumer... assertions) {
    testRunner.waitAndAssertMetrics(instrumentationName, assertions);
  }

  /**
   * Removes all captured telemetry data. After calling this method {@link #spans()} and {@link
   * #metrics()} will return empty lists until more telemetry data is captured.
   */
  public void clearData() {
    testRunner.clearAllExportedData();
  }

  /**
   * Wait until at least {@code numberOfTraces} traces are completed and return all captured traces.
   * Note that there may be more than {@code numberOfTraces} collected. This waits up to 20 seconds,
   * then times out.
   */
  public List> waitForTraces(int numberOfTraces) {
    return testRunner.waitForTraces(numberOfTraces);
  }

  /**
   * Wait until at least {@code numberOfLogRecords} log records are completed and return all
   * captured log records. Note that there may be more than {@code numberOfLogRecords} collected.
   * This waits up to 20 seconds, then times out.
   */
  public List waitForLogRecords(int numberOfLogRecords) {
    await()
        .timeout(Duration.ofSeconds(20))
        .untilAsserted(
            () ->
                assertThat(testRunner.getExportedLogRecords().size())
                    .isEqualTo(numberOfLogRecords));
    return testRunner.getExportedLogRecords();
  }

  @SafeVarargs
  @SuppressWarnings("varargs")
  public final void waitAndAssertSortedTraces(
      Comparator> traceComparator, Consumer... assertions) {
    testRunner.waitAndAssertSortedTraces(traceComparator, assertions);
  }

  public final void waitAndAssertSortedTraces(
      Comparator> traceComparator,
      Iterable> assertions) {
    testRunner.waitAndAssertSortedTraces(traceComparator, assertions);
  }

  @SafeVarargs
  @SuppressWarnings("varargs")
  public final void waitAndAssertTracesWithoutScopeVersionVerification(
      Consumer... assertions) {
    testRunner.waitAndAssertTracesWithoutScopeVersionVerification(assertions);
  }

  @SafeVarargs
  @SuppressWarnings("varargs")
  public final void waitAndAssertTraces(Consumer... assertions) {
    testRunner.waitAndAssertTraces(assertions);
  }

  public final void waitAndAssertTraces(Iterable> assertions) {
    testRunner.waitAndAssertTraces(assertions);
  }

  private void doWaitAndAssertLogRecords(List> assertions) {
    List logRecordDataList = waitForLogRecords(assertions.size());
    Iterator> assertionIterator = assertions.iterator();
    for (LogRecordData logRecordData : logRecordDataList) {
      assertionIterator.next().accept(assertThat(logRecordData));
    }
  }

  public final void waitAndAssertLogRecords(
      Iterable> assertions) {
    List> assertionsList = new ArrayList<>();
    assertions.forEach(assertionsList::add);
    doWaitAndAssertLogRecords(assertionsList);
  }

  @SafeVarargs
  @SuppressWarnings("varargs")
  public final void waitAndAssertLogRecords(Consumer... assertions) {
    doWaitAndAssertLogRecords(Arrays.asList(assertions));
  }

  /**
   * Runs the provided {@code callback} inside the scope of an INTERNAL span with name {@code
   * spanName}.
   */
  public  void runWithSpan(String spanName, ThrowingRunnable callback)
      throws E {
    testRunner.runWithSpan(spanName, callback);
  }

  /**
   * Runs the provided {@code callback} inside the scope of an INTERNAL span with name {@code
   * spanName}.
   */
  public  T runWithSpan(String spanName, ThrowingSupplier callback)
      throws E {
    return testRunner.runWithSpan(spanName, callback);
  }

  /**
   * Runs the provided {@code callback} inside the scope of an HTTP CLIENT span with name {@code
   * spanName}.
   */
  public  void runWithHttpClientSpan(
      String spanName, ThrowingRunnable callback) throws E {
    testRunner.runWithHttpClientSpan(spanName, callback);
  }

  /**
   * Runs the provided {@code callback} inside the scope of an HTTP CLIENT span with name {@code
   * spanName}.
   */
  public  T runWithHttpClientSpan(
      String spanName, ThrowingSupplier callback) throws E {
    return testRunner.runWithHttpClientSpan(spanName, callback);
  }

  /**
   * Runs the provided {@code callback} inside the scope of an CLIENT span with name {@code
   * spanName}.
   */
  public  void runWithHttpServerSpan(ThrowingRunnable callback) throws E {
    testRunner.runWithHttpServerSpan(callback);
  }

  /**
   * Runs the provided {@code callback} inside the scope of an CLIENT span with name {@code
   * spanName}.
   */
  public  T runWithHttpServerSpan(ThrowingSupplier callback)
      throws E {
    return testRunner.runWithHttpServerSpan(callback);
  }

  /** Returns whether forceFlush was called. */
  public boolean forceFlushCalled() {
    return testRunner.forceFlushCalled();
  }

  /** Returns the {@link OpenTelemetrySdk} initialized for library tests. */
  public OpenTelemetrySdk getOpenTelemetrySdk() {
    if (testRunner instanceof LibraryTestRunner) {
      return ((LibraryTestRunner) testRunner).getOpenTelemetrySdk();
    }
    throw new IllegalStateException("Can only be called from library instrumentation tests.");
  }

  protected InstrumentationTestRunner getTestRunner() {
    return testRunner;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy