From e8872e1bb1865b03ee3f3b969dd63423c48feff2 Mon Sep 17 00:00:00 2001 From: Qinfeng Chen Date: Wed, 17 Oct 2018 12:42:11 -0400 Subject: [PATCH] Migrate from remoting3 to tracing-java (#100) * Remove remoting3 dependency and pick up rebranded tracing-java change. * Split tracing-api & tracing implementation dependency * Add tracing sanity check for legacy remoting3 Log error and fallback to remoting3 tracing if the detected remoting3 tracer does not delegate to java-tracing properly. * Use reflection for remoting3 tracing fallback * Extract Tracer interface, java-tracing and reflective implementations * TracingInvocationEventHandler factory --- tritium-jmh/build.gradle | 1 + .../microbenchmarks/ProxyBenchmark.java | 40 ++++- .../java/com/palantir/tritium/Tritium.java | 2 +- tritium-tracing/build.gradle | 2 +- .../tritium/tracing/JavaTracingTracer.java | 32 ++++ .../tritium/tracing/ReflectiveTracer.java | 89 ++++++++++ ...mpatibleTracingInvocationEventHandler.java | 162 ++++++++++++++++++ .../com/palantir/tritium/tracing/Tracer.java | 24 +++ .../TracingInvocationEventHandler.java | 30 +++- .../tritium/tracing/ReflectiveTracerTest.java | 66 +++++++ .../TracingInvocationEventHandlerTest.java | 14 +- versions.props | 1 + 12 files changed, 442 insertions(+), 21 deletions(-) create mode 100644 tritium-tracing/src/main/java/com/palantir/tritium/tracing/JavaTracingTracer.java create mode 100644 tritium-tracing/src/main/java/com/palantir/tritium/tracing/ReflectiveTracer.java create mode 100644 tritium-tracing/src/main/java/com/palantir/tritium/tracing/RemotingCompatibleTracingInvocationEventHandler.java create mode 100644 tritium-tracing/src/main/java/com/palantir/tritium/tracing/Tracer.java create mode 100644 tritium-tracing/src/test/java/com/palantir/tritium/tracing/ReflectiveTracerTest.java diff --git a/tritium-jmh/build.gradle b/tritium-jmh/build.gradle index ec7380905..25ab0bea1 100644 --- a/tritium-jmh/build.gradle +++ b/tritium-jmh/build.gradle @@ -18,6 +18,7 @@ dependencies { jmh project(':tritium-lib') jmh 'ch.qos.logback:logback-classic' + jmh 'com.palantir.remoting3:tracing' jmh 'org.slf4j:slf4j-simple' } diff --git a/tritium-jmh/src/jmh/java/com/palantir/tritium/microbenchmarks/ProxyBenchmark.java b/tritium-jmh/src/jmh/java/com/palantir/tritium/microbenchmarks/ProxyBenchmark.java index 4697de359..7e80691af 100644 --- a/tritium-jmh/src/jmh/java/com/palantir/tritium/microbenchmarks/ProxyBenchmark.java +++ b/tritium-jmh/src/jmh/java/com/palantir/tritium/microbenchmarks/ProxyBenchmark.java @@ -16,10 +16,11 @@ package com.palantir.tritium.microbenchmarks; -import com.palantir.remoting3.tracing.AsyncSlf4jSpanObserver; -import com.palantir.remoting3.tracing.Tracer; +import com.palantir.tracing.AsyncSlf4jSpanObserver; +import com.palantir.tracing.Tracer; import com.palantir.tritium.metrics.MetricRegistries; import com.palantir.tritium.proxy.Instrumentation; +import com.palantir.tritium.tracing.RemotingCompatibleTracingInvocationEventHandler; import com.palantir.tritium.tracing.TracingInvocationEventHandler; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -59,6 +60,7 @@ public class ProxyBenchmark { private Service instrumentedWithMetrics; private Service instrumentedWithEverything; private Service instrumentedWithTracing; + private Service instrumentedWithRemoting; private ExecutorService executor; @@ -78,17 +80,20 @@ public void before() { .withMetrics(MetricRegistries.createWithHdrHistogramReservoirs()) .build(); - TracingInvocationEventHandler tracingInvocationEventHandler = new TracingInvocationEventHandler("jmh"); executor = Executors.newSingleThreadExecutor(); Tracer.subscribe("slf4j", AsyncSlf4jSpanObserver.of("test", executor)); instrumentedWithTracing = Instrumentation.builder(Service.class, raw) - .withHandler(tracingInvocationEventHandler) + .withHandler(TracingInvocationEventHandler.create("jmh")) + .build(); + + instrumentedWithRemoting = Instrumentation.builder(Service.class, raw) + .withHandler(new RemotingCompatibleTracingInvocationEventHandler("jmh", Remoting3Tracer.INSTANCE)) .build(); instrumentedWithEverything = Instrumentation.builder(Service.class, raw) .withMetrics(MetricRegistries.createWithHdrHistogramReservoirs()) .withPerformanceTraceLogging() - .withHandler(tracingInvocationEventHandler) + .withHandler(TracingInvocationEventHandler.create("jmh")) .build(); } @@ -107,17 +112,17 @@ public String raw() { return raw.echo("test"); } - @Benchmark + // @Benchmark public String instrumentedWithoutHandlers() { return instrumentedWithoutHandlers.echo("test"); } - @Benchmark + // @Benchmark public String instrumentedWithPerformanceLogging() { return instrumentedWithPerformanceLogging.echo("test"); } - @Benchmark + // @Benchmark public String instrumentedWithMetrics() { return instrumentedWithMetrics.echo("test"); } @@ -128,6 +133,11 @@ public String instrumentedWithTracing() { } @Benchmark + public String instrumentedWithRemoting() { + return instrumentedWithRemoting.echo("test"); + } + + // @Benchmark public String instrumentedWithEverything() { return instrumentedWithEverything.echo("test"); } @@ -155,4 +165,18 @@ public static void main(String[] args) throws Exception { new Runner(options).run(); } + public enum Remoting3Tracer implements com.palantir.tritium.tracing.Tracer { + INSTANCE; + + @Override + public void startSpan(String operationName) { + com.palantir.remoting3.tracing.Tracer.startSpan(operationName); + } + + @Override + public void completeSpan() { + com.palantir.remoting3.tracing.Tracer.fastCompleteSpan(); + } + + } } diff --git a/tritium-lib/src/main/java/com/palantir/tritium/Tritium.java b/tritium-lib/src/main/java/com/palantir/tritium/Tritium.java index b7aedf635..1658371ae 100644 --- a/tritium-lib/src/main/java/com/palantir/tritium/Tritium.java +++ b/tritium-lib/src/main/java/com/palantir/tritium/Tritium.java @@ -42,7 +42,7 @@ public static T instrument(Class serviceInterface, U delegat return Instrumentation.builder(serviceInterface, delegate) .withMetrics(metricRegistry) .withPerformanceTraceLogging() - .withHandler(new TracingInvocationEventHandler(serviceInterface.getName())) + .withHandler(TracingInvocationEventHandler.create(serviceInterface.getName())) .build(); } } diff --git a/tritium-tracing/build.gradle b/tritium-tracing/build.gradle index c16272477..1d2080019 100644 --- a/tritium-tracing/build.gradle +++ b/tritium-tracing/build.gradle @@ -4,9 +4,9 @@ dependencies { api project(':tritium-api') api project(':tritium-core') - api 'com.palantir.remoting3:tracing' implementation 'com.palantir.safe-logging:safe-logging' + implementation 'com.palantir.tracing:tracing' implementation 'org.slf4j:slf4j-api' testImplementation project(':tritium-test') diff --git a/tritium-tracing/src/main/java/com/palantir/tritium/tracing/JavaTracingTracer.java b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/JavaTracingTracer.java new file mode 100644 index 000000000..2970bacaa --- /dev/null +++ b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/JavaTracingTracer.java @@ -0,0 +1,32 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tritium.tracing; + +enum JavaTracingTracer implements Tracer { + INSTANCE; + + @Override + public void startSpan(String operationName) { + com.palantir.tracing.Tracer.startSpan(operationName); + } + + @Override + public void completeSpan() { + com.palantir.tracing.Tracer.fastCompleteSpan(); + } + +} diff --git a/tritium-tracing/src/main/java/com/palantir/tritium/tracing/ReflectiveTracer.java b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/ReflectiveTracer.java new file mode 100644 index 000000000..4009ebe5b --- /dev/null +++ b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/ReflectiveTracer.java @@ -0,0 +1,89 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tritium.tracing; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Throwables; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +final class ReflectiveTracer implements Tracer { + + private final Method startSpanMethod; + private final Method completeSpanMethod; + + ReflectiveTracer(Method startSpanMethod, Method completeSpanMethod) { + this.startSpanMethod = checkStartMethod(startSpanMethod); + this.completeSpanMethod = checkCompleteMethod(completeSpanMethod); + } + + @Override + public void startSpan(String operationName) { + try { + startSpanMethod.invoke(null, operationName); + } catch (ReflectiveOperationException e) { + throw throwUnchecked(e); + } + } + + @Override + public void completeSpan() { + try { + completeSpanMethod.invoke(null); + } catch (ReflectiveOperationException e) { + throw throwUnchecked(e); + } + } + + private static Method checkStartMethod(Method method) { + checkNotNull(method, "method"); + checkArgument(Modifier.isPublic(method.getModifiers()), "method must be public: %s", method); + checkArgument(Modifier.isStatic(method.getModifiers()), "method must be static: %s", method); + if (method.getParameterCount() != 1 || !String.class.equals(method.getParameterTypes()[0])) { + throw new IllegalArgumentException(String.format("startSpan method should take 1 String argument, was %s", + paramsToClassNames(method))); + } + return method; + } + + private static Method checkCompleteMethod(Method method) { + checkNotNull(method, "method"); + checkArgument(Modifier.isPublic(method.getModifiers()), "method must be public: %s", method); + checkArgument(Modifier.isStatic(method.getModifiers()), "method must be static: %s", method); + checkArgument(method.getParameterCount() == 0, + "completeSpan method should take 0 arguments, was %s", paramsToClassNames(method)); + return method; + } + + private static List paramsToClassNames(Method method) { + return Arrays.stream(method.getParameterTypes()) + .map(Class::getName) + .collect(Collectors.toList()); + } + + private static RuntimeException throwUnchecked(ReflectiveOperationException reflectionException) { + Throwable cause = reflectionException.getCause() != null ? reflectionException.getCause() : reflectionException; + Throwables.throwIfUnchecked(cause); + throw new RuntimeException(cause); + } + +} diff --git a/tritium-tracing/src/main/java/com/palantir/tritium/tracing/RemotingCompatibleTracingInvocationEventHandler.java b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/RemotingCompatibleTracingInvocationEventHandler.java new file mode 100644 index 000000000..f60565d5f --- /dev/null +++ b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/RemotingCompatibleTracingInvocationEventHandler.java @@ -0,0 +1,162 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tritium.tracing; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.palantir.logsafe.SafeArg; +import com.palantir.tritium.event.AbstractInvocationEventHandler; +import com.palantir.tritium.event.DefaultInvocationContext; +import com.palantir.tritium.event.InstrumentationProperties; +import com.palantir.tritium.event.InvocationContext; +import com.palantir.tritium.event.InvocationEventHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Objects; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class RemotingCompatibleTracingInvocationEventHandler + extends AbstractInvocationEventHandler { + + private static final Logger logger = LoggerFactory.getLogger(RemotingCompatibleTracingInvocationEventHandler.class); + + private final String component; + private final Tracer tracer; + + public RemotingCompatibleTracingInvocationEventHandler(String component, Tracer tracer) { + super((java.util.function.BooleanSupplier) InstrumentationProperties.getSystemPropertySupplier(component)); + this.component = Preconditions.checkNotNull(component, "component"); + this.tracer = Preconditions.checkNotNull(tracer, "tracer"); + } + + static InvocationEventHandler create(String component) { + return new RemotingCompatibleTracingInvocationEventHandler(component, createTracer()); + } + + @Override + public InvocationContext preInvocation(Object instance, Method method, Object[] args) { + InvocationContext context = DefaultInvocationContext.of(instance, method, args); + String operationName = getOperationName(method); + tracer.startSpan(operationName); + return context; + } + + private String getOperationName(Method method) { + return Strings.isNullOrEmpty(component) ? method.getName() : component + '.' + method.getName(); + } + + @Override + public void onSuccess(@Nullable InvocationContext context, @Nullable Object result) { + debugIfNullContext(context); + tracer.completeSpan(); + } + + @Override + public void onFailure(@Nullable InvocationContext context, @Nonnull Throwable cause) { + debugIfNullContext(context); + // TODO(davids): add Error event + tracer.completeSpan(); + } + + private static void debugIfNullContext(@Nullable InvocationContext context) { + if (context == null) { + logger.debug("Encountered null metric context likely due to exception in preInvocation"); + } + } + + private static Class loadRemoting3TracersClass() throws ClassNotFoundException { + return Thread.currentThread().getContextClassLoader().loadClass("com.palantir.remoting3.tracing.Tracers"); + } + + /** + * Reflection based check to determine what implementation of tracing to use to avoid duplicate traces as + * remoting3's tracing classes delegate functionality to tracing-java in remoting 3.43.0+ and + * remoting3.tracing.Tracers.wrap now returns a "com.palantir.tracing.Tracers" implementation. + *
    + *
  1. a) remoting3 prior to 3.43.0+ -> use reflection based remoting3 tracer
  2. + *
  3. b) remoting3 3.43.0+ -> use tracing-java
  4. + *
  5. c) no remoting3 -> use tracing-java
  6. + *
+ * + * @return true if we detect that remoting3's tracing does not delegate to tracing-java + */ + static boolean requiresRemotingFallback() { + try { + if (isUsingMultipleTracers(loadRemoting3TracersClass())) { + return true; + } + } catch (ReflectiveOperationException e) { + // expected case when remoting3 is not on classpath + return false; + } + + return false; + } + + private static boolean isUsingMultipleTracers(Class tracersClass) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + if (tracersClass != null) { + Method wrapMethod = tracersClass.getMethod("wrap", Runnable.class); + if (wrapMethod != null) { + Object wrappedTrace = wrapMethod.invoke(null, (Runnable) () -> { + }); + String expectedTracingPackage = com.palantir.tracing.Tracers.class.getPackage().getName(); + String actualTracingPackage = wrappedTrace.getClass().getPackage().getName(); + if (!Objects.equals(expectedTracingPackage, actualTracingPackage)) { + logger.error("Multiple tracing implementations detected, expected '{}' but found '{}'," + + " using legacy remoting3 tracing for backward compatibility", + SafeArg.of("expectedPackage", expectedTracingPackage), + SafeArg.of("actualPackage", actualTracingPackage)); + return true; + } + } + } + + return false; + } + + static Tracer createTracer() { + // Ugly reflection based check to determine what implementation of tracing to use to avoid duplicate + // traces as remoting3's tracing classes delegate functionality to tracing-java in remoting 3.43.0+ + // and remoting3.tracing.Tracers.wrap now returns a "com.palantir.tracing.Tracers" implementation. + // + // a) remoting3 prior to 3.43.0+ -> use reflection based remoting3 tracer + // b) remoting3 3.43.0+ -> use tracing-java + // c) no remoting3 -> use tracing-java + + try { + Class tracersClass = loadRemoting3TracersClass(); + if (isUsingMultipleTracers(tracersClass)) { + Class tracerClass = tracersClass.getClassLoader().loadClass("com.palantir.remoting3.tracing.Tracer"); + Method startSpanMethod = tracerClass.getMethod("startSpan", String.class); + Method completeSpanMethod = tracerClass.getMethod("fastCompleteSpan"); + if (startSpanMethod != null && completeSpanMethod != null) { + return new ReflectiveTracer(startSpanMethod, completeSpanMethod); + } + } + } catch (ReflectiveOperationException e) { + // expected case when remoting3 is not on classpath + logger.debug("Remoting3 unavailable, using Java tracing", e); + } + + return JavaTracingTracer.INSTANCE; + } + +} diff --git a/tritium-tracing/src/main/java/com/palantir/tritium/tracing/Tracer.java b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/Tracer.java new file mode 100644 index 000000000..c4eb3b587 --- /dev/null +++ b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/Tracer.java @@ -0,0 +1,24 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tritium.tracing; + +public interface Tracer { + + void startSpan(String operationName); + void completeSpan(); + +} diff --git a/tritium-tracing/src/main/java/com/palantir/tritium/tracing/TracingInvocationEventHandler.java b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/TracingInvocationEventHandler.java index b7ff5c9d7..13046f828 100644 --- a/tritium-tracing/src/main/java/com/palantir/tritium/tracing/TracingInvocationEventHandler.java +++ b/tritium-tracing/src/main/java/com/palantir/tritium/tracing/TracingInvocationEventHandler.java @@ -16,13 +16,14 @@ package com.palantir.tritium.tracing; +import com.google.common.base.Preconditions; import com.google.common.base.Strings; -import com.palantir.remoting3.tracing.Tracer; import com.palantir.tritium.api.functions.BooleanSupplier; import com.palantir.tritium.event.AbstractInvocationEventHandler; import com.palantir.tritium.event.DefaultInvocationContext; import com.palantir.tritium.event.InstrumentationProperties; import com.palantir.tritium.event.InvocationContext; +import com.palantir.tritium.event.InvocationEventHandler; import java.lang.reflect.Method; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -35,16 +36,35 @@ public final class TracingInvocationEventHandler extends AbstractInvocationEvent private final String component; + /** + * Constructs new tracing event handler. + * @param component component name + * @deprecated use {@link #create(String)} + */ + @Deprecated public TracingInvocationEventHandler(String component) { super((java.util.function.BooleanSupplier) getEnabledSupplier(component)); - this.component = component; + this.component = Preconditions.checkNotNull(component, "component"); + } + + /** + * Constructs new tracing event handler. + * @param component component name + * @return tracing event handler + */ + public static InvocationEventHandler create(String component) { + if (RemotingCompatibleTracingInvocationEventHandler.requiresRemotingFallback()) { + return RemotingCompatibleTracingInvocationEventHandler.create(component); + } + //noinspection deprecation + return new TracingInvocationEventHandler(component); } @Override public InvocationContext preInvocation(Object instance, Method method, Object[] args) { InvocationContext context = DefaultInvocationContext.of(instance, method, args); String operationName = getOperationName(method); - Tracer.startSpan(operationName); + com.palantir.tracing.Tracer.startSpan(operationName); return context; } @@ -55,14 +75,14 @@ private String getOperationName(Method method) { @Override public void onSuccess(@Nullable InvocationContext context, @Nullable Object result) { debugIfNullContext(context); - Tracer.fastCompleteSpan(); + com.palantir.tracing.Tracer.fastCompleteSpan(); } @Override public void onFailure(@Nullable InvocationContext context, @Nonnull Throwable cause) { debugIfNullContext(context); // TODO(davids): add Error event - Tracer.fastCompleteSpan(); + com.palantir.tracing.Tracer.fastCompleteSpan(); } private static void debugIfNullContext(@Nullable InvocationContext context) { diff --git a/tritium-tracing/src/test/java/com/palantir/tritium/tracing/ReflectiveTracerTest.java b/tritium-tracing/src/test/java/com/palantir/tritium/tracing/ReflectiveTracerTest.java new file mode 100644 index 000000000..cd832df44 --- /dev/null +++ b/tritium-tracing/src/test/java/com/palantir/tritium/tracing/ReflectiveTracerTest.java @@ -0,0 +1,66 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.tritium.tracing; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import java.lang.reflect.Method; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class ReflectiveTracerTest { + + @Test + public void createValid() throws Exception { + Method startMethod = MockTracer.class.getMethod("start", String.class); + Method completeMethod = MockTracer.class.getMethod("stop"); + ReflectiveTracer reflectiveTracer = new ReflectiveTracer(startMethod, completeMethod); + reflectiveTracer.startSpan("test"); + reflectiveTracer.completeSpan(); + } + + @Test + public void createInvalid() throws Exception { + Method validStartMethod = MockTracer.class.getMethod("start", String.class); + Method validCompleteMethod = MockTracer.class.getMethod("stop"); + Method invalidStartMethod = MockTracer.class.getMethod("badStart", Integer.class); + Method invalidCompleteMethod = MockTracer.class.getMethod("badStop", String.class); + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> new ReflectiveTracer(invalidStartMethod, validCompleteMethod)) + .withMessage("startSpan method should take 1 String argument, was [java.lang.Integer]"); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> new ReflectiveTracer(validStartMethod, invalidCompleteMethod)) + .withMessage("completeSpan method should take 0 arguments, was [java.lang.String]"); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> new ReflectiveTracer(invalidStartMethod, invalidCompleteMethod)) + .withMessage("startSpan method should take 1 String argument, was [java.lang.Integer]"); + } + + public static final class MockTracer { + public static void start(String name) {} + + public static void stop() {} + + public static void badStart(Integer id) {} + + public static void badStop(String name) {} + } + +} diff --git a/tritium-tracing/src/test/java/com/palantir/tritium/tracing/TracingInvocationEventHandlerTest.java b/tritium-tracing/src/test/java/com/palantir/tritium/tracing/TracingInvocationEventHandlerTest.java index 190a1081e..6fcf04fe8 100644 --- a/tritium-tracing/src/test/java/com/palantir/tritium/tracing/TracingInvocationEventHandlerTest.java +++ b/tritium-tracing/src/test/java/com/palantir/tritium/tracing/TracingInvocationEventHandlerTest.java @@ -23,11 +23,12 @@ import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.MoreExecutors; -import com.palantir.remoting.api.tracing.Span; -import com.palantir.remoting.api.tracing.SpanObserver; -import com.palantir.remoting3.tracing.AsyncSlf4jSpanObserver; -import com.palantir.remoting3.tracing.Tracer; +import com.palantir.tracing.AsyncSlf4jSpanObserver; +import com.palantir.tracing.Tracer; +import com.palantir.tracing.api.Span; +import com.palantir.tracing.api.SpanObserver; import com.palantir.tritium.event.InvocationContext; +import com.palantir.tritium.event.InvocationEventHandler; import com.palantir.tritium.test.TestImplementation; import com.palantir.tritium.test.TestInterface; import java.lang.reflect.Method; @@ -44,7 +45,7 @@ @RunWith(MockitoJUnitRunner.class) public class TracingInvocationEventHandlerTest { - private TracingInvocationEventHandler handler; + private InvocationEventHandler handler; private TestInterface instance; private Method method; private Object[] args; @@ -56,7 +57,8 @@ public class TracingInvocationEventHandlerTest { @Before public void before() throws Exception { executor = MoreExecutors.newDirectExecutorService(); - handler = new TracingInvocationEventHandler("testComponent"); + handler = TracingInvocationEventHandler.create("testComponent"); + assertThat(handler).isInstanceOf(TracingInvocationEventHandler.class); Tracer.subscribe("sysout", System.out::println); Tracer.subscribe("mock", mockSpanObserver); Tracer.subscribe("slf4j", AsyncSlf4jSpanObserver.of("test", executor)); diff --git a/versions.props b/versions.props index 22ce21a25..7fc810e2e 100644 --- a/versions.props +++ b/versions.props @@ -11,6 +11,7 @@ com.google.guava:* = 23.6.1-jre com.palantir.baseline:* = 0.37.3 com.palantir.remoting3:* = 3.45.0 com.palantir.safe-logging:safe-logging = 1.5.1 +com.palantir.tracing:* = 1.2.0 io.dropwizard.metrics:metrics-core = 3.2.5 junit:junit = 4.12 org.assertj:assertj-core = 3.11.1