diff --git a/pom.xml b/pom.xml index 1b33d2112..38cb3526d 100644 --- a/pom.xml +++ b/pom.xml @@ -163,10 +163,30 @@ + + + + org.apache.httpcomponents + httpcore + 4.3 + provided + + + org.apache.httpcomponents + httpasyncclient + 4.0 + provided + + + org.apache.httpcomponents + httpcore-nio + 4.3 + provided + org.apache.httpcomponents httpclient - 4.1.3 + 4.3 provided @@ -179,6 +199,8 @@ + + mysql mysql-connector-java diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/DefaultModifierRegistry.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/DefaultModifierRegistry.java index 1802caf68..e95c25067 100644 --- a/src/main/java/com/nhn/pinpoint/profiler/modifier/DefaultModifierRegistry.java +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/DefaultModifierRegistry.java @@ -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() { diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/BasicFutureModifier.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/BasicFutureModifier.java new file mode 100644 index 000000000..ac05f6793 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/BasicFutureModifier.java @@ -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; + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/ClosableHttpAsyncClientModifier.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/ClosableHttpAsyncClientModifier.java new file mode 100644 index 000000000..48ce73c9e --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/ClosableHttpAsyncClientModifier.java @@ -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; + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/InternalHttpAsyncClientModifier.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/InternalHttpAsyncClientModifier.java new file mode 100644 index 000000000..2132a366e --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/InternalHttpAsyncClientModifier.java @@ -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; + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/AsyncClientExecuteInterceptor.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/AsyncClientExecuteInterceptor.java new file mode 100644 index 000000000..a11aebf41 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/AsyncClientExecuteInterceptor.java @@ -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 + *
+ * org.apache.http.impl.nio.client.CloseableHttpAsyncClient.execute(HttpHost, HttpRequest, HttpContext, FutureCallback)
+ * 
+ * + * original code of method. + *
+ * 
+ * public Future execute(
+ *     final HttpHost target,
+ *     final HttpRequest request,
+ *     final HttpContext context,
+ *     final FutureCallback callback) {
+ *     
+ *     return execute(
+ *         HttpAsyncMethods.create(target, request),
+ *         HttpAsyncMethods.createConsumer(),
+ *         context,
+ *         callback);
+ * }
+ * 
+ * 
+ * + * @author netspider + * + */ +public class AsyncClientExecuteInterceptor extends AbstractHttpRequestExecute implements TargetClassLoader { + + @Override + protected NameIntValuePair 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(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; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/AsyncInternalClientExecuteInterceptor.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/AsyncInternalClientExecuteInterceptor.java new file mode 100644 index 000000000..b52e151f4 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/AsyncInternalClientExecuteInterceptor.java @@ -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 + * + *
+ * org.apache.http.impl.nio.client.InternalHttpAsyncClient.execute(HttpAsyncRequestProducer, HttpAsyncResponseConsumer, HttpContext, FutureCallback)
+ * org.apache.http.impl.nio.client.CloseableHttpAsyncClient.execute(HttpAsyncRequestProducer, HttpAsyncResponseConsumer, FutureCallback)
+ * 
+ * + * original code of method. + * + *
+ * 
+ * // org.apache.http.impl.nio.client.InternalHttpAsyncClient.execute
+ * public  Future execute(
+ *     final org.apache.http.nio.protocol.HttpAsyncRequestProducer requestProducer,
+ *     final org.apache.http.nio.protocol.HttpAsyncResponseConsumer responseConsumer,
+ * 	   final org.apache.http.protocol.HttpContext context,
+ * 	   final org.apache.http.concurrent.FutureCallback callback) {
+ * 
+ * 	   final Status status = getStatus();
+ * 	   Asserts.check(status == Status.ACTIVE, "Request cannot be executed; I/O reactor status: %s", status);
+ * 
+ * 	   final BasicFuture future = new BasicFuture(callback);
+ * 	   final HttpClientContext localcontext = HttpClientContext.adapt(context != null ? context : new BasicHttpContext());
+ * 	   setupContext(localcontext);
+ * 
+ * 	   @SuppressWarnings("resource")
+ * 	   final DefaultClientExchangeHandlerImpl handler = new DefaultClientExchangeHandlerImpl(
+ * 	       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  Future execute(
+ *     final HttpAsyncRequestProducer requestProducer,
+ *     final HttpAsyncResponseConsumer responseConsumer,
+ *     final FutureCallback callback) {
+ *     
+ *     return execute(requestProducer, responseConsumer, new BasicHttpContext(), callback);
+ * }
+ * 
+ * 
+ * + * + * @author netspider + * + */ +public class AsyncInternalClientExecuteInterceptor extends AbstractHttpRequestExecute implements TargetClassLoader { + + @Override + protected NameIntValuePair 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(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; + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureCompletedInterceptor.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureCompletedInterceptor.java new file mode 100644 index 000000000..5c45eaadc --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureCompletedInterceptor.java @@ -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 + *
+ * org.apache.http.concurrent.BasicFuture.completed(T)
+ * 
+ * + * original code of method + * + *
+ * 	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;
+ * 	}
+ * 
+ *
+ * + * @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); + } +} diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureFailedInterceptor.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureFailedInterceptor.java new file mode 100644 index 000000000..b2a082f22 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureFailedInterceptor.java @@ -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 + *
+ * org.apache.http.concurrent.BasicFuture.failed(Exception)
+ * 
+ * + * original code of method + * + *
+ * 	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;
+ * 	}
+ * 
+ *
+ * + * @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); + } +} diff --git a/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureGetInterceptor.java b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureGetInterceptor.java new file mode 100644 index 000000000..15a2ee48d --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/profiler/modifier/connector/httpclient4/interceptor/BasicFutureGetInterceptor.java @@ -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 + * + *
+ * org.apache.http.concurrent.BasicFuture.get()
+ * org.apache.http.concurrent.BasicFuture.get(long, TimeUnit)
+ * 
+ * + * + *
+ * 	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();
+ * 					}
+ * 				}
+ * 			}
+ * 		}
+ * 	}
+ * 
+ *
+ * + * @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); + } +}