Search in sources :

Example 11 with InvocationContext

use of com.palantir.tritium.event.InvocationContext in project tritium by palantir.

the class InvocationEventProxy method invoke.

/**
 * Optimized to avoid excessive stack frames for readable stack traces.
 */
@Override
@Nullable
public final Object invoke(Object proxy, Method method, @Nullable Object[] nullableArgs) throws Throwable {
    Object[] arguments = nullableArgs == null ? EMPTY_ARRAY : nullableArgs;
    if (isSpecialMethod(method, arguments)) {
        return handleSpecialMethod(proxy, method, arguments);
    }
    InvocationContext context = handlePreInvocation(proxy, method, arguments);
    try {
        Object result = method.invoke(getDelegate(), arguments);
        return handleOnSuccess(context, result);
    } catch (InvocationTargetException ite) {
        throw handleOnFailure(context, ite.getCause());
    } catch (IllegalAccessException | RuntimeException | Error t) {
        throw handleOnFailure(context, t);
    }
}
Also used : InvocationContext(com.palantir.tritium.event.InvocationContext) InvocationTargetException(java.lang.reflect.InvocationTargetException) Nullable(javax.annotation.Nullable)

Example 12 with InvocationContext

use of com.palantir.tritium.event.InvocationContext in project tritium by palantir.

the class InvocationEventProxyTest method testInstrumentPreInvocation.

@Test
@SuppressWarnings("checkstyle:illegalthrows")
public void testInstrumentPreInvocation() throws Throwable {
    InvocationEventHandler<InvocationContext> testHandler = new SimpleHandler();
    InvocationEventProxy proxy = createTestProxy(testHandler);
    assertThat(proxy.invoke(this, getStringLengthMethod(), EMPTY_ARGS)).isEqualTo("test".length());
    Object result2 = proxy.handlePreInvocation(this, getStringLengthMethod(), EMPTY_ARGS);
    assertThat(result2).isInstanceOf(DefaultInvocationContext.class).asString().contains(InvocationEventProxyTest.class.getName());
    InvocationContext context = proxy.handlePreInvocation(this, getStringLengthMethod(), EMPTY_ARGS);
    assertThat(context).asString().contains("startTimeNanos").contains("instance").contains("method");
}
Also used : InvocationContext(com.palantir.tritium.event.InvocationContext) DefaultInvocationContext(com.palantir.tritium.event.DefaultInvocationContext) Test(org.junit.jupiter.api.Test)

Example 13 with InvocationContext

use of com.palantir.tritium.event.InvocationContext in project tritium by palantir.

the class InvocationEventProxyTest method testInstrumentOnFailureThrows.

@Test
@SuppressWarnings("checkstyle:illegalthrows")
public void testInstrumentOnFailureThrows() throws Throwable {
    InvocationEventHandler<InvocationContext> testHandler = new SimpleHandler() {

        @Override
        public void onSuccess(@Nullable InvocationContext _context, @Nullable Object _result) {
            throw new IllegalStateException("expected");
        }

        @Override
        public void onFailure(@Nullable InvocationContext _context, @Nonnull Throwable _cause) {
            throw new IllegalStateException("expected");
        }
    };
    InvocationEventProxy proxy = createTestProxy(testHandler);
    Object result = proxy.invoke(this, getStringLengthMethod(), EMPTY_ARGS);
    assertThat(result).isEqualTo("test".length());
    InvocationContext context = DefaultInvocationContext.of(this, getStringLengthMethod(), null);
    RuntimeException expected = new RuntimeException("expected");
    Throwable throwable = proxy.handleOnFailure(context, expected);
    assertThat(throwable).isSameAs(expected);
}
Also used : Nonnull(javax.annotation.Nonnull) InvocationContext(com.palantir.tritium.event.InvocationContext) DefaultInvocationContext(com.palantir.tritium.event.DefaultInvocationContext) Nullable(javax.annotation.Nullable) Test(org.junit.jupiter.api.Test)

Example 14 with InvocationContext

use of com.palantir.tritium.event.InvocationContext in project tritium by palantir.

the class InstrumentationTest method testThrowingHandler_failure_single.

@Test
@SuppressWarnings("unchecked")
void testThrowingHandler_failure_single() {
    InvocationEventHandler<InvocationContext> handler = Mockito.mock(InvocationEventHandler.class);
    when(handler.isEnabled()).thenReturn(true);
    when(handler.preInvocation(any(), any(), any())).thenThrow(new RuntimeException());
    Runnable wrapped = Instrumentation.builder(Runnable.class, () -> {
        throw new SafeRuntimeException("expected");
    }).withHandler(handler).build();
    assertThatCode(wrapped::run).isExactlyInstanceOf(SafeRuntimeException.class).hasMessage("expected");
    verify(handler).isEnabled();
    verify(handler).preInvocation(any(), any(), any());
    verify(handler).onFailure(isNull(), any());
}
Also used : SafeRuntimeException(com.palantir.logsafe.exceptions.SafeRuntimeException) SafeRuntimeException(com.palantir.logsafe.exceptions.SafeRuntimeException) InvocationContext(com.palantir.tritium.event.InvocationContext) DefaultInvocationContext(com.palantir.tritium.event.DefaultInvocationContext) Test(org.junit.jupiter.api.Test)

Example 15 with InvocationContext

use of com.palantir.tritium.event.InvocationContext in project tritium by palantir.

the class TritiumAnnotationProcessor method createMethod.

private static void createMethod(MethodElements method, TypeSpec.Builder typeBuilder, IdentityHashMap<MethodElements, String> methodToStaticFieldName) {
    String methodName = method.element().getSimpleName().toString();
    TypeName returnType = TypeName.get(method.type().getReturnType());
    boolean isVoidMethod = method.type().getReturnType().getKind() == TypeKind.VOID;
    String parameterString = method.element().getParameters().stream().map(param -> param.getSimpleName().toString()).collect(Collectors.joining(", "));
    ImmutableSet<String> parameters = method.element().getParameters().stream().map(param -> param.getSimpleName().toString()).collect(ImmutableSet.toImmutableSet());
    String throwableName = Parameters.disambiguate("throwable", parameters);
    String contextName = Parameters.disambiguate("invocationContext", parameters);
    String returnValueName = Parameters.disambiguate("returnValue", parameters);
    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(methodName).addAnnotation(Override.class).addModifiers(Modifier.PUBLIC).addTypeVariables(Lists.transform(method.element().getTypeParameters(), TypeVariableName::get)).returns(returnType).beginControlFlow("if (this.$N.isEnabled())", HANDLER_NAME).addStatement("$T $N = $T.pre(this.$N, this.$N, this, $N, new Object[]{$L})", InvocationContext.class, contextName, Handlers.class, HANDLER_NAME, FILTER_NAME, Preconditions.checkNotNull(methodToStaticFieldName.get(method), "missing name"), parameterString).beginControlFlow("try");
    if (method.element().getAnnotation(Deprecated.class) != null) {
        methodBuilder = methodBuilder.addAnnotation(Deprecated.class);
    }
    for (int i = 0; i < method.type().getThrownTypes().size(); i++) {
        TypeMirror type = method.type().getThrownTypes().get(i);
        methodBuilder.addException(TypeName.get(type));
    }
    StringBuilder statement = new StringBuilder().append("this.").append(DELEGATE_NAME).append(".").append(methodName).append("(");
    for (int i = 0; i < method.element().getParameters().size(); i++) {
        TypeMirror param = method.type().getParameterTypes().get(i);
        String paramName = method.element().getParameters().get(i).getSimpleName().toString();
        methodBuilder.addParameter(TypeName.get(param), paramName);
    }
    String delegateInvocation = statement.append(parameterString).append(")").toString();
    if (isVoidMethod) {
        methodBuilder.addStatement(delegateInvocation).addStatement("$T.onSuccess(this.$N, $N)", Handlers.class, HANDLER_NAME, contextName);
    } else {
        methodBuilder.addStatement("$T $N = $L", returnType, returnValueName, delegateInvocation).addStatement("$T.onSuccess(this.$N, $N, returnValue)", Handlers.class, HANDLER_NAME, contextName).addStatement("return $N", returnValueName);
    }
    methodBuilder.nextControlFlow("catch ($T $N)", Throwable.class, throwableName).addStatement("$T.onFailure(this.$N, $N, $N)", Handlers.class, HANDLER_NAME, contextName, throwableName).addStatement("throw $N", throwableName).endControlFlow().nextControlFlow("else").addStatement(isVoidMethod ? "$L" : "return $L", delegateInvocation).endControlFlow();
    typeBuilder.addMethod(methodBuilder.build());
}
Also used : Handlers(com.palantir.tritium.event.Handlers) AbstractProcessor(javax.annotation.processing.AbstractProcessor) Modifier(javax.lang.model.element.Modifier) InstrumentationFilter(com.palantir.tritium.api.event.InstrumentationFilter) ClassName(com.squareup.javapoet.ClassName) TypeElement(javax.lang.model.element.TypeElement) Instrument(com.palantir.tritium.annotations.Instrument) Elements(javax.lang.model.util.Elements) InvocationContext(com.palantir.tritium.event.InvocationContext) Generated(javax.annotation.processing.Generated) Map(java.util.Map) InstrumentationBuilder(com.palantir.tritium.annotations.internal.InstrumentationBuilder) SimpleElementVisitor8(javax.lang.model.util.SimpleElementVisitor8) Messager(javax.annotation.processing.Messager) ImmutableSet(com.google.common.collect.ImmutableSet) ParameterSpec(com.squareup.javapoet.ParameterSpec) IdentityHashMap(java.util.IdentityHashMap) GoetheException(com.palantir.goethe.GoetheException) Set(java.util.Set) Element(javax.lang.model.element.Element) Types(javax.lang.model.util.Types) Collectors(java.util.stream.Collectors) TypeKind(javax.lang.model.type.TypeKind) JavaFile(com.squareup.javapoet.JavaFile) SourceVersion(javax.lang.model.SourceVersion) List(java.util.List) InvocationEventHandler(com.palantir.tritium.event.InvocationEventHandler) Filer(javax.annotation.processing.Filer) TypeName(com.squareup.javapoet.TypeName) TypeVariable(javax.lang.model.type.TypeVariable) FieldSpec(com.squareup.javapoet.FieldSpec) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Kind(javax.tools.Diagnostic.Kind) Lists(com.google.common.collect.Lists) DeclaredType(javax.lang.model.type.DeclaredType) Nullable(javax.annotation.Nullable) Goethe(com.palantir.goethe.Goethe) Name(javax.lang.model.element.Name) TypeVariableName(com.squareup.javapoet.TypeVariableName) ElementKind(javax.lang.model.element.ElementKind) ExecutableType(javax.lang.model.type.ExecutableType) MethodSpec(com.squareup.javapoet.MethodSpec) ExecutableElement(javax.lang.model.element.ExecutableElement) Throwables(com.google.common.base.Throwables) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) TypeSpec(com.squareup.javapoet.TypeSpec) TaggedMetricRegistry(com.palantir.tritium.metrics.registry.TaggedMetricRegistry) TypeMirror(javax.lang.model.type.TypeMirror) RoundEnvironment(javax.annotation.processing.RoundEnvironment) AnnotationSpec(com.squareup.javapoet.AnnotationSpec) ProcessingEnvironment(javax.annotation.processing.ProcessingEnvironment) Preconditions(com.palantir.logsafe.Preconditions) TypeName(com.squareup.javapoet.TypeName) ParameterizedTypeName(com.squareup.javapoet.ParameterizedTypeName) MethodSpec(com.squareup.javapoet.MethodSpec) Handlers(com.palantir.tritium.event.Handlers) TypeMirror(javax.lang.model.type.TypeMirror) InvocationContext(com.palantir.tritium.event.InvocationContext)

Aggregations

InvocationContext (com.palantir.tritium.event.InvocationContext)20 Test (org.junit.jupiter.api.Test)16 DefaultInvocationContext (com.palantir.tritium.event.DefaultInvocationContext)14 SafeRuntimeException (com.palantir.logsafe.exceptions.SafeRuntimeException)5 Nullable (javax.annotation.Nullable)4 DefaultTaggedMetricRegistry (com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry)3 ImmutableSet (com.google.common.collect.ImmutableSet)2 Span (com.palantir.tracing.api.Span)2 TestImplementation (com.palantir.tritium.test.TestImplementation)2 TestInterface (com.palantir.tritium.test.TestInterface)2 Set (java.util.Set)2 MetricRegistry (com.codahale.metrics.MetricRegistry)1 Throwables (com.google.common.base.Throwables)1 Lists (com.google.common.collect.Lists)1 Goethe (com.palantir.goethe.Goethe)1 GoetheException (com.palantir.goethe.GoetheException)1 Preconditions (com.palantir.logsafe.Preconditions)1 Instrument (com.palantir.tritium.annotations.Instrument)1 InstrumentationBuilder (com.palantir.tritium.annotations.internal.InstrumentationBuilder)1 InstrumentationFilter (com.palantir.tritium.api.event.InstrumentationFilter)1