diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/AnnotationKey.java b/commons/src/main/java/com/navercorp/pinpoint/common/AnnotationKey.java index 6e72c3e5b..3dc1aa214 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/AnnotationKey.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/AnnotationKey.java @@ -19,6 +19,10 @@ public enum AnnotationKey { API(12, "API"), API_METADATA(13, "API-METADATA"), RETURN_DATA(14, "RETRUN_DATA", true), + + CAll_URL(15, "CALL_URL"), + CAll_PARAM(16, "CALL_PARAM", true), + PROTOCAL(17, "PROTOCAL", true), // 정확한 에러 원인을 모를 경우. ERROR_API_METADATA_ERROR(10000010, "API-METADATA-ERROR"), diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/ServiceType.java b/commons/src/main/java/com/navercorp/pinpoint/common/ServiceType.java index d080d96e8..473f935e1 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/ServiceType.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/ServiceType.java @@ -53,6 +53,7 @@ public enum ServiceType { TEST_STAND_ALONE((short) 1005, "TEST_STAND_ALONE", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), TOMCAT((short) 1010, "TOMCAT", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), BLOC((short) 1020, "BLOC", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + BLOC_INTERNAL_METHOD((short) 1021, "INTERNAL_METHOD", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), /** * Database diff --git a/commons/src/main/java/com/navercorp/pinpoint/common/util/AnnotationUtils.java b/commons/src/main/java/com/navercorp/pinpoint/common/util/AnnotationUtils.java index 613cec81a..7ea8a23b1 100644 --- a/commons/src/main/java/com/navercorp/pinpoint/common/util/AnnotationUtils.java +++ b/commons/src/main/java/com/navercorp/pinpoint/common/util/AnnotationUtils.java @@ -63,6 +63,10 @@ public class AnnotationUtils { if (serviceType == ServiceType.HTTP_CLIENT_INTERNAL) { return findAnnotationBo(list, AnnotationKey.HTTP_CALL_RETRY_COUNT); } + + if (serviceType == ServiceType.BLOC_INTERNAL_METHOD) { + return findAnnotationBo(list, AnnotationKey.CAll_URL); + } // span에 해당하는 Tomcat의 경우 Span에 포함된 rpc 필드를 사용하므로 annotation에서 찾을필요가 없음. // if (span.getServiceType() == ServiceType.TOMCAT) { diff --git a/pom.xml b/pom.xml index 89307ccb9..91ff6ff33 100644 --- a/pom.xml +++ b/pom.xml @@ -349,6 +349,11 @@ lucy-bloc-http11 5.5.23 + + com.nhncorp.lucy + bloc-core + 4.0.3 + diff --git a/profiler/pom.xml b/profiler/pom.xml index f36373681..f0d6c7ee9 100644 --- a/profiler/pom.xml +++ b/profiler/pom.xml @@ -177,6 +177,12 @@ + + + com.nhncorp.lucy + bloc-core + provided + com.ibatis diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java index d9b26864f..3b4b491fe 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java @@ -18,12 +18,13 @@ import com.nhn.pinpoint.profiler.modifier.arcus.OperationFutureModifier; import com.nhn.pinpoint.profiler.modifier.bloc.handler.HTTPHandlerModifier; import com.nhn.pinpoint.profiler.modifier.bloc4.NettyInboundHandlerModifier; import com.nhn.pinpoint.profiler.modifier.bloc4.NpcHandlerModifier; +import com.nhn.pinpoint.profiler.modifier.bloc4.RequestProcessorModifier; 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.ClosableHttpClientModifier; -import com.nhn.pinpoint.profiler.modifier.connector.httpclient4.HttpClient4Modifier; import com.nhn.pinpoint.profiler.modifier.connector.httpclient4.DefaultHttpRequestRetryHandlerModifier; +import com.nhn.pinpoint.profiler.modifier.connector.httpclient4.HttpClient4Modifier; 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; @@ -218,6 +219,9 @@ public class DefaultModifierRegistry implements ModifierRegistry { NpcHandlerModifier npcHandlerModifier = new NpcHandlerModifier(byteCodeInstrumentor, agent); addModifier(npcHandlerModifier); + + RequestProcessorModifier requestProcessorModifier = new RequestProcessorModifier(byteCodeInstrumentor, agent); + addModifier(requestProcessorModifier); } public void addTomcatModifier() { diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/bloc4/RequestProcessorModifier.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/bloc4/RequestProcessorModifier.java new file mode 100644 index 000000000..b6dc219fa --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/bloc4/RequestProcessorModifier.java @@ -0,0 +1,45 @@ +package com.nhn.pinpoint.profiler.modifier.bloc4; + +import java.security.ProtectionDomain; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.nhn.pinpoint.bootstrap.Agent; +import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; +import com.nhn.pinpoint.bootstrap.instrument.InstrumentClass; +import com.nhn.pinpoint.bootstrap.instrument.InstrumentException; +import com.nhn.pinpoint.bootstrap.interceptor.Interceptor; +import com.nhn.pinpoint.profiler.modifier.AbstractModifier; + +public class RequestProcessorModifier extends AbstractModifier { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + public RequestProcessorModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + } + + @Override + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isInfoEnabled()) { + logger.info("Modifing. {}", javassistClassName); + } + + try { + InstrumentClass npcHandler = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer); + Interceptor messageReceivedInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.bloc4.interceptor.ProcessInterceptor"); + npcHandler.addInterceptor("process", new String[] {"com.nhncorp.lucy.bloc.core.processor.BlocRequest"}, messageReceivedInterceptor); + + return npcHandler.toBytecode(); + } catch (InstrumentException e) { + logger.warn("RequestProcessorModifier fail. Caused:", e.getMessage(), e); + return null; + } + } + + @Override + public String getTargetClass() { + return "com/nhncorp/lucy/bloc/core/processor/RequestProcessor"; + } +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/bloc4/interceptor/ProcessInterceptor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/bloc4/interceptor/ProcessInterceptor.java new file mode 100644 index 000000000..bc2ddff06 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/bloc4/interceptor/ProcessInterceptor.java @@ -0,0 +1,83 @@ +package com.nhn.pinpoint.profiler.modifier.bloc4.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.bootstrap.logging.PLoggerFactory; +import com.nhn.pinpoint.common.AnnotationKey; +import com.nhn.pinpoint.common.ServiceType; +import com.nhncorp.lucy.bloc.core.processor.BlocRequest; + +public class ProcessInterceptor implements SimpleAroundInterceptor, ByteCodeMethodDescriptorSupport, TraceContextSupport, TargetClassLoader { + + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private MethodDescriptor descriptor; + private TraceContext traceContext; + private ServiceType serviceType = ServiceType.INTERNAL_METHOD; + + + @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); + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args); + } + + Trace trace = traceContext.currentTraceObject(); + + if (trace == null) { + return; + } + + try { + trace.recordApi(descriptor); + trace.recordException(throwable); + + if (args[0] != null) { + BlocRequest blocRequest = (BlocRequest)args[0]; + trace.recordAttribute(AnnotationKey.CAll_URL, blocRequest.getPath()); + trace.recordAttribute(AnnotationKey.PROTOCAL, blocRequest.getProtocol()); + } + + trace.markAfterTime(); + } finally { + trace.traceBlockEnd(); + } + } + + @Override + public void setMethodDescriptor(MethodDescriptor descriptor) { + this.descriptor = descriptor; + this.traceContext.cacheApi(descriptor); + } + + @Override + public void setTraceContext(TraceContext traceContext) { + this.traceContext = traceContext; + } +} +