From bc55b837c1dd9ffae4d340079b08aabe1e15f7a7 Mon Sep 17 00:00:00 2001 From: Jaehong Kim Date: Fri, 24 Jul 2015 14:43:36 +0900 Subject: [PATCH 1/3] add to denpendy in pom.xml --- plugins/pom.xml | 6 ++++++ pom.xml | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/plugins/pom.xml b/plugins/pom.xml index 1f50dee20..431dad2d2 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -25,6 +25,7 @@ thrift user arcus + google-httpclient @@ -93,6 +94,11 @@ pinpoint-arcus-plugin ${project.version} + + com.navercorp.pinpoint + pinpoint-google-httpclient-plugin + ${project.version} + diff --git a/pom.xml b/pom.xml index eddb5f518..e5c47b1b0 100644 --- a/pom.xml +++ b/pom.xml @@ -450,6 +450,11 @@ 3.1 + + com.google.http-client + google-http-client + 1.20.0 + redis.clients From 7be5b92d2a2210ab16c9a3177a0b2ab057595637 Mon Sep 17 00:00:00 2001 From: Jaehong Kim Date: Fri, 24 Jul 2015 14:52:42 +0900 Subject: [PATCH 2/3] add google httpclient plugin --- plugins/google-httpclient/.gitignore | 5 + plugins/google-httpclient/clover.license | 5 + plugins/google-httpclient/pom.xml | 30 +++ .../httpclient/HttpClientConstants.java | 32 +++ .../google/httpclient/HttpClientPlugin.java | 80 +++++++ .../httpclient/HttpClientPluginConfig.java | 29 +++ .../httpclient/HttpClientTypeProvider.java | 31 +++ ...euteAsyncMethodInnerClassMethodFilter.java | 30 +++ ...MethodInnerClassCallMethodInterceptor.java | 29 +++ ...ethodInnerClassConstructorInterceptor.java | 61 ++++++ ...pRequestExecuteAsyncMethodInterceptor.java | 85 ++++++++ .../HttpRequestExecuteMethodInterceptor.java | 25 +++ ...p.pinpoint.bootstrap.plugin.ProfilerPlugin | 1 + ...inpoint.common.trace.TraceMetadataProvider | 1 + .../src/test/resources/pinpoint.config | 205 ++++++++++++++++++ 15 files changed, 649 insertions(+) create mode 100644 plugins/google-httpclient/.gitignore create mode 100644 plugins/google-httpclient/clover.license create mode 100644 plugins/google-httpclient/pom.xml create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientConstants.java create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPlugin.java create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPluginConfig.java create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientTypeProvider.java create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpRequestExceuteAsyncMethodInnerClassMethodFilter.java create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor.java create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor.java create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInterceptor.java create mode 100644 plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteMethodInterceptor.java create mode 100644 plugins/google-httpclient/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin create mode 100644 plugins/google-httpclient/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider create mode 100644 plugins/google-httpclient/src/test/resources/pinpoint.config diff --git a/plugins/google-httpclient/.gitignore b/plugins/google-httpclient/.gitignore new file mode 100644 index 000000000..8c2d47305 --- /dev/null +++ b/plugins/google-httpclient/.gitignore @@ -0,0 +1,5 @@ +/target/ +/.settings/ +/.classpath +/.project +/*.iml diff --git a/plugins/google-httpclient/clover.license b/plugins/google-httpclient/clover.license new file mode 100644 index 000000000..569fa6175 --- /dev/null +++ b/plugins/google-httpclient/clover.license @@ -0,0 +1,5 @@ +RMRqrdbgbKFhbaVnDxHUdDQvrOQXxIBklnvcmahheubVC +mh2KM35CLkwUHS4DH7QVhxy52J5hnWbyEm6Cyd3KkF + 4.0.0 + + com.navercorp.pinpoint + pom + ../.. + 1.5.0-SNAPSHOT + + + pinpoint-google-httpclient-plugin + pinpoint-google-httpclient-plugin + jar + + + + com.navercorp.pinpoint + pinpoint-bootstrap + provided + + + + + + com.google.http-client + google-http-client + provided + + + diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientConstants.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientConstants.java new file mode 100644 index 000000000..49aec2d4f --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientConstants.java @@ -0,0 +1,32 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient; + + +/** + * + * @author jaehong.kim + * + */ +public interface HttpClientConstants { + public static final String METADATA_END_POINT = "endPoint"; + public static final String METADATA_DESTINATION_ID = "destinationId"; + public static final String METADATA_ASYNC_TRACE_ID = "asyncTraceId"; + public static final String FIELD_REQUEST_PRODUCER = "requestProducer"; + public static final String FIELD_RESULT_FUTURE = "resultFuture"; + + public static final String EXECUTE_ASYNC_SCOPE = "ExecuteAsyncScope"; +} diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPlugin.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPlugin.java new file mode 100644 index 000000000..0285bbe23 --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPlugin.java @@ -0,0 +1,80 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient; + +import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers; +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin; +import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassConditions; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassFileTransformerBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConditionalClassFileTransformerBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConditionalClassFileTransformerSetup; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConstructorTransformerBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerExceptionHandler; + +/** + * @author jaehong.kim + * + */ +public class HttpClientPlugin implements ProfilerPlugin, HttpClientConstants { + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + + @Override + public void setup(ProfilerPluginContext context) { + addHttpRequestClass(context); + addHttpRequestExecuteAsyncMethodInnerClass(context); + } + + private void addHttpRequestClass(ProfilerPluginContext context) { + final ClassFileTransformerBuilder classBuilder = context.getClassFileTransformerBuilder("com.google.api.client.http.HttpRequest"); + + MethodTransformerBuilder executeMethodBuilder = classBuilder.editMethod("execute"); + executeMethodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteMethodInterceptor"); + + MethodTransformerBuilder executeAsyncMethodBuilder = classBuilder.editMethod("executeAsync", "java.util.concurrent.Executor"); + executeAsyncMethodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInterceptor"); + + context.addClassFileTransformer(classBuilder.build()); + } + + private void addHttpRequestExecuteAsyncMethodInnerClass(ProfilerPluginContext context) { + final ClassFileTransformerBuilder classBuilder = context.getClassFileTransformerBuilder("com.google.api.client.http.HttpRequest$1"); + classBuilder.injectMetadata(METADATA_ASYNC_TRACE_ID); + + ConstructorTransformerBuilder constructorBuilder = classBuilder.editConstructor("com.google.api.client.http.HttpRequest"); + constructorBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor"); + + classBuilder.conditional(ClassConditions.hasMethod("call", "com.google.api.client.http.HttpResponse"),new ConditionalClassFileTransformerSetup() { + + @Override + public void setup(ConditionalClassFileTransformerBuilder conditional) { + MethodTransformerBuilder methodBuilder = conditional.editMethods(new HttpRequestExceuteAsyncMethodInnerClassMethodFilter()); + methodBuilder.exceptionHandler(new MethodTransformerExceptionHandler() { + public void handle(String targetClassName, String targetMethodName, String[] targetMethodParameterTypes, Throwable exception) throws Throwable { + if (logger.isWarnEnabled()) { + logger.warn("[HttpClientPlugin] Unsupported method " + targetClassName + "." + targetMethodName, exception); + } + } + }); + methodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor"); + } + }); + context.addClassFileTransformer(classBuilder.build()); + } +} \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPluginConfig.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPluginConfig.java new file mode 100644 index 000000000..73b0b6d34 --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPluginConfig.java @@ -0,0 +1,29 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient; + +import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; + +/** + * + * @author jaehong.kim + * + */ +public class HttpClientPluginConfig { + + public HttpClientPluginConfig(ProfilerConfig src) { + } +} diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientTypeProvider.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientTypeProvider.java new file mode 100644 index 000000000..805485a38 --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientTypeProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient; + +import com.navercorp.pinpoint.common.trace.TraceMetadataProvider; +import com.navercorp.pinpoint.common.trace.TraceMetadataSetupContext; + +/** + * + * @author jaehong.kim + * + */ +public class HttpClientTypeProvider implements TraceMetadataProvider, HttpClientConstants{ + + @Override + public void setup(TraceMetadataSetupContext context) { + } +} diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpRequestExceuteAsyncMethodInnerClassMethodFilter.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpRequestExceuteAsyncMethodInnerClassMethodFilter.java new file mode 100644 index 000000000..d79960bd5 --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpRequestExceuteAsyncMethodInnerClassMethodFilter.java @@ -0,0 +1,30 @@ +package com.navercorp.pinpoint.plugin.google.httpclient; + +import java.lang.reflect.Modifier; + +import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; +import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo; + +public class HttpRequestExceuteAsyncMethodInnerClassMethodFilter implements MethodFilter { + private static final int SYNTHETIC = 0x00001000; + + @Override + public boolean accept(MethodInfo method) { + final int modifiers = method.getModifiers(); + + if (isSynthetic(modifiers) || !Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + return REJECT; + } + + final String name = method.getName(); + if (name.equals("call")) { + return ACCEPT; + } + + return REJECT; + } + + private boolean isSynthetic(int mod) { + return (mod & SYNTHETIC) != 0; + } +} \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor.java new file mode 100644 index 000000000..d8c89ffe0 --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor.java @@ -0,0 +1,29 @@ +package com.navercorp.pinpoint.plugin.google.httpclient.interceptor; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId; +import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.interceptor.SpanAsyncEventSimpleAroundInterceptor; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name; +import com.navercorp.pinpoint.common.trace.ServiceType; +import com.navercorp.pinpoint.plugin.google.httpclient.HttpClientConstants; + +public class HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor extends SpanAsyncEventSimpleAroundInterceptor { + + public HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor(TraceContext traceContext, MethodDescriptor descriptor, @Name(HttpClientConstants.METADATA_ASYNC_TRACE_ID) MetadataAccessor asyncTraceIdAccessor) { + super(traceContext, descriptor, asyncTraceIdAccessor); + } + + @Override + protected void doInBeforeTrace(SpanEventRecorder recorder, AsyncTraceId asyncTraceId, Object target, Object[] args) { + } + + @Override + protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) { + recorder.recordApi(methodDescriptor); + recorder.recordServiceType(ServiceType.HTTP_CLIENT_INTERNAL); + recorder.recordException(throwable); + } +} \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor.java new file mode 100644 index 000000000..ade90e6e8 --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor.java @@ -0,0 +1,61 @@ +package com.navercorp.pinpoint.plugin.google.httpclient.interceptor; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor; +import com.navercorp.pinpoint.bootstrap.interceptor.group.ExecutionPolicy; +import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroup; +import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation; +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name; +import com.navercorp.pinpoint.plugin.google.httpclient.HttpClientConstants; + +@Group(value = HttpClientConstants.EXECUTE_ASYNC_SCOPE, executionPoint = ExecutionPolicy.ALWAYS) +public class HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor implements SimpleAroundInterceptor, HttpClientConstants { + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final MetadataAccessor asyncTraceIdAccessor; + private InterceptorGroup interceptorGroup; + + public HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor(TraceContext traceContext, MethodDescriptor descriptor, @Name(HttpClientConstants.METADATA_ASYNC_TRACE_ID) MetadataAccessor asyncTraceIdAccessor, InterceptorGroup interceptorGroup) { + this.asyncTraceIdAccessor = asyncTraceIdAccessor; + this.interceptorGroup = interceptorGroup; + } + + @Override + public void before(Object target, Object[] args) { + if (isDebug) { + logger.beforeInterceptor(target, args); + } + + try { + if (!validate(target, args)) { + return; + } + + InterceptorGroupInvocation transaction = interceptorGroup.getCurrentInvocation(); + AsyncTraceId asyncTraceId = (AsyncTraceId) transaction.getAttachment(); + asyncTraceIdAccessor.set(target, asyncTraceId); + } catch (Throwable t) { + logger.warn("Failed to before process. {}", t.getMessage(), t); + } + } + + private boolean validate(final Object target, final Object[] args) { + if (!asyncTraceIdAccessor.isApplicable(target)) { + logger.debug("Invalid target object. Need metadata accessor({}).", METADATA_ASYNC_TRACE_ID); + return false; + } + + return true; + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + } +} \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInterceptor.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInterceptor.java new file mode 100644 index 000000000..20f5cb235 --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInterceptor.java @@ -0,0 +1,85 @@ +package com.navercorp.pinpoint.plugin.google.httpclient.interceptor; + +import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId; +import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; +import com.navercorp.pinpoint.bootstrap.context.Trace; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor; +import com.navercorp.pinpoint.bootstrap.interceptor.group.ExecutionPolicy; +import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroup; +import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation; +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group; +import com.navercorp.pinpoint.common.trace.ServiceType; +import com.navercorp.pinpoint.plugin.google.httpclient.HttpClientConstants; + +@Group(value = HttpClientConstants.EXECUTE_ASYNC_SCOPE, executionPoint = ExecutionPolicy.ALWAYS) +public class HttpRequestExecuteAsyncMethodInterceptor implements SimpleAroundInterceptor { + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private TraceContext traceContext; + private MethodDescriptor methodDescriptor; + private InterceptorGroup interceptorGroup; + + public HttpRequestExecuteAsyncMethodInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, InterceptorGroup interceptorGroup) { + this.traceContext = traceContext; + this.methodDescriptor = methodDescriptor; + this.interceptorGroup = interceptorGroup; + } + + @Override + public void before(Object target, Object[] args) { + if (isDebug) { + logger.beforeInterceptor(target, args); + } + + final Trace trace = traceContext.currentTraceObject(); + if (trace == null) { + return; + } + + SpanEventRecorder recorder = trace.traceBlockBegin(); + try { + // set asynchronous trace + final AsyncTraceId asyncTraceId = trace.getAsyncTraceId(); + recorder.recordNextAsyncId(asyncTraceId.getAsyncId()); + + // set async id. + InterceptorGroupInvocation transaction = interceptorGroup.getCurrentInvocation(); + transaction.setAttachment(asyncTraceId); + if (isDebug) { + logger.debug("Set asyncTraceId metadata {}", asyncTraceId); + } + } catch (Throwable t) { + logger.warn("Failed to before process. {}", t.getMessage(), t); + } + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args); + } + + final Trace trace = traceContext.currentTraceObject(); + if (trace == null) { + return; + } + + try { + SpanEventRecorder recorder = trace.currentSpanEventRecorder(); + recorder.recordApi(methodDescriptor); + recorder.recordServiceType(ServiceType.HTTP_CLIENT_INTERNAL); + recorder.recordException(throwable); + + // remove async id. + InterceptorGroupInvocation transaction = interceptorGroup.getCurrentInvocation(); + transaction.removeAttachment(); + } finally { + trace.traceBlockEnd(); + } + } +} \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteMethodInterceptor.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteMethodInterceptor.java new file mode 100644 index 000000000..31fd3837d --- /dev/null +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteMethodInterceptor.java @@ -0,0 +1,25 @@ +package com.navercorp.pinpoint.plugin.google.httpclient.interceptor; + +import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin; +import com.navercorp.pinpoint.common.trace.ServiceType; + +public class HttpRequestExecuteMethodInterceptor extends SpanEventSimpleAroundInterceptorForPlugin { + + public HttpRequestExecuteMethodInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { + super(traceContext, descriptor); + } + + @Override + protected void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) { + } + + @Override + protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) { + recorder.recordApi(methodDescriptor); + recorder.recordServiceType(ServiceType.HTTP_CLIENT_INTERNAL); + recorder.recordException(throwable); + } +} \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin b/plugins/google-httpclient/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin new file mode 100644 index 000000000..0d80403d7 --- /dev/null +++ b/plugins/google-httpclient/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin @@ -0,0 +1 @@ +com.navercorp.pinpoint.plugin.google.httpclient.HttpClientPlugin \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider b/plugins/google-httpclient/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider new file mode 100644 index 000000000..2342d2d87 --- /dev/null +++ b/plugins/google-httpclient/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider @@ -0,0 +1 @@ +com.navercorp.pinpoint.plugin.google.httpclient.HttpClientTypeProvider \ No newline at end of file diff --git a/plugins/google-httpclient/src/test/resources/pinpoint.config b/plugins/google-httpclient/src/test/resources/pinpoint.config new file mode 100644 index 000000000..37524ece0 --- /dev/null +++ b/plugins/google-httpclient/src/test/resources/pinpoint.config @@ -0,0 +1,205 @@ +# +# Pinpoint agent configuration +# + +########################################################### +# Collector server # +########################################################### +profiler.collector.ip=127.0.0.1 + +# placeHolder support "${key}" +profiler.collector.span.ip=${profiler.collector.ip} +profiler.collector.span.port=9996 + +# placeHolder support "${key}" +profiler.collector.stat.ip=${profiler.collector.ip} +profiler.collector.stat.port=9995 + +# placeHolder support "${key}" +profiler.collector.tcp.ip=${profiler.collector.ip} +profiler.collector.tcp.port=9994 + + +########################################################### +# Profiler Global Configuration # +########################################################### +profiler.enable=true + +profiler.jvm.collect.interval=1000 + +profiler.sampling.enable=true +profiler.sampling.rate=1 + +profiler.io.buffering.enable=true +profiler.io.buffering.buffersize=20 + + + +profiler.spandatasender.write.queue.size=5120 +#profiler.spandatasender.socket.sendbuffersize=1048576 +#profiler.spandatasender.socket.timeout=3000 +profiler.spandatasender.chunk.size=16384 + +profiler.statdatasender.write.queue.size=5120 +#profiler.statdatasender.socket.sendbuffersize=1048576 +#profiler.statdatasender.socket.timeout=3000 +profiler.statdatasender.chunk.size=16384 + +profiler.agentInfo.send.retry.interval=300000 + +profiler.tcpdatasender.command.accept.enable=true + +########################################################### +# application type # +########################################################### +#profiler.applicationservertype=TOMCAT +#profiler.applicationservertype=BLOC + + +########################################################### +# user defined classes # +########################################################### +profiler.include=com.navercorp.pinpoint.testweb.controller.*,com.navercorp.pinpoint.testweb.MyClass + +########################################################### +# TOMCAT # +########################################################### +profiler.tomcat.hidepinpointheader=true +#naver standard l7 check +profiler.tomcat.excludeurl=/monitor/l7check.html +#profiler.tomcat.excludeurl=/aa/test.html, /bb/exclude.html + +########################################################### +# JDBC # +########################################################### +profiler.jdbc=true +profiler.jdbc.sqlcachesize=1024 +profiler.jdbc.maxsqlbindvaluesize=1024 + +# +# MYSQL +# +profiler.jdbc.mysql=true +profiler.jdbc.mysql.setautocommit=true +profiler.jdbc.mysql.commit=true +profiler.jdbc.mysql.rollback=true + +# +# MSSQL Jtds +# +profiler.jdbc.jtds=true +profiler.jdbc.jtds.setautocommit=true +profiler.jdbc.jtds.commit=true +profiler.jdbc.jtds.rollback=true + +# +# Oracle +# +profiler.jdbc.oracle=true +profiler.jdbc.oracle.setautocommit=true +profiler.jdbc.oracle.commit=true +profiler.jdbc.oracle.rollback=true + +# +# CUBRID +# +profiler.jdbc.cubrid=true +profiler.jdbc.cubrid.setautocommit=true +profiler.jdbc.cubrid.commit=true +profiler.jdbc.cubrid.rollback=true + +# +# DBCP +# +profiler.jdbc.dbcp=true +profiler.jdbc.dbcp.connectionclose=true + + +########################################################### +# Apache HTTP Client 4.x # +########################################################### +profiler.apache.httpclient4=true + +profiler.apache.httpclient4.cookie=true +profiler.apache.httpclient4.cookie.dumptype=ALWAYS +profiler.apache.httpclient4.cookie.sampling.rate=1 + +profiler.apache.httpclient4.entity=true +profiler.apache.httpclient4.entity.dumptype=ALWAYS +profiler.apache.httpclient4.entity.sampling.rate=1 + +# Can profile status code value +profiler.apache.httpclient4.entity.statuscode=true + +# Not supported yet +#profiler.apache.nio.httpclient4=true + + +########################################################### +# JDK HTTPURLConnection # +########################################################### +profiler.jdk.httpurlconnection=true + + +########################################################### +# Ning Async HTTP Client # +########################################################### +profiler.ning.asynchttpclient=true +profiler.ning.asynchttpclient.cookie=true +profiler.ning.asynchttpclient.cookie.dumptype=ALWAYS +profiler.ning.asynchttpclient.cookie.dumpsize=1024 +profiler.ning.asynchttpclient.cookie.sampling.rate=1 +profiler.ning.asynchttpclient.entity=true +profiler.ning.asynchttpclient.entity.dumptype=ALWAYS +profiler.ning.asynchttpclient.entity.dumpsize=1024 +profiler.ning.asynchttpclient.entity.sampling.rate=1 +profiler.ning.asynchttpclient.param=true +profiler.ning.asynchttpclient.param.dumptype=ALWAYS +profiler.ning.asynchttpclient.param.dumpsize=1024 +profiler.ning.asynchttpclient.param.sampling.rate=1 + + +########################################################### +# Arcus # +########################################################### +profiler.arcus=true +profiler.arcus.keytrace=true + + +########################################################### +# Memcached # +########################################################### +profiler.memcached=true +profiler.memcached.keytrace=true + + +########################################################### +# ibatis # +########################################################### +profiler.orm.ibatis=true + + +########################################################### +# mybatis # +########################################################### +profiler.orm.mybatis=true + +########################################################### +# redis # +########################################################### +profiler.redis=true +profiler.redis.pipeline=true + +########################################################### +# nBase-ARC # +########################################################### +profiler.nbase_arc=true +profiler.nbase_arc.pipeline=true + +########################################################### +# spring-beans +########################################################### +profiler.spring.beans=false +profiler.spring.beans.name.pattern= +profiler.spring.beans.class.pattern= +profiler.spring.beans.annotation=org.springframework.stereotype.Controller,org.springframework.stereotype.Service,org.springframework.stereotype.Repository From 3c46fb141b0a0ac350829e8ceac5257be65c1b09 Mon Sep 17 00:00:00 2001 From: Jaehong Kim Date: Wed, 29 Jul 2015 10:40:45 +0900 Subject: [PATCH 3/3] add testcase --- agent/pom.xml | 261 +++++++++--------- agent/src/main/resources/pinpoint.config | 9 +- .../httpclient/HttpClientConstants.java | 5 - .../google/httpclient/HttpClientPlugin.java | 75 +++-- .../httpclient/HttpClientPluginConfig.java | 34 ++- ...euteAsyncMethodInnerClassMethodFilter.java | 20 ++ ...MethodInnerClassCallMethodInterceptor.java | 20 ++ ...ethodInnerClassConstructorInterceptor.java | 31 ++- ...pRequestExecuteAsyncMethodInterceptor.java | 39 ++- .../HttpRequestExecuteMethodInterceptor.java | 20 ++ .../src/test/resources/pinpoint.config | 8 + 11 files changed, 357 insertions(+), 165 deletions(-) diff --git a/agent/pom.xml b/agent/pom.xml index 339010b8e..6273e10ae 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -1,138 +1,143 @@ - 4.0.0 - - com.navercorp.pinpoint - pom - 1.5.0-SNAPSHOT - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + 4.0.0 + + com.navercorp.pinpoint + pom + 1.5.0-SNAPSHOT + - pinpoint-agent - pinpoint-agent-distribution + pinpoint-agent + pinpoint-agent-distribution - - jar + + jar - - - com.navercorp.pinpoint - pinpoint-profiler - - - com.navercorp.pinpoint - pinpoint-profiler-optional - + + + com.navercorp.pinpoint + pinpoint-profiler + + + com.navercorp.pinpoint + pinpoint-profiler-optional + - - - com.navercorp.pinpoint - pinpoint-plugins - zip - runtime - + + + com.navercorp.pinpoint + pinpoint-plugins + zip + runtime + - - - com.navercorp.pinpoint - pinpoint-test - test - - - org.springframework - spring-test - test - - - org.springframework - spring-context - test - - - com.google.code.gson - gson - 2.3.1 - test - - - net.sf.json-lib - json-lib - 2.3 - jdk15 - test - - - com.fasterxml.jackson.core - jackson-databind - test - - - org.codehaus.jackson - jackson-mapper-asl - test - - + + + com.navercorp.pinpoint + pinpoint-test + test + + + org.springframework + spring-test + test + + + org.springframework + spring-context + test + + + com.google.code.gson + gson + 2.3.1 + test + + + net.sf.json-lib + json-lib + 2.3 + jdk15 + test + + + com.fasterxml.jackson.core + jackson-databind + test + + + org.codehaus.jackson + jackson-mapper-asl + test + + + com.google.http-client + google-http-client + test + + - - - - ${basedir}/src/main/java - - **/*.java - - - - true - ${basedir}/src/main/resources - - - ${basedir}/src/main/resources-${env} - - + + + + ${basedir}/src/main/java + + **/*.java + + + + true + ${basedir}/src/main/resources + + + ${basedir}/src/main/resources-${env} + + - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.18.1 - - - integration-test - - integration-test - - - - verify - - verify - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 2.5.3 - - - src/assembly/distribution.xml - - ${project.build.directory} - false - - - - create-distribution - package - - single - - - - - - + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.18.1 + + + integration-test + + integration-test + + + + verify + + verify + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.5.3 + + + src/assembly/distribution.xml + + ${project.build.directory} + false + + + + create-distribution + package + + single + + + + + + diff --git a/agent/src/main/resources/pinpoint.config b/agent/src/main/resources/pinpoint.config index 18b96b868..eed827f8e 100644 --- a/agent/src/main/resources/pinpoint.config +++ b/agent/src/main/resources/pinpoint.config @@ -241,4 +241,11 @@ profiler.log4j.logging.transactioninfo=false ########################################################### # logback (guide url : https://github.com/naver/pinpoint/blob/master/doc/per-request_feature_guide.md) ########################################################### -profiler.logback.logging.transactioninfo=false \ No newline at end of file +profiler.logback.logging.transactioninfo=false + +########################################################### +# google httpclient +########################################################### +profiler.google.httpclient.enable=true +profiler.google.httpclient.async=true +profiler.google.httpclient.async.innerclassname.max=3 \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientConstants.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientConstants.java index 49aec2d4f..b6db4acbe 100644 --- a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientConstants.java +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientConstants.java @@ -22,11 +22,6 @@ package com.navercorp.pinpoint.plugin.google.httpclient; * */ public interface HttpClientConstants { - public static final String METADATA_END_POINT = "endPoint"; - public static final String METADATA_DESTINATION_ID = "destinationId"; public static final String METADATA_ASYNC_TRACE_ID = "asyncTraceId"; - public static final String FIELD_REQUEST_PRODUCER = "requestProducer"; - public static final String FIELD_RESULT_FUTURE = "resultFuture"; - public static final String EXECUTE_ASYNC_SCOPE = "ExecuteAsyncScope"; } diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPlugin.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPlugin.java index 0285bbe23..5b5fca495 100644 --- a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPlugin.java +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPlugin.java @@ -15,18 +15,19 @@ */ package com.navercorp.pinpoint.plugin.google.httpclient; -import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers; +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; import com.navercorp.pinpoint.bootstrap.logging.PLogger; import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext; -import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassConditions; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassCondition; import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassFileTransformerBuilder; import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConditionalClassFileTransformerBuilder; import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConditionalClassFileTransformerSetup; import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConstructorTransformerBuilder; import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerBuilder; import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerExceptionHandler; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerProperty; /** * @author jaehong.kim @@ -34,47 +35,79 @@ import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerExce */ public class HttpClientPlugin implements ProfilerPlugin, HttpClientConstants { private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); - + @Override public void setup(ProfilerPluginContext context) { - addHttpRequestClass(context); - addHttpRequestExecuteAsyncMethodInnerClass(context); + final HttpClientPluginConfig config = new HttpClientPluginConfig(context.getConfig()); + logger.debug("[GoogleHttpClient] Initialized config={}", config); + + if (!config.isEnable()) { + return; + } + + logger.debug("[GoogleHttpClient] Add HttpRequest class."); + addHttpRequestClass(context, config); + + if (config.isAsync()) { + final int max = config.getMaxAnonymousInnerClassNameNumber(); + for (int i = 1; i <= max; i++) { + final String targetClassName = "com.google.api.client.http.HttpRequest$" + i; + logger.debug("[GoogleHttpClient] Add {} class.", targetClassName); + addHttpRequestExecuteAsyncMethodInnerClass(context, targetClassName); + } + } } - private void addHttpRequestClass(ProfilerPluginContext context) { + private void addHttpRequestClass(ProfilerPluginContext context, HttpClientPluginConfig config) { final ClassFileTransformerBuilder classBuilder = context.getClassFileTransformerBuilder("com.google.api.client.http.HttpRequest"); MethodTransformerBuilder executeMethodBuilder = classBuilder.editMethod("execute"); + executeMethodBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST); executeMethodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteMethodInterceptor"); - - MethodTransformerBuilder executeAsyncMethodBuilder = classBuilder.editMethod("executeAsync", "java.util.concurrent.Executor"); - executeAsyncMethodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInterceptor"); + + if (config.isAsync()) { + MethodTransformerBuilder executeAsyncMethodBuilder = classBuilder.editMethod("executeAsync", "java.util.concurrent.Executor"); + executeAsyncMethodBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST); + executeAsyncMethodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInterceptor"); + } context.addClassFileTransformer(classBuilder.build()); } - - private void addHttpRequestExecuteAsyncMethodInnerClass(ProfilerPluginContext context) { - final ClassFileTransformerBuilder classBuilder = context.getClassFileTransformerBuilder("com.google.api.client.http.HttpRequest$1"); + + private void addHttpRequestExecuteAsyncMethodInnerClass(ProfilerPluginContext context, String targetClassName) { + final ClassFileTransformerBuilder classBuilder = context.getClassFileTransformerBuilder(targetClassName); classBuilder.injectMetadata(METADATA_ASYNC_TRACE_ID); - - ConstructorTransformerBuilder constructorBuilder = classBuilder.editConstructor("com.google.api.client.http.HttpRequest"); - constructorBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor"); - - classBuilder.conditional(ClassConditions.hasMethod("call", "com.google.api.client.http.HttpResponse"),new ConditionalClassFileTransformerSetup() { - + + classBuilder.conditional(new ClassCondition() { + @Override + public boolean check(ProfilerPluginContext context, ClassLoader classLoader, InstrumentClass target) { + if (!target.hasConstructor(new String[] { "com.google.api.client.http.HttpRequest" })) { + return false; + } + + if (!target.hasMethod("call", null, "com.google.api.client.http.HttpResponse")) { + return false; + } + + return true; + } + }, new ConditionalClassFileTransformerSetup() { @Override public void setup(ConditionalClassFileTransformerBuilder conditional) { + ConstructorTransformerBuilder constructorBuilder = conditional.editConstructor("com.google.api.client.http.HttpRequest"); + constructorBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor"); + MethodTransformerBuilder methodBuilder = conditional.editMethods(new HttpRequestExceuteAsyncMethodInnerClassMethodFilter()); methodBuilder.exceptionHandler(new MethodTransformerExceptionHandler() { public void handle(String targetClassName, String targetMethodName, String[] targetMethodParameterTypes, Throwable exception) throws Throwable { if (logger.isWarnEnabled()) { - logger.warn("[HttpClientPlugin] Unsupported method " + targetClassName + "." + targetMethodName, exception); + logger.warn("[GoogleHttpClient] Unsupported method " + targetClassName + "." + targetMethodName, exception); } } }); methodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor"); } - }); - context.addClassFileTransformer(classBuilder.build()); + }); + context.addClassFileTransformer(classBuilder.build()); } } \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPluginConfig.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPluginConfig.java index 73b0b6d34..3026b0a66 100644 --- a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPluginConfig.java +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpClientPluginConfig.java @@ -24,6 +24,38 @@ import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; */ public class HttpClientPluginConfig { + private final boolean enable; + private final boolean async; + private final int maxAnonymousInnerClassNameNumber; + public HttpClientPluginConfig(ProfilerConfig src) { + enable = src.readBoolean("profiler.google.httpclient.enable", true); + async = src.readBoolean("profiler.google.httpclient.async", true); + maxAnonymousInnerClassNameNumber = src.readInt("profiler.google.httpclient.async.innerclassname.max", 3); } -} + + public boolean isEnable() { + return enable; + } + + public boolean isAsync() { + return async; + } + + public int getMaxAnonymousInnerClassNameNumber() { + return maxAnonymousInnerClassNameNumber; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("{enable="); + builder.append(enable); + builder.append(", async="); + builder.append(async); + builder.append(", maxAnonymousInnerClassNameNumber="); + builder.append(maxAnonymousInnerClassNameNumber); + builder.append("}"); + return builder.toString(); + } +} \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpRequestExceuteAsyncMethodInnerClassMethodFilter.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpRequestExceuteAsyncMethodInnerClassMethodFilter.java index d79960bd5..67a7e3338 100644 --- a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpRequestExceuteAsyncMethodInnerClassMethodFilter.java +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/HttpRequestExceuteAsyncMethodInnerClassMethodFilter.java @@ -1,3 +1,18 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient; import java.lang.reflect.Modifier; @@ -5,6 +20,11 @@ import java.lang.reflect.Modifier; import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo; +/** + * + * @author jaehong.kim + * + */ public class HttpRequestExceuteAsyncMethodInnerClassMethodFilter implements MethodFilter { private static final int SYNTHETIC = 0x00001000; diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor.java index d8c89ffe0..9db7f3648 100644 --- a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor.java +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor.java @@ -1,3 +1,18 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient.interceptor; import com.navercorp.pinpoint.bootstrap.MetadataAccessor; @@ -10,6 +25,11 @@ import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name; import com.navercorp.pinpoint.common.trace.ServiceType; import com.navercorp.pinpoint.plugin.google.httpclient.HttpClientConstants; +/** + * + * @author jaehong.kim + * + */ public class HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor extends SpanAsyncEventSimpleAroundInterceptor { public HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor(TraceContext traceContext, MethodDescriptor descriptor, @Name(HttpClientConstants.METADATA_ASYNC_TRACE_ID) MetadataAccessor asyncTraceIdAccessor) { diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor.java index ade90e6e8..a0fea4751 100644 --- a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor.java +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor.java @@ -1,3 +1,18 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient.interceptor; import com.navercorp.pinpoint.bootstrap.MetadataAccessor; @@ -14,6 +29,11 @@ import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group; import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name; import com.navercorp.pinpoint.plugin.google.httpclient.HttpClientConstants; +/** + * + * @author jaehong.kim + * + */ @Group(value = HttpClientConstants.EXECUTE_ASYNC_SCOPE, executionPoint = ExecutionPolicy.ALWAYS) public class HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor implements SimpleAroundInterceptor, HttpClientConstants { private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); @@ -39,8 +59,12 @@ public class HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor imple } InterceptorGroupInvocation transaction = interceptorGroup.getCurrentInvocation(); - AsyncTraceId asyncTraceId = (AsyncTraceId) transaction.getAttachment(); - asyncTraceIdAccessor.set(target, asyncTraceId); + if(transaction != null && transaction.getAttachment() != null) { + AsyncTraceId asyncTraceId = (AsyncTraceId) transaction.getAttachment(); + asyncTraceIdAccessor.set(target, asyncTraceId); + // clear. + transaction.removeAttachment(); + } } catch (Throwable t) { logger.warn("Failed to before process. {}", t.getMessage(), t); } @@ -57,5 +81,8 @@ public class HttpRequestExecuteAsyncMethodInnerClassConstructorInterceptor imple @Override public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args); + } } } \ No newline at end of file diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInterceptor.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInterceptor.java index 20f5cb235..2f5011771 100644 --- a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInterceptor.java +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteAsyncMethodInterceptor.java @@ -1,3 +1,18 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient.interceptor; import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId; @@ -15,6 +30,11 @@ import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group; import com.navercorp.pinpoint.common.trace.ServiceType; import com.navercorp.pinpoint.plugin.google.httpclient.HttpClientConstants; +/** + * + * @author jaehong.kim + * + */ @Group(value = HttpClientConstants.EXECUTE_ASYNC_SCOPE, executionPoint = ExecutionPolicy.ALWAYS) public class HttpRequestExecuteAsyncMethodInterceptor implements SimpleAroundInterceptor { private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); @@ -29,7 +49,7 @@ public class HttpRequestExecuteAsyncMethodInterceptor implements SimpleAroundInt this.methodDescriptor = methodDescriptor; this.interceptorGroup = interceptorGroup; } - + @Override public void before(Object target, Object[] args) { if (isDebug) { @@ -46,12 +66,14 @@ public class HttpRequestExecuteAsyncMethodInterceptor implements SimpleAroundInt // set asynchronous trace final AsyncTraceId asyncTraceId = trace.getAsyncTraceId(); recorder.recordNextAsyncId(asyncTraceId.getAsyncId()); - + // set async id. InterceptorGroupInvocation transaction = interceptorGroup.getCurrentInvocation(); - transaction.setAttachment(asyncTraceId); - if (isDebug) { - logger.debug("Set asyncTraceId metadata {}", asyncTraceId); + if (transaction != null) { + transaction.setAttachment(asyncTraceId); + if (isDebug) { + logger.debug("Set asyncTraceId metadata {}", asyncTraceId); + } } } catch (Throwable t) { logger.warn("Failed to before process. {}", t.getMessage(), t); @@ -74,10 +96,13 @@ public class HttpRequestExecuteAsyncMethodInterceptor implements SimpleAroundInt recorder.recordApi(methodDescriptor); recorder.recordServiceType(ServiceType.HTTP_CLIENT_INTERNAL); recorder.recordException(throwable); - + // remove async id. InterceptorGroupInvocation transaction = interceptorGroup.getCurrentInvocation(); - transaction.removeAttachment(); + if (transaction != null) { + // clear + transaction.removeAttachment(); + } } finally { trace.traceBlockEnd(); } diff --git a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteMethodInterceptor.java b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteMethodInterceptor.java index 31fd3837d..21f5aff34 100644 --- a/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteMethodInterceptor.java +++ b/plugins/google-httpclient/src/main/java/com/navercorp/pinpoint/plugin/google/httpclient/interceptor/HttpRequestExecuteMethodInterceptor.java @@ -1,3 +1,18 @@ +/* + * Copyright 2014 NAVER Corp. + * + * 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.navercorp.pinpoint.plugin.google.httpclient.interceptor; import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; @@ -6,6 +21,11 @@ import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor; import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin; import com.navercorp.pinpoint.common.trace.ServiceType; +/** + * + * @author jaehong.kim + * + */ public class HttpRequestExecuteMethodInterceptor extends SpanEventSimpleAroundInterceptorForPlugin { public HttpRequestExecuteMethodInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { diff --git a/plugins/google-httpclient/src/test/resources/pinpoint.config b/plugins/google-httpclient/src/test/resources/pinpoint.config index 37524ece0..4530cef5b 100644 --- a/plugins/google-httpclient/src/test/resources/pinpoint.config +++ b/plugins/google-httpclient/src/test/resources/pinpoint.config @@ -203,3 +203,11 @@ profiler.spring.beans=false profiler.spring.beans.name.pattern= profiler.spring.beans.class.pattern= profiler.spring.beans.annotation=org.springframework.stereotype.Controller,org.springframework.stereotype.Service,org.springframework.stereotype.Repository + + +########################################################### +# google httpclient +########################################################### +profiler.google.httpclient.enable=true +profiler.google.httpclient.async=true +profiler.google.httpclient.async.innerclassname.max=3 \ No newline at end of file