Merge pull request #782 from jaehong-kim/google-httpclient

Google httpclient
This commit is contained in:
Jaehong Kim
2015-07-29 14:07:58 +09:00
19 changed files with 981 additions and 129 deletions
+133 -128
View File
@@ -1,138 +1,143 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pom</artifactId>
<version>1.5.0-SNAPSHOT</version>
</parent>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pom</artifactId>
<version>1.5.0-SNAPSHOT</version>
</parent>
<artifactId>pinpoint-agent</artifactId>
<name>pinpoint-agent-distribution</name>
<artifactId>pinpoint-agent</artifactId>
<name>pinpoint-agent-distribution</name>
<!-- this module contains integration tests. if we set packaging to pom,
tests are not run. so we set it to jar even though the project will not be
packaged as a jar. -->
<packaging>jar</packaging>
<!-- this module contains integration tests. if we set packaging to pom,
tests are not run. so we set it to jar even though the project will not be
packaged as a jar. -->
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-profiler</artifactId>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-profiler-optional</artifactId>
</dependency>
<dependencies>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-profiler</artifactId>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-profiler-optional</artifactId>
</dependency>
<!-- plug-ins -->
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-plugins</artifactId>
<type>zip</type>
<scope>runtime</scope>
</dependency>
<!-- plug-ins -->
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-plugins</artifactId>
<type>zip</type>
<scope>runtime</scope>
</dependency>
<!-- for tests -->
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.3</version>
<classifier>jdk15</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- for tests -->
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.3</version>
<classifier>jdk15</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
<resource>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${basedir}/src/main/resources-${env}</directory>
</resource>
</resources>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
<resource>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${basedir}/src/main/resources-${env}</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptors>
<descriptor>src/assembly/distribution.xml</descriptor>
</descriptors>
<outputDirectory>${project.build.directory}</outputDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>create-distribution</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptors>
<descriptor>src/assembly/distribution.xml</descriptor>
</descriptors>
<outputDirectory>${project.build.directory}</outputDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>create-distribution</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
+8 -1
View File
@@ -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
profiler.logback.logging.transactioninfo=false
###########################################################
# google httpclient
###########################################################
profiler.google.httpclient.enable=true
profiler.google.httpclient.async=true
profiler.google.httpclient.async.innerclassname.max=3
+5
View File
@@ -0,0 +1,5 @@
/target/
/.settings/
/.classpath
/.project
/*.iml
+5
View File
@@ -0,0 +1,5 @@
RMRqrdbgbKFhbaVnDxHUdDQvrOQXxIBklnvcmahheubVC
mh2KM35CLkwUHS4DH7QVhxy52J5hnWbyEm6Cyd3KkF<mV
RmmnSVOqOMnOnMMrmMqwXomoroNrqPNRrPSsWwtUxXuUU
sRONqpnmqmUUnqonmstsmmmmmUUnqonmstsmmmmmUUGfk
mlfkqUUnmmmm
+30
View File
@@ -0,0 +1,30 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pom</artifactId>
<relativePath>../..</relativePath>
<version>1.5.0-SNAPSHOT</version>
</parent>
<artifactId>pinpoint-google-httpclient-plugin</artifactId>
<name>pinpoint-google-httpclient-plugin</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-bootstrap</artifactId>
<scope>provided</scope>
</dependency>
<!-- HTTP Client -->
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,27 @@
/*
* 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_ASYNC_TRACE_ID = "asyncTraceId";
public static final String EXECUTE_ASYNC_SCOPE = "ExecuteAsyncScope";
}
@@ -0,0 +1,113 @@
/*
* 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.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.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
*
*/
public class HttpClientPlugin implements ProfilerPlugin, HttpClientConstants {
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
@Override
public void setup(ProfilerPluginContext 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, 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");
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, String targetClassName) {
final ClassFileTransformerBuilder classBuilder = context.getClassFileTransformerBuilder(targetClassName);
classBuilder.injectMetadata(METADATA_ASYNC_TRACE_ID);
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("[GoogleHttpClient] Unsupported method " + targetClassName + "." + targetMethodName, exception);
}
}
});
methodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.google.httpclient.interceptor.HttpRequestExecuteAsyncMethodInnerClassCallMethodInterceptor");
}
});
context.addClassFileTransformer(classBuilder.build());
}
}
@@ -0,0 +1,61 @@
/*
* 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 {
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();
}
}
@@ -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) {
}
}
@@ -0,0 +1,50 @@
/*
* 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;
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;
@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;
}
}
@@ -0,0 +1,49 @@
/*
* 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;
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;
/**
*
* @author jaehong.kim
*
*/
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);
}
}
@@ -0,0 +1,88 @@
/*
* 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;
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;
/**
*
* @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());
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();
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);
}
}
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) {
if (isDebug) {
logger.afterInterceptor(target, args);
}
}
}
@@ -0,0 +1,110 @@
/*
* 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;
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;
/**
*
* @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());
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();
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);
}
}
@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();
if (transaction != null) {
// clear
transaction.removeAttachment();
}
} finally {
trace.traceBlockEnd();
}
}
}
@@ -0,0 +1,45 @@
/*
* 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;
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;
/**
*
* @author jaehong.kim
*
*/
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);
}
}
@@ -0,0 +1 @@
com.navercorp.pinpoint.plugin.google.httpclient.HttpClientPlugin
@@ -0,0 +1 @@
com.navercorp.pinpoint.plugin.google.httpclient.HttpClientTypeProvider
@@ -0,0 +1,213 @@
#
# 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
###########################################################
# google httpclient
###########################################################
profiler.google.httpclient.enable=true
profiler.google.httpclient.async=true
profiler.google.httpclient.async.innerclassname.max=3
+6
View File
@@ -25,6 +25,7 @@
<module>thrift</module>
<module>user</module>
<module>arcus</module>
<module>google-httpclient</module>
</modules>
<dependencies>
@@ -93,6 +94,11 @@
<artifactId>pinpoint-arcus-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-google-httpclient-plugin</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
+5
View File
@@ -455,6 +455,11 @@
<version>3.1</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
<version>1.20.0</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>