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

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 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