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);
}
}
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");
}
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);
}
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());
}
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());
}
Aggregations