[유치수] [profiler-36] ClosableAsyncHttpClient 인터셉터 추가.

git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-tomcat-profiler/trunk@3967 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
Chisu Yu
2014-06-01 01:51:20 +00:00
parent 65713c4dc7
commit ccfb7598bd
10 changed files with 697 additions and 2 deletions
+23 -1
View File
@@ -163,10 +163,30 @@
</exclusion>
</exclusions>
</dependency>
<!-- HTTP Client -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore-nio</artifactId>
<version>4.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.1.3</version>
<version>4.3</version>
<scope>provided</scope>
<exclusions>
<exclusion>
@@ -179,6 +199,8 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
@@ -16,7 +16,10 @@ import com.nhn.pinpoint.profiler.modifier.arcus.MemcachedClientModifier;
import com.nhn.pinpoint.profiler.modifier.arcus.OperationFutureModifier;
import com.nhn.pinpoint.profiler.modifier.bloc.handler.HTTPHandlerModifier;
import com.nhn.pinpoint.profiler.modifier.connector.asynchttpclient.AsyncHttpClientModifier;
import com.nhn.pinpoint.profiler.modifier.connector.httpclient4.BasicFutureModifier;
import com.nhn.pinpoint.profiler.modifier.connector.httpclient4.ClosableHttpAsyncClientModifier;
import com.nhn.pinpoint.profiler.modifier.connector.httpclient4.HttpClient4Modifier;
import com.nhn.pinpoint.profiler.modifier.connector.httpclient4.InternalHttpAsyncClientModifier;
import com.nhn.pinpoint.profiler.modifier.connector.jdkhttpconnector.HttpURLConnectionModifier;
import com.nhn.pinpoint.profiler.modifier.connector.lucynet.CompositeInvocationFutureModifier;
import com.nhn.pinpoint.profiler.modifier.connector.lucynet.DefaultInvocationFutureModifier;
@@ -110,8 +113,13 @@ public class DefaultModifierRegistry implements ModifierRegistry {
HttpURLConnectionModifier httpURLConnectionModifier = new HttpURLConnectionModifier(byteCodeInstrumentor, agent);
addModifier(httpURLConnectionModifier);
// async http connector
// ning async http client
addModifier(new AsyncHttpClientModifier(byteCodeInstrumentor, agent));
// apache nio http client
// addModifier(new InternalHttpAsyncClientModifier(byteCodeInstrumentor, agent));
addModifier(new ClosableHttpAsyncClientModifier(byteCodeInstrumentor, agent));
addModifier(new BasicFutureModifier(byteCodeInstrumentor, agent));
}
public void addArcusModifier() {
@@ -0,0 +1,62 @@
package com.nhn.pinpoint.profiler.modifier.connector.httpclient4;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.interceptor.Interceptor;
import com.nhn.pinpoint.profiler.interceptor.bci.ByteCodeInstrumentor;
import com.nhn.pinpoint.profiler.interceptor.bci.InstrumentClass;
import com.nhn.pinpoint.profiler.interceptor.bci.InstrumentException;
import com.nhn.pinpoint.profiler.modifier.AbstractModifier;
/**
*
* @author netspider
*
*/
public class BasicFutureModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public BasicFutureModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "org/apache/http/concurrent/BasicFuture";
}
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifing. {} @ {}", javassistClassName, classLoader);
}
byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
try {
InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName);
Interceptor futureGetInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor.BasicFutureGetInterceptor");
aClass.addInterceptor("get", null, futureGetInterceptor);
Interceptor futureGetInterceptor2 = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor.BasicFutureGetInterceptor");
aClass.addInterceptor("get", new String[] { "long", "java.util.concurrent.TimeUnit" }, futureGetInterceptor2);
Interceptor futureCompletedInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor.BasicFutureCompletedInterceptor");
aClass.addInterceptor("completed", new String[] { "java.lang.Object" }, futureCompletedInterceptor);
Interceptor futureFailedInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor.BasicFutureFailedInterceptor");
aClass.addInterceptor("failed", new String[] { "java.lang.Exception" }, futureFailedInterceptor);
return aClass.toBytecode();
} catch (InstrumentException e) {
logger.info("modify fail. Cause:{}", e.getMessage(), e);
return null;
}
}
}
@@ -0,0 +1,79 @@
package com.nhn.pinpoint.profiler.modifier.connector.httpclient4;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.interceptor.Interceptor;
import com.nhn.pinpoint.profiler.interceptor.bci.ByteCodeInstrumentor;
import com.nhn.pinpoint.profiler.interceptor.bci.InstrumentClass;
import com.nhn.pinpoint.profiler.interceptor.bci.InstrumentException;
import com.nhn.pinpoint.profiler.modifier.AbstractModifier;
/**
*
* @author netspider
*
*/
public class ClosableHttpAsyncClientModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public ClosableHttpAsyncClientModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "org/apache/http/impl/nio/client/CloseableHttpAsyncClient";
}
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifing. {} @ {}", javassistClassName, classLoader);
}
byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
try {
InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName);
/**
* 아래 두 메소드는 오버로드 되었으나 호출 관계가 없어 scope 없어도 됨.
*/
Interceptor executeInterceptor = byteCodeInstrumentor.newInterceptor(classLoader,
protectedDomain,
"com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor.AsyncClientExecuteInterceptor");
String[] executeParams = new String[] {
"org.apache.http.HttpHost",
"org.apache.http.HttpRequest",
"org.apache.http.protocol.HttpContext",
"org.apache.http.concurrent.FutureCallback"
};
aClass.addInterceptor("execute", executeParams, executeInterceptor);
/**
*
*/
Interceptor internalExecuteInterceptor = byteCodeInstrumentor.newInterceptor(classLoader,
protectedDomain,
"com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor.AsyncInternalClientExecuteInterceptor");
String[] internalExecuteParams = new String[] {
"org.apache.http.nio.protocol.HttpAsyncRequestProducer",
"org.apache.http.nio.protocol.HttpAsyncResponseConsumer",
"org.apache.http.concurrent.FutureCallback"
};
aClass.addInterceptor("execute", internalExecuteParams, internalExecuteInterceptor);
return aClass.toBytecode();
} catch (InstrumentException e) {
logger.info("modify fail. Cause:{}", e.getMessage(), e);
return null;
}
}
}
@@ -0,0 +1,63 @@
package com.nhn.pinpoint.profiler.modifier.connector.httpclient4;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.interceptor.Interceptor;
import com.nhn.pinpoint.profiler.interceptor.bci.ByteCodeInstrumentor;
import com.nhn.pinpoint.profiler.interceptor.bci.InstrumentClass;
import com.nhn.pinpoint.profiler.interceptor.bci.InstrumentException;
import com.nhn.pinpoint.profiler.modifier.AbstractModifier;
/**
*
* @author netspider
*
*/
@Deprecated
public class InternalHttpAsyncClientModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public InternalHttpAsyncClientModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "org/apache/http/impl/nio/client/InternalHttpAsyncClient";
}
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifing. {} @ {}", javassistClassName, classLoader);
}
byteCodeInstrumentor.checkLibrary(classLoader, javassistClassName);
try {
InstrumentClass aClass = byteCodeInstrumentor.getClass(javassistClassName);
Interceptor internalExecuteInterceptor = byteCodeInstrumentor.newInterceptor(classLoader,
protectedDomain,
"com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor.AsyncInternalClientExecuteInterceptor");
String[] internalExecuteParams = new String[] {
"org.apache.http.nio.protocol.HttpAsyncRequestProducer",
"org.apache.http.nio.protocol.HttpAsyncResponseConsumer",
"org.apache.http.protocol.HttpContext",
"org.apache.http.concurrent.FutureCallback"
};
aClass.addInterceptor("execute", internalExecuteParams, internalExecuteInterceptor);
return aClass.toBytecode();
} catch (InstrumentException e) {
logger.info("modify fail. Cause:{}", e.getMessage(), e);
return null;
}
}
}
@@ -0,0 +1,54 @@
package com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor;
import com.nhn.pinpoint.bootstrap.interceptor.TargetClassLoader;
import com.nhn.pinpoint.bootstrap.pair.NameIntValuePair;
/**
*
* suitable target method
* <pre>
* org.apache.http.impl.nio.client.CloseableHttpAsyncClient.execute(HttpHost, HttpRequest, HttpContext, FutureCallback<HttpResponse>)
* </pre>
*
* original code of method.
* <pre>
* <code>
* public Future<HttpResponse> execute(
* final HttpHost target,
* final HttpRequest request,
* final HttpContext context,
* final FutureCallback<HttpResponse> callback) {
*
* return execute(
* HttpAsyncMethods.create(target, request),
* HttpAsyncMethods.createConsumer(),
* context,
* callback);
* }
* </code>
* </pre>
*
* @author netspider
*
*/
public class AsyncClientExecuteInterceptor extends AbstractHttpRequestExecute implements TargetClassLoader {
@Override
protected NameIntValuePair<String> getHost(Object[] args) {
if (args[0] instanceof org.apache.http.HttpHost) {
final org.apache.http.HttpHost httpHost = (org.apache.http.HttpHost) args[0];
return new NameIntValuePair<String>(httpHost.getHostName(), httpHost.getPort());
} else {
return null;
}
}
@Override
protected org.apache.http.HttpRequest getHttpRequest(final Object[] args) {
if (args[1] instanceof org.apache.http.HttpRequest) {
return (org.apache.http.HttpRequest) args[1];
} else {
return null;
}
}
}
@@ -0,0 +1,100 @@
package com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor;
import org.apache.http.HttpHost;
import com.nhn.pinpoint.bootstrap.interceptor.TargetClassLoader;
import com.nhn.pinpoint.bootstrap.pair.NameIntValuePair;
/**
*
* suitable target method
*
* <pre>
* org.apache.http.impl.nio.client.InternalHttpAsyncClient.execute(HttpAsyncRequestProducer, HttpAsyncResponseConsumer<T>, HttpContext, FutureCallback<T>)
* org.apache.http.impl.nio.client.CloseableHttpAsyncClient.execute(HttpAsyncRequestProducer, HttpAsyncResponseConsumer<T>, FutureCallback<T>)
* </pre>
*
* original code of method.
*
* <pre>
* <code>
* // org.apache.http.impl.nio.client.InternalHttpAsyncClient.execute
* public <T> Future<T> execute(
* final org.apache.http.nio.protocol.HttpAsyncRequestProducer requestProducer,
* final org.apache.http.nio.protocol.HttpAsyncResponseConsumer<T> responseConsumer,
* final org.apache.http.protocol.HttpContext context,
* final org.apache.http.concurrent.FutureCallback<T> callback) {
*
* final Status status = getStatus();
* Asserts.check(status == Status.ACTIVE, "Request cannot be executed; I/O reactor status: %s", status);
*
* final BasicFuture<T> future = new BasicFuture<T>(callback);
* final HttpClientContext localcontext = HttpClientContext.adapt(context != null ? context : new BasicHttpContext());
* setupContext(localcontext);
*
* @SuppressWarnings("resource")
* final DefaultClientExchangeHandlerImpl<T> handler = new DefaultClientExchangeHandlerImpl<T>(
* this.log,
* requestProducer,
* responseConsumer,
* localcontext,
* future,
* this.connmgr,
* this.exec);
*
* try {
* handler.start();
* } catch (final Exception ex) {
* handler.failed(ex);
* }
* return future;
* }
*
* OR
*
* // org.apache.http.impl.nio.client.CloseableHttpAsyncClient.execute
* public <T> Future<T> execute(
* final HttpAsyncRequestProducer requestProducer,
* final HttpAsyncResponseConsumer<T> responseConsumer,
* final FutureCallback<T> callback) {
*
* return execute(requestProducer, responseConsumer, new BasicHttpContext(), callback);
* }
* </code>
* </pre>
*
*
* @author netspider
*
*/
public class AsyncInternalClientExecuteInterceptor extends AbstractHttpRequestExecute implements TargetClassLoader {
@Override
protected NameIntValuePair<String> getHost(Object[] args) {
if (!(args[0] instanceof org.apache.http.nio.protocol.HttpAsyncRequestProducer)) {
return null;
}
final org.apache.http.nio.protocol.HttpAsyncRequestProducer producer = (org.apache.http.nio.protocol.HttpAsyncRequestProducer) args[0];
final HttpHost httpHost = producer.getTarget();
return new NameIntValuePair<String>(httpHost.getHostName(), httpHost.getPort());
}
@Override
protected org.apache.http.HttpRequest getHttpRequest(final Object[] args) {
if (!(args[0] instanceof org.apache.http.nio.protocol.HttpAsyncRequestProducer)) {
return null;
}
final org.apache.http.nio.protocol.HttpAsyncRequestProducer producer = (org.apache.http.nio.protocol.HttpAsyncRequestProducer) args[0];
try {
/**
* FIXME org.apache.http.nio.protocol.BasicAsyncRequestProducer.
* generateRequest() 는 문제가 되지 않지만 다른 구현체는 문제가 될 수 있다.
*/
return producer.generateRequest();
} catch (Exception e) {
return null;
}
}
}
@@ -0,0 +1,97 @@
package com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor;
import com.nhn.pinpoint.bootstrap.context.Trace;
import com.nhn.pinpoint.bootstrap.context.TraceContext;
import com.nhn.pinpoint.bootstrap.interceptor.ByteCodeMethodDescriptorSupport;
import com.nhn.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.nhn.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.nhn.pinpoint.bootstrap.interceptor.TargetClassLoader;
import com.nhn.pinpoint.bootstrap.interceptor.TraceContextSupport;
import com.nhn.pinpoint.bootstrap.logging.PLogger;
import com.nhn.pinpoint.common.ServiceType;
/**
*
* suitable method
* <pre>
* org.apache.http.concurrent.BasicFuture.completed(T)
* </pre>
*
* original code of method
* <code>
* <pre>
* public boolean completed(final T result) {
* synchronized (this) {
* if (this.completed) {
* return false;
* }
* this.completed = true;
* this.result = result;
* notifyAll();
* }
* if (this.callback != null) {
* this.callback.completed(result);
* }
* return true;
* }
* </pre>
* </code>
*
* @author netspider
*
*/
public class BasicFutureCompletedInterceptor implements SimpleAroundInterceptor, ByteCodeMethodDescriptorSupport, TraceContextSupport, TargetClassLoader {
protected PLogger logger;
protected boolean isDebug;
protected TraceContext traceContext;
protected MethodDescriptor descriptor;
@Override
public void before(Object target, Object[] args) {
if (isDebug) {
logger.beforeInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
trace.traceBlockBegin();
trace.markBeforeTime();
trace.recordServiceType(ServiceType.HTTP_CLIENT_INTERNAL);
}
@Override
public void after(Object target, Object[] args, Object result) {
if (isDebug) {
logger.afterInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
try {
trace.recordApi(descriptor);
trace.recordException(result);
trace.markAfterTime();
} finally {
trace.traceBlockEnd();
}
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
@Override
public void setMethodDescriptor(MethodDescriptor descriptor) {
this.descriptor = descriptor;
traceContext.cacheApi(descriptor);
}
}
@@ -0,0 +1,97 @@
package com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor;
import com.nhn.pinpoint.bootstrap.context.Trace;
import com.nhn.pinpoint.bootstrap.context.TraceContext;
import com.nhn.pinpoint.bootstrap.interceptor.ByteCodeMethodDescriptorSupport;
import com.nhn.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.nhn.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.nhn.pinpoint.bootstrap.interceptor.TargetClassLoader;
import com.nhn.pinpoint.bootstrap.interceptor.TraceContextSupport;
import com.nhn.pinpoint.bootstrap.logging.PLogger;
import com.nhn.pinpoint.common.ServiceType;
/**
*
* suitable method
* <pre>
* org.apache.http.concurrent.BasicFuture.failed(Exception)
* </pre>
*
* original code of method
* <code>
* <pre>
* public boolean failed(final Exception exception) {
* synchronized (this) {
* if (this.completed) {
* return false;
* }
* this.completed = true;
* this.ex = exception;
* notifyAll();
* }
* if (this.callback != null) {
* this.callback.failed(exception);
* }
* return true;
* }
* </pre>
* </code>
*
* @author netspider
*
*/
public class BasicFutureFailedInterceptor implements SimpleAroundInterceptor, ByteCodeMethodDescriptorSupport, TraceContextSupport, TargetClassLoader {
protected PLogger logger;
protected boolean isDebug;
protected TraceContext traceContext;
protected MethodDescriptor descriptor;
@Override
public void before(Object target, Object[] args) {
if (isDebug) {
logger.beforeInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
trace.traceBlockBegin();
trace.markBeforeTime();
trace.recordServiceType(ServiceType.HTTP_CLIENT_INTERNAL);
}
@Override
public void after(Object target, Object[] args, Object result) {
if (isDebug) {
logger.afterInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
try {
trace.recordApi(descriptor);
trace.recordException(result);
trace.markAfterTime();
} finally {
trace.traceBlockEnd();
}
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
@Override
public void setMethodDescriptor(MethodDescriptor descriptor) {
this.descriptor = descriptor;
traceContext.cacheApi(descriptor);
}
}
@@ -0,0 +1,113 @@
package com.nhn.pinpoint.profiler.modifier.connector.httpclient4.interceptor;
import com.nhn.pinpoint.bootstrap.context.Trace;
import com.nhn.pinpoint.bootstrap.context.TraceContext;
import com.nhn.pinpoint.bootstrap.interceptor.ByteCodeMethodDescriptorSupport;
import com.nhn.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.nhn.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.nhn.pinpoint.bootstrap.interceptor.TargetClassLoader;
import com.nhn.pinpoint.bootstrap.interceptor.TraceContextSupport;
import com.nhn.pinpoint.bootstrap.logging.PLogger;
import com.nhn.pinpoint.common.ServiceType;
/**
* suitable method
*
* <pre>
* org.apache.http.concurrent.BasicFuture.get()
* org.apache.http.concurrent.BasicFuture.get(long, TimeUnit)
* </pre>
*
* <code>
* <pre>
* public synchronized T get() throws InterruptedException, ExecutionException {
* while (!this.completed) {
* wait();
* }
* return getResult();
* }
*
* public synchronized T get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
* Args.notNull(unit, "Time unit");
* final long msecs = unit.toMillis(timeout);
* final long startTime = (msecs <= 0) ? 0 : System.currentTimeMillis();
* long waitTime = msecs;
* if (this.completed) {
* return getResult();
* } else if (waitTime <= 0) {
* throw new TimeoutException();
* } else {
* for (;;) {
* wait(waitTime);
* if (this.completed) {
* return getResult();
* } else {
* waitTime = msecs - (System.currentTimeMillis() - startTime);
* if (waitTime <= 0) {
* throw new TimeoutException();
* }
* }
* }
* }
* }
* </pre>
* </code>
*
* @author netspider
*
*/
public class BasicFutureGetInterceptor implements SimpleAroundInterceptor, ByteCodeMethodDescriptorSupport, TraceContextSupport, TargetClassLoader {
protected PLogger logger;
protected boolean isDebug;
protected TraceContext traceContext;
protected MethodDescriptor descriptor;
@Override
public void before(Object target, Object[] args) {
if (isDebug) {
logger.beforeInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
trace.traceBlockBegin();
trace.markBeforeTime();
trace.recordServiceType(ServiceType.HTTP_CLIENT_INTERNAL);
}
@Override
public void after(Object target, Object[] args, Object result) {
if (isDebug) {
logger.afterInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
try {
trace.recordApi(descriptor);
trace.recordException(result);
trace.markAfterTime();
} finally {
trace.traceBlockEnd();
}
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
@Override
public void setMethodDescriptor(MethodDescriptor descriptor) {
this.descriptor = descriptor;
traceContext.cacheApi(descriptor);
}
}