in instrumentation/src/main/java/com/uber/data/kafka/instrumentation/Instrumentation.java [147:198]
public <T, E extends Exception> T withException(
Logger logger,
Scope scope,
@Nullable Tracer tracer,
ThrowingSupplier<T, E> supplier,
Function<T, Boolean> resultChecker,
String name,
String... tags)
throws E {
@Nullable Span span = null;
if (tracer != null) {
Span parentSpan = tracer.activeSpan();
span = startSpan(tracer, parentSpan, name);
}
long startNs = System.nanoTime();
boolean isFailure = false;
Closeable tracing = getTracingScope(tracer, span);
try {
T t = supplier.get();
try {
boolean success = resultChecker.apply(t);
if (!success) {
logAndMetricsFailure(logger, scope, System.nanoTime() - startNs, name, tags);
isFailure = true;
}
} catch (Throwable ignored) {
// treats exception as success, so we don't set isFailure.
}
return t;
} catch (RuntimeException | Error e) {
isFailure = true;
logAndMetricsFailure(logger, scope, e, System.nanoTime() - startNs, name, tags);
throw e;
} catch (Exception ex) {
isFailure = true;
// supplier can only return type E for checked exception so we can safely cast to E.
@SuppressWarnings("unchecked")
E e = (E) ex;
logAndMetricsFailure(logger, scope, e, System.nanoTime() - startNs, name, tags);
throw e;
} finally {
if (!isFailure) {
logAndMetricsSuccess(logger, scope, System.nanoTime() - startNs, name, tags);
}
// tracing implements Closeable interface which may throw IOException, but
// the actual implementation of tracer scope never throws IOException so we can use safeClose.
safeClose(tracing);
if (span != null) {
span.finish();
}
}
}