
com.undefinedlabs.scope.rules.ScalaTestScopeAgentRule Maven / Gradle / Ivy
package com.undefinedlabs.scope.rules;
import com.undefinedlabs.scope.ScopeGlobalTracer;
import com.undefinedlabs.scope.ScopeSpanContainer;
import com.undefinedlabs.scope.events.EventFieldsFactory;
import com.undefinedlabs.scope.events.exception.ThrowableEvent;
import com.undefinedlabs.scope.rules.transformer.ScopeAgentAdvicedTransformer;
import com.undefinedlabs.scope.statistics.Statistics;
import com.undefinedlabs.scope.utils.baggage.BaggageKeys;
import com.undefinedlabs.scope.utils.baggage.BaggageValues;
import com.undefinedlabs.scope.utils.event.EventValues;
import com.undefinedlabs.scope.utils.sourcecode.ExceptionSourceCodeFactory;
import com.undefinedlabs.scope.utils.sourcecode.ExceptionSourceCodeFrame;
import com.undefinedlabs.scope.utils.tag.TagKeys;
import com.undefinedlabs.scope.utils.tag.TagValues;
import io.opentracing.Span;
import io.opentracing.Tracer;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import org.scalatest.Suite;
import org.scalatest.Suite$;
import org.scalatest.exceptions.TestFailedException;
import java.util.Collections;
import static net.bytebuddy.matcher.ElementMatchers.*;
public class ScalaTestScopeAgentRule extends AbstractScopeAgentRule {
@Override
protected Iterable extends AgentBuilder> transformers() {
final Class instrumentedClass = lookUp("org.scalatest.Suite$");
return (instrumentedClass != null) ?
Collections.singleton(newAgentBuilder()
.type(is(instrumentedClass)).transform(new ScopeAgentAdvicedTransformer(ScalaTestStartedTestAdvice.class, named("reportTestStarting")))
.type(is(instrumentedClass)).transform(new ScopeAgentAdvicedTransformer(ScalaTestSucceededTestAdvice.class, named("reportTestSucceeded")))
.type(is(instrumentedClass)).transform(new ScopeAgentAdvicedTransformer(ScalaTestFailedTestAdvice.class, named("reportTestFailed")))
.type(is(instrumentedClass)).transform(new ScopeAgentAdvicedTransformer(ScalaTestIgnoredTestAdvice.class, named("reportTestIgnored")))
.type(is(instrumentedClass)).transform(new ScopeAgentAdvicedTransformer(ScalaTestCanceledTestAdvice.class, named("reportTestCanceled"))))
: emptyCollection();
}
public static class ScalaTestStartedTestAdvice {
@Advice.OnMethodExit
public static void exit(@Advice.This Suite$ thiz, @Advice.AllArguments Object[] args) {
final Suite suite = (Suite) args[0];
final String testName = (String) args[3];
final Tracer tracer = ScopeGlobalTracer.get();
final Span span = tracer.buildSpan(testName)
.ignoreActiveSpan()
.withTag(TagKeys.COMPONENT, TagValues.Test.Framework.SCALATEST)
.withTag(TagKeys.SPAN_KIND, TagValues.SPAN_KIND_TEST)
.withTag(TagKeys.Test.TEST_NAME, testName)
.withTag(TagKeys.Test.TEST_SUITE, suite.suiteName())
.withTag(TagKeys.Test.TEST_FRAMEWORK, TagValues.Test.Framework.SCALATEST)
.withTag(TagKeys.Test.TEST_LANGUAGE, TagValues.Test.Language.SCALA)
.withTag(TagKeys.LANGUAGE, TagValues.Language.SCALA)
.start();
span.setBaggageItem(BaggageKeys.TRACE_KIND, BaggageValues.TRACE_KIND_TEST);
final ScopeSpanContainer scopeSpanContainer = new ScopeSpanContainer(span, tracer.activateSpan(span));
ScalaTestContextManager.INSTANCE.add(suite.suiteId()+"_"+testName, scopeSpanContainer);
Statistics.INSTANCE.registerStartedTestSpan(span);
}
}
public static class ScalaTestSucceededTestAdvice {
@Advice.OnMethodExit
public static void exit(@Advice.This Suite$ thiz, @Advice.AllArguments Object[] args) {
final Suite suite = (Suite) args[0];
final String testName = (String) args[3];
final ScopeSpanContainer scopeSpanContainer = ScalaTestContextManager.INSTANCE.poll(suite.suiteId()+"_"+testName);
if(scopeSpanContainer == null){
return;
}
final Span span = scopeSpanContainer.getSpan();
span.setTag(TagKeys.Test.TEST_STATUS, TagValues.Test.TEST_PASS);
span.setTag(TagKeys.ERROR, false);
span.finish();
scopeSpanContainer.getScope().close();
Statistics.INSTANCE.registerFinishedTestSpan(span);
}
}
public static class ScalaTestFailedTestAdvice {
@Advice.OnMethodExit
public static void exit(@Advice.This Suite$ thiz, @Advice.AllArguments Object[] args) {
final Suite suite = (Suite) args[0];
final Throwable throwable = (Throwable) args[2];
final String testName = (String) args[3];
final ScopeSpanContainer scopeSpanContainer = ScalaTestContextManager.INSTANCE.poll(suite.suiteId()+"_"+testName);
if(scopeSpanContainer == null){
return;
}
final Span span = scopeSpanContainer.getSpan();
final ExceptionSourceCodeFrame exceptionSourceCodeFrame = ExceptionSourceCodeFactory.INSTANCE.createFrame(throwable);
final ThrowableEvent.Builder throwableEventBuilder = ThrowableEvent.newBuilder();
final ThrowableEvent throwableEvent = throwableEventBuilder
.withEventType((exceptionSourceCodeFrame.getUserThrowable() instanceof TestFailedException) ||
(exceptionSourceCodeFrame.getUserThrowable() instanceof AssertionError)
? EventValues.Test.TEST_FAILURE
: EventValues.Test.TEST_ERROR)
.withThrowable(exceptionSourceCodeFrame.getUserThrowable())
.withSource(exceptionSourceCodeFrame.getSourceCodeFrame().getLinkPathWithMethodLine())
.build();
span.log(EventFieldsFactory.INSTANCE.createFields(throwableEvent));
span.setTag(TagKeys.Test.TEST_STATUS, TagValues.Test.TEST_FAIL);
span.setTag(TagKeys.ERROR, true);
span.finish();
scopeSpanContainer.getScope().close();
Statistics.INSTANCE.registerFinishedTestSpan(span);
}
}
public static class ScalaTestIgnoredTestAdvice {
@Advice.OnMethodExit
public static void exit(@Advice.This Suite$ thiz, @Advice.AllArguments Object[] args) {
final Suite suite = (Suite) args[0];
final String testName = (String) args[3];
final Tracer tracer = ScopeGlobalTracer.get();
final Span span = tracer.buildSpan(testName)
.ignoreActiveSpan()
.withTag(TagKeys.COMPONENT, TagValues.Test.Framework.SCALATEST)
.withTag(TagKeys.SPAN_KIND, TagValues.SPAN_KIND_TEST)
.withTag(TagKeys.Test.TEST_NAME, testName)
.withTag(TagKeys.Test.TEST_SUITE, suite.suiteName())
.withTag(TagKeys.Test.TEST_FRAMEWORK, TagValues.Test.Framework.SCALATEST)
.withTag(TagKeys.Test.TEST_LANGUAGE, TagValues.Test.Language.SCALA)
.withTag(TagKeys.LANGUAGE, TagValues.Language.SCALA)
.start();
span.setBaggageItem(BaggageKeys.TRACE_KIND, BaggageValues.TRACE_KIND_TEST);
span.setTag(TagKeys.Test.TEST_STATUS, TagValues.Test.TEST_SKIP);
span.setTag(TagKeys.ERROR, false);
span.finish();
Statistics.INSTANCE.registerFinishedTestSpan(span);
}
}
public static class ScalaTestCanceledTestAdvice {
@Advice.OnMethodExit
public static void exit(@Advice.This Suite$ thiz, @Advice.AllArguments Object[] args) {
final Suite suite = (Suite) args[0];
final Throwable throwable = (Throwable) args[2];
final String testName = (String) args[3];
final ScopeSpanContainer scopeSpanContainer = ScalaTestContextManager.INSTANCE.poll(suite.suiteId()+"_"+testName);
if(scopeSpanContainer == null){
return;
}
final Span span = scopeSpanContainer.getSpan();
final ExceptionSourceCodeFrame exceptionSourceCodeFrame = ExceptionSourceCodeFactory.INSTANCE.createFrame(throwable);
final ThrowableEvent.Builder throwableEventBuilder = ThrowableEvent.newBuilder();
final ThrowableEvent throwableEvent = throwableEventBuilder
.withEventType(EventValues.Test.TEST_CANCELED)
.withThrowable(exceptionSourceCodeFrame.getUserThrowable())
.withSource(exceptionSourceCodeFrame.getSourceCodeFrame().getLinkPathWithMethodLine())
.build();
span.log(EventFieldsFactory.INSTANCE.createFields(throwableEvent));
span.setTag(TagKeys.Test.TEST_STATUS, TagValues.Test.TEST_SKIP);
span.setTag(TagKeys.ERROR, false);
span.finish();
scopeSpanContainer.getScope().close();
Statistics.INSTANCE.registerFinishedTestSpan(span);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy