This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git
The following commit(s) were added to refs/heads/main by this push:
new 9101f69 Add okhttp2.x plugin (#49)
9101f69 is described below
commit 9101f691fba659a2616918588cae65da25e04690
Author: xu1009 <[email protected]>
AuthorDate: Mon Oct 25 22:40:37 2021 +0800
Add okhttp2.x plugin (#49)
Co-authored-by: litexu <[email protected]>
---
.github/workflows/plugins-test.2.yaml | 1 +
CHANGES.md | 2 +
.../apm-sdk-plugin/okhttp-2.x-plugin/pom.xml | 53 +++++++
.../plugin/okhttp/v2}/AsyncCallInterceptor.java | 57 +------
.../apm/plugin/okhttp/v2/CallInterceptor.java} | 60 ++-----
.../apm/plugin/okhttp/v2/EnqueueInterceptor.java} | 40 +++--
.../plugin/okhttp/v2}/OnResponseInterceptor.java | 20 +--
.../apm/plugin/okhttp/v2}/RealCallInterceptor.java | 35 +++--
.../okhttp/v2/define/AsyncCallInstrumentation.java | 83 ++++++++++
.../okhttp/v2/define/CallbackInstrumentation.java | 80 ++++++++++
.../okhttp/v2/define/RealCallInstrumentation.java | 120 ++++++++++++++
.../src/main/resources/skywalking-plugin.def | 19 +++
.../plugin/okhttp/v2/RealCallInterceptorTest.java | 175 +++++++++++++++++++++
.../okhttp/v3/define/RealCallInstrumentation.java | 100 +++++++-----
.../okhttp/v4/define/RealCallInstrumentation.java | 101 +++++++-----
.../plugin/okhttp/common/AsyncCallInterceptor.java | 53 +------
...alCallInterceptor.java => CallInterceptor.java} | 48 ++----
.../plugin/okhttp/common/OnFailureInterceptor.java | 3 +-
.../okhttp/common/OnResponseInterceptor.java | 8 +-
.../plugin/okhttp/common/RealCallInterceptor.java | 18 +--
apm-sniffer/apm-sdk-plugin/pom.xml | 1 +
.../setup/service-agent/java-agent/Plugin-list.md | 1 +
.../service-agent/java-agent/Supported-list.md | 2 +-
pom.xml | 1 +
.../okhttp-scenario/config/expectedData.yaml | 49 ++++--
.../scenarios/okhttp2-scenario/bin/startup.sh | 21 +++
.../config/expectedData.yaml | 69 +++++---
.../scenarios/okhttp2-scenario/configuration.yml | 20 +++
test/plugin/scenarios/okhttp2-scenario/pom.xml | 124 +++++++++++++++
.../src/main/assembly/assembly.xml | 41 +++++
.../apm/testcase/okhttp2/Application.java | 34 ++++
.../okhttp2/controller/CaseController.java | 83 ++++++++++
.../src/main/resources/application.yaml | 23 +++
.../okhttp2-scenario/src/main/resources/log4j2.xml | 30 ++++
.../okhttp2-scenario/support-version.list | 22 +++
35 files changed, 1246 insertions(+), 351 deletions(-)
diff --git a/.github/workflows/plugins-test.2.yaml
b/.github/workflows/plugins-test.2.yaml
index 2ded7f6..44489ee 100644
--- a/.github/workflows/plugins-test.2.yaml
+++ b/.github/workflows/plugins-test.2.yaml
@@ -78,6 +78,7 @@ jobs:
- struts2.3-scenario
- struts2.5-scenario
- cxf-scenario
+ - okhttp2-scenario
steps:
- uses: actions/checkout@v2
with:
diff --git a/CHANGES.md b/CHANGES.md
index 6218db0..46455b0 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -37,6 +37,8 @@ Release Notes.
* Fix version compatibility for JsonRPC4J plugin.
* Add plugin to support Apache Kylin-jdbc 2.6.x 3.x 4.x
* Fix instrumentation v2 API doesn't work for constructor instrumentation.
+* Add plugin to support okhttp 2.x
+* Optimize okhttp 3.x 4.x plugin to get span time cost precisely
#### Documentation
diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml
new file mode 100644
index 0000000..be93a8a
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You 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.
+ ~
+ -->
+
+<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/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>apm-sdk-plugin</artifactId>
+ <groupId>org.apache.skywalking</groupId>
+ <version>8.8.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>okhttp-2.x-plugin</artifactId>
+ <name>okhttp-2.x-plugin</name>
+ <packaging>jar</packaging>
+
+ <properties>
+ <okhttp.version>2.7.5</okhttp.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>${okhttp.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.skywalking</groupId>
+ <artifactId>apm-okhttp-common</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/AsyncCallInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/AsyncCallInterceptor.java
similarity index 57%
copy from
apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/AsyncCallInterceptor.java
copy to
apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/AsyncCallInterceptor.java
index 54364f4..2163ec1 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/AsyncCallInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/AsyncCallInterceptor.java
@@ -16,25 +16,15 @@
*
*/
-package org.apache.skywalking.apm.plugin.okhttp.common;
+package org.apache.skywalking.apm.plugin.okhttp.v2;
-import okhttp3.Headers;
-import okhttp3.HttpUrl;
-import okhttp3.Request;
-import org.apache.skywalking.apm.agent.core.context.CarrierItem;
-import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.tag.Tags;
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
+import org.apache.skywalking.apm.plugin.okhttp.common.EnhanceRequiredInfo;
/**
* {@link AsyncCallInterceptor} get the `EnhanceRequiredInfo` instance from
`SkyWalkingDynamicField` and then put it
@@ -45,18 +35,6 @@ import java.lang.reflect.Method;
*/
public class AsyncCallInterceptor implements InstanceConstructorInterceptor,
InstanceMethodsAroundInterceptor {
- private static Field FIELD_HEADERS_OF_REQUEST;
-
- static {
- try {
- final Field field = Request.class.getDeclaredField("headers");
- field.setAccessible(true);
- FIELD_HEADERS_OF_REQUEST = field;
- } catch (Exception ignore) {
- FIELD_HEADERS_OF_REQUEST = null;
- }
- }
-
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
/**
@@ -71,43 +49,22 @@ public class AsyncCallInterceptor implements
InstanceConstructorInterceptor, Ins
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
+ MethodInterceptResult result) throws Throwable {
EnhanceRequiredInfo enhanceRequiredInfo = (EnhanceRequiredInfo)
objInst.getSkyWalkingDynamicField();
- Request request = (Request)
enhanceRequiredInfo.getRealCallEnhance().getSkyWalkingDynamicField();
-
- HttpUrl requestUrl = request.url();
- AbstractSpan span = ContextManager.createExitSpan(requestUrl.uri()
-
.getPath(), requestUrl.host() + ":" + requestUrl.port());
+ ContextManager.createLocalSpan("Async/execute");
ContextManager.continued(enhanceRequiredInfo.getContextSnapshot());
- ContextCarrier contextCarrier = new ContextCarrier();
- ContextManager.inject(contextCarrier);
- span.setComponent(ComponentsDefine.OKHTTP);
- Tags.HTTP.METHOD.set(span, request.method());
- Tags.URL.set(span, requestUrl.uri().toString());
- SpanLayer.asHttp(span);
-
- if (FIELD_HEADERS_OF_REQUEST != null) {
- Headers.Builder headerBuilder = request.headers().newBuilder();
- CarrierItem next = contextCarrier.items();
- while (next.hasNext()) {
- next = next.next();
- headerBuilder.set(next.getHeadKey(), next.getHeadValue());
- }
- FIELD_HEADERS_OF_REQUEST.set(request, headerBuilder.build());
- }
-
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
+ Object ret) throws Throwable {
ContextManager.stopSpan();
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments,
- Class<?>[] argumentsTypes, Throwable t) {
+ Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/CallInterceptor.java
similarity index 68%
copy from
apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
copy to
apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/CallInterceptor.java
index c944649..adf5965 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/CallInterceptor.java
@@ -16,12 +16,14 @@
*
*/
-package org.apache.skywalking.apm.plugin.okhttp.common;
+package org.apache.skywalking.apm.plugin.okhttp.v2;
-import okhttp3.Headers;
-import okhttp3.HttpUrl;
-import okhttp3.Request;
-import okhttp3.Response;
+import com.squareup.okhttp.Headers;
+import com.squareup.okhttp.HttpUrl;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
@@ -29,18 +31,11 @@ import
org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-/**
- * {@link RealCallInterceptor} intercept the synchronous http calls by the
discovery of okhttp.
- */
-public class RealCallInterceptor implements InstanceMethodsAroundInterceptor,
InstanceConstructorInterceptor {
+public class CallInterceptor implements InstanceMethodsAroundInterceptor {
private static Field FIELD_HEADERS_OF_REQUEST;
@@ -55,32 +50,18 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
}
@Override
- public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
- objInst.setSkyWalkingDynamicField(allArguments[1]);
- }
-
- /**
- * Get the {@link Request} from {@link EnhancedInstance}, then create
{@link AbstractSpan} and set host,
- * port, kind, component, url from {@link Request}. Through the reflection
of the way, set the http header
- * of context data into {@link Request#headers}.
- *
- * @param result change this result, if you want to truncate the method.
- */
- @Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
+ MethodInterceptResult result) throws Throwable {
Request request = (Request) objInst.getSkyWalkingDynamicField();
-
- ContextCarrier contextCarrier = new ContextCarrier();
- HttpUrl requestUrl = request.url();
+ HttpUrl requestUrl = request.httpUrl();
AbstractSpan span = ContextManager.createExitSpan(requestUrl.uri()
-
.getPath(), contextCarrier, requestUrl.host() + ":" + requestUrl
- .port());
+ .getPath(), requestUrl.host() + ":" + requestUrl.port());
+ ContextCarrier contextCarrier = new ContextCarrier();
+ ContextManager.inject(contextCarrier);
span.setComponent(ComponentsDefine.OKHTTP);
Tags.HTTP.METHOD.set(span, request.method());
Tags.URL.set(span, requestUrl.uri().toString());
SpanLayer.asHttp(span);
-
if (FIELD_HEADERS_OF_REQUEST != null) {
Headers.Builder headerBuilder = request.headers().newBuilder();
CarrierItem next = contextCarrier.items();
@@ -92,15 +73,9 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
}
}
- /**
- * Get the status code from {@link Response}, when status code greater
than 400, it means there was some errors in
- * the server. Finish the {@link AbstractSpan}.
- *
- * @param ret the method's original return value.
- */
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
+ Object ret) throws Throwable {
Response response = (Response) ret;
if (response != null) {
int statusCode = response.code();
@@ -110,16 +85,13 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode);
}
}
-
ContextManager.stopSpan();
-
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments,
- Class<?>[] argumentsTypes, Throwable t) {
- AbstractSpan abstractSpan = ContextManager.activeSpan();
- abstractSpan.log(t);
+ Class<?>[] argumentsTypes, Throwable t) {
+ ContextManager.activeSpan().log(t);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/EnqueueInterceptor.java
similarity index 51%
copy from
apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
copy to
apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/EnqueueInterceptor.java
index 62728b3..a487a3d 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/EnqueueInterceptor.java
@@ -16,34 +16,47 @@
*
*/
-package org.apache.skywalking.apm.plugin.okhttp.common;
+package org.apache.skywalking.apm.plugin.okhttp.v2;
-import okhttp3.Response;
+import com.squareup.okhttp.Request;
+import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-
-import java.lang.reflect.Method;
+import org.apache.skywalking.apm.plugin.okhttp.common.EnhanceRequiredInfo;
/**
- * {@link OnResponseInterceptor} validate the response code if it is great
equal than 400. if so. the transaction status
- * chang to `error`, or do nothing.
+ * {@link EnqueueInterceptor} create a local span and the prefix of the span
operation name is start with `Async` when
+ * the `enqueue` method called and also put the `ContextSnapshot` and
`RealCall` instance into the
+ * `SkyWalkingDynamicField`.
*/
-public class OnResponseInterceptor implements InstanceMethodsAroundInterceptor
{
+public class EnqueueInterceptor implements InstanceMethodsAroundInterceptor,
InstanceConstructorInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
- Response response = (Response) allArguments[1];
+ EnhancedInstance callbackInstance = (EnhancedInstance) allArguments[0];
+ Request request = (Request) objInst.getSkyWalkingDynamicField();
+ ContextManager.createLocalSpan("Async" +
request.httpUrl().uri().getPath());
+
+ /**
+ * Here is the process about how to trace the async function.
+ *
+ * 1. Storage `Request` object into `RealCall` instance when the
constructor of `RealCall` called.
+ * 2. Put the `RealCall` instance to `CallBack` instance
+ * 3. Get the `RealCall` instance from `CallBack` and then Put the
`RealCall` into `AsyncCall` instance
+ * since the constructor of `RealCall` called.
+ * 5. Create the exit span by using the `RealCall` instance when
`AsyncCall` method called.
+ */
- if (response.code() >= 400) {
- ContextManager.activeSpan().errorOccurred();
- }
+ callbackInstance.setSkyWalkingDynamicField(new
EnhanceRequiredInfo(objInst, ContextManager.capture()));
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
+ ContextManager.stopSpan();
return ret;
}
@@ -52,4 +65,9 @@ public class OnResponseInterceptor implements
InstanceMethodsAroundInterceptor {
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
+
+ @Override
+ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+ objInst.setSkyWalkingDynamicField(allArguments[1]);
+ }
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/OnResponseInterceptor.java
similarity index 83%
copy from
apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
copy to
apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/OnResponseInterceptor.java
index 62728b3..b4b540c 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/OnResponseInterceptor.java
@@ -16,40 +16,36 @@
*
*/
-package org.apache.skywalking.apm.plugin.okhttp.common;
+package org.apache.skywalking.apm.plugin.okhttp.v2;
-import okhttp3.Response;
+import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import java.lang.reflect.Method;
-
/**
* {@link OnResponseInterceptor} validate the response code if it is great
equal than 400. if so. the transaction status
* chang to `error`, or do nothing.
*/
public class OnResponseInterceptor implements InstanceMethodsAroundInterceptor
{
+
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
- Response response = (Response) allArguments[1];
-
- if (response.code() >= 400) {
- ContextManager.activeSpan().errorOccurred();
- }
+ MethodInterceptResult result) throws Throwable {
+ ContextManager.createLocalSpan("Callback/onResponse");
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
+ Object ret) throws Throwable {
+ ContextManager.stopSpan();
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments,
- Class<?>[] argumentsTypes, Throwable t) {
+ Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/RealCallInterceptor.java
similarity index 85%
copy from
apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
copy to
apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/RealCallInterceptor.java
index c944649..2b9387e 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/RealCallInterceptor.java
@@ -16,27 +16,28 @@
*
*/
-package org.apache.skywalking.apm.plugin.okhttp.common;
+package org.apache.skywalking.apm.plugin.okhttp.v2;
-import okhttp3.Headers;
-import okhttp3.HttpUrl;
-import okhttp3.Request;
-import okhttp3.Response;
+import com.squareup.okhttp.Headers;
+import com.squareup.okhttp.HttpUrl;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.logging.api.ILog;
+import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
/**
* {@link RealCallInterceptor} intercept the synchronous http calls by the
discovery of okhttp.
*/
@@ -44,6 +45,8 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
private static Field FIELD_HEADERS_OF_REQUEST;
+ private static final ILog LOGGER =
LogManager.getLogger(RealCallInterceptor.class);
+
static {
try {
final Field field = Request.class.getDeclaredField("headers");
@@ -62,20 +65,20 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
/**
* Get the {@link Request} from {@link EnhancedInstance}, then create
{@link AbstractSpan} and set host,
* port, kind, component, url from {@link Request}. Through the reflection
of the way, set the http header
- * of context data into {@link Request#headers}.
+ * of context data into {@link Request#headers()}.
*
* @param result change this result, if you want to truncate the method.
*/
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
+ MethodInterceptResult result) throws Throwable {
Request request = (Request) objInst.getSkyWalkingDynamicField();
ContextCarrier contextCarrier = new ContextCarrier();
- HttpUrl requestUrl = request.url();
- AbstractSpan span = ContextManager.createExitSpan(requestUrl.uri()
-
.getPath(), contextCarrier, requestUrl.host() + ":" + requestUrl
- .port());
+ HttpUrl requestUrl = request.httpUrl();
+ AbstractSpan span =
ContextManager.createExitSpan(requestUrl.uri().getPath(), contextCarrier,
+ requestUrl.host() + ":" + requestUrl.port());
+ ContextManager.inject(contextCarrier);
span.setComponent(ComponentsDefine.OKHTTP);
Tags.HTTP.METHOD.set(span, request.method());
Tags.URL.set(span, requestUrl.uri().toString());
@@ -100,7 +103,7 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
*/
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
+ Object ret) throws Throwable {
Response response = (Response) ret;
if (response != null) {
int statusCode = response.code();
@@ -118,7 +121,7 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments,
- Class<?>[] argumentsTypes, Throwable t) {
+ Class<?>[] argumentsTypes, Throwable t) {
AbstractSpan abstractSpan = ContextManager.activeSpan();
abstractSpan.log(t);
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/AsyncCallInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/AsyncCallInstrumentation.java
new file mode 100644
index 0000000..3daa03d
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/AsyncCallInstrumentation.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.okhttp.v2.define;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static
org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+public class AsyncCallInstrumentation extends
ClassInstanceMethodsEnhancePluginDefine {
+
+
+ /**
+ * Intercept class.
+ */
+ private static final String INTERCEPT_CLASS =
"org.apache.skywalking.apm.plugin.okhttp.v2.AsyncCallInterceptor";
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[]{
+ new ConstructorInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getConstructorMatcher() {
+ return any();
+ }
+
+ @Override
+ public String getConstructorInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+ }
+ };
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints()
{
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("execute");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byName("com.squareup.okhttp.Call$AsyncCall");
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/CallbackInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/CallbackInstrumentation.java
new file mode 100644
index 0000000..dd65eb0
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/CallbackInstrumentation.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.okhttp.v2.define;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static
org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+public class CallbackInstrumentation extends
ClassInstanceMethodsEnhancePluginDefine {
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints()
{
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("onFailure");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return
"org.apache.skywalking.apm.plugin.okhttp.common.OnFailureInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("onResponse");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return
"org.apache.skywalking.apm.plugin.okhttp.v2.OnResponseInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byHierarchyMatch(new String[]{"com.squareup.okhttp.Callback"});
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/RealCallInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/RealCallInstrumentation.java
new file mode 100644
index 0000000..aee7fcf
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v2/define/RealCallInstrumentation.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.okhttp.v2.define;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
+
+public class RealCallInstrumentation extends
ClassInstanceMethodsEnhancePluginDefine {
+
+ /**
+ * Enhance class.
+ */
+ private static final String ENHANCE_CLASS = "com.squareup.okhttp.Call";
+
+ /**
+ * Intercept class.
+ */
+ private static final String INTERCEPT_CLASS =
"org.apache.skywalking.apm.plugin.okhttp.v2.RealCallInterceptor";
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return NameMatch.byName(ENHANCE_CLASS);
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[]{
+ new ConstructorInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getConstructorMatcher() {
+ return any();
+ }
+
+ @Override
+ public String getConstructorInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+ }
+ };
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints()
{
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("execute");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("getResponseWithInterceptorChain");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return
"org.apache.skywalking.apm.plugin.okhttp.v2.CallInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("enqueue").and(takesArguments(1));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return
"org.apache.skywalking.apm.plugin.okhttp.v2.EnqueueInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/resources/skywalking-plugin.def
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000..d3772e8
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+okhttp-2.x=org.apache.skywalking.apm.plugin.okhttp.v2.define.RealCallInstrumentation
+okhttp-2.x=org.apache.skywalking.apm.plugin.okhttp.v2.define.CallbackInstrumentation
+okhttp-2.x=org.apache.skywalking.apm.plugin.okhttp.v2.define.AsyncCallInstrumentation
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/okhttp/v2/RealCallInterceptorTest.java
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/okhttp/v2/RealCallInterceptorTest.java
new file mode 100644
index 0000000..692753f
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/okhttp/v2/RealCallInterceptorTest.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.okhttp.v2;
+
+import static
org.apache.skywalking.apm.agent.test.tools.SpanAssert.assertComponent;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+import java.util.List;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.helper.SpanHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.SpanAssert;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+@PrepareForTest({Response.class})
+public class RealCallInterceptorTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule serviceRule = new AgentServiceRule();
+
+ private RealCallInterceptor realCallInterceptor;
+
+ @Mock
+ private OkHttpClient client;
+
+ private Request request;
+
+ private Object[] allArguments;
+ private Class[] argumentTypes;
+
+ private EnhancedInstance enhancedInstance = new EnhancedInstance() {
+
+ private Object object;
+
+ @Override
+ public Object getSkyWalkingDynamicField() {
+ return object;
+ }
+
+ @Override
+ public void setSkyWalkingDynamicField(Object value) {
+ this.object = value;
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ request = new Request.Builder().url("http://skywalking.org").build();
+ allArguments = new Object[]{
+ client,
+ request,
+ false
+ };
+ argumentTypes = new Class[]{
+ client.getClass(),
+ request.getClass(),
+ Boolean.class
+ };
+ realCallInterceptor = new RealCallInterceptor();
+ }
+
+ @Test
+ public void testOnConstruct() {
+ realCallInterceptor.onConstruct(enhancedInstance, allArguments);
+ assertThat(enhancedInstance.getSkyWalkingDynamicField(),
is(allArguments[1]));
+ }
+
+ @Test
+ public void testMethodsAround() throws Throwable {
+ realCallInterceptor.onConstruct(enhancedInstance, allArguments);
+ realCallInterceptor.beforeMethod(enhancedInstance, null, allArguments,
argumentTypes, null);
+
+ Response response = mock(Response.class);
+ when(response.code()).thenReturn(200);
+ realCallInterceptor.afterMethod(enhancedInstance, null, allArguments,
argumentTypes, response);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+ List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+
+ assertSpan(spans.get(0));
+ SpanAssert.assertOccurException(spans.get(0), false);
+ }
+
+ @Test
+ public void testMethodsAroundError() throws Throwable {
+ realCallInterceptor.onConstruct(enhancedInstance, allArguments);
+ realCallInterceptor.beforeMethod(enhancedInstance, null, allArguments,
argumentTypes, null);
+
+ Response response = mock(Response.class);
+ when(response.code()).thenReturn(404);
+ realCallInterceptor.afterMethod(enhancedInstance, null, allArguments,
argumentTypes, response);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+ List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+
+ assertSpan(spans.get(0));
+ SpanAssert.assertOccurException(spans.get(0), true);
+ }
+
+ private void assertSpan(AbstractTracingSpan span) {
+ assertComponent(span, ComponentsDefine.OKHTTP);
+ SpanAssert.assertLayer(span, SpanLayer.HTTP);
+ SpanAssert.assertTag(span, 0, "GET");
+ SpanAssert.assertTag(span, 1, "http://skywalking.org/");
+ assertThat(span.isExit(), is(true));
+ assertThat(span.getOperationName(), is("/"));
+ }
+
+ @Test
+ public void testException() throws Throwable {
+ realCallInterceptor.onConstruct(enhancedInstance, allArguments);
+ realCallInterceptor.beforeMethod(enhancedInstance, null, allArguments,
argumentTypes, null);
+
+ realCallInterceptor.handleMethodException(enhancedInstance, null,
allArguments, argumentTypes,
+ new NullPointerException("testException"));
+
+ Response response = mock(Response.class);
+ when(response.code()).thenReturn(200);
+ realCallInterceptor.afterMethod(enhancedInstance, null, allArguments,
argumentTypes, response);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+ List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+
+ assertSpan(spans.get(0));
+ SpanAssert.assertOccurException(spans.get(0), true);
+ SpanAssert.assertLogSize(spans.get(0), 1);
+ SpanAssert.assertException(SpanHelper.getLogs(spans.get(0))
+ .get(0), NullPointerException.class, "testException");
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/RealCallInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/RealCallInstrumentation.java
index 0658359..9746545 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/RealCallInstrumentation.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v3/define/RealCallInstrumentation.java
@@ -18,6 +18,10 @@
package org.apache.skywalking.apm.plugin.okhttp.v3.define;
+import static net.bytebuddy.matcher.ElementMatchers.any;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
@@ -25,10 +29,6 @@ import
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsIn
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
-import static net.bytebuddy.matcher.ElementMatchers.any;
-import static net.bytebuddy.matcher.ElementMatchers.named;
-import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
-
public class RealCallInstrumentation extends AbstractOkhttpInstrumentation {
/**
@@ -48,56 +48,72 @@ public class RealCallInstrumentation extends
AbstractOkhttpInstrumentation {
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
- return new ConstructorInterceptPoint[] {
- new ConstructorInterceptPoint() {
- @Override
- public ElementMatcher<MethodDescription>
getConstructorMatcher() {
- return any();
- }
+ return new ConstructorInterceptPoint[]{
+ new ConstructorInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getConstructorMatcher() {
+ return any();
+ }
- @Override
- public String getConstructorInterceptor() {
- return INTERCEPT_CLASS;
+ @Override
+ public String getConstructorInterceptor() {
+ return INTERCEPT_CLASS;
+ }
}
- }
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints()
{
- return new InstanceMethodsInterceptPoint[] {
- new InstanceMethodsInterceptPoint() {
- @Override
- public ElementMatcher<MethodDescription> getMethodsMatcher() {
- return named("execute");
- }
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("execute");
+ }
- @Override
- public String getMethodsInterceptor() {
- return INTERCEPT_CLASS;
- }
+ @Override
+ public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
- @Override
- public boolean isOverrideArgs() {
- return false;
- }
- },
- new InstanceMethodsInterceptPoint() {
- @Override
- public ElementMatcher<MethodDescription> getMethodsMatcher() {
- return named("enqueue").and(takesArguments(1));
- }
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("getResponseWithInterceptorChain");
+ }
- @Override
- public String getMethodsInterceptor() {
- return
"org.apache.skywalking.apm.plugin.okhttp.common.EnqueueInterceptor";
- }
+ @Override
+ public String getMethodsInterceptor() {
+ return
"org.apache.skywalking.apm.plugin.okhttp.common.CallInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("enqueue").and(takesArguments(1));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return
"org.apache.skywalking.apm.plugin.okhttp.common.EnqueueInterceptor";
+ }
- @Override
- public boolean isOverrideArgs() {
- return false;
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
}
- }
};
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v4/define/RealCallInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v4/define/RealCallInstrumentation.java
index ea97358..1f7edc8 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v4/define/RealCallInstrumentation.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/okhttp/v4/define/RealCallInstrumentation.java
@@ -18,6 +18,11 @@
package org.apache.skywalking.apm.plugin.okhttp.v4.define;
+import static net.bytebuddy.matcher.ElementMatchers.any;
+import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
@@ -25,10 +30,6 @@ import
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsIn
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
-import static net.bytebuddy.matcher.ElementMatchers.any;
-import static net.bytebuddy.matcher.ElementMatchers.named;
-import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
-
public class RealCallInstrumentation extends AbstractOkhttpInstrumentation {
/**
@@ -48,56 +49,72 @@ public class RealCallInstrumentation extends
AbstractOkhttpInstrumentation {
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
- return new ConstructorInterceptPoint[] {
- new ConstructorInterceptPoint() {
- @Override
- public ElementMatcher<MethodDescription>
getConstructorMatcher() {
- return any();
- }
+ return new ConstructorInterceptPoint[]{
+ new ConstructorInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getConstructorMatcher() {
+ return any();
+ }
- @Override
- public String getConstructorInterceptor() {
- return INTERCEPT_CLASS;
+ @Override
+ public String getConstructorInterceptor() {
+ return INTERCEPT_CLASS;
+ }
}
- }
};
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints()
{
- return new InstanceMethodsInterceptPoint[] {
- new InstanceMethodsInterceptPoint() {
- @Override
- public ElementMatcher<MethodDescription> getMethodsMatcher() {
- return named("execute");
- }
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("execute");
+ }
- @Override
- public String getMethodsInterceptor() {
- return INTERCEPT_CLASS;
- }
+ @Override
+ public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
- @Override
- public boolean isOverrideArgs() {
- return false;
- }
- },
- new InstanceMethodsInterceptPoint() {
- @Override
- public ElementMatcher<MethodDescription> getMethodsMatcher() {
- return named("enqueue").and(takesArguments(1));
- }
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return
nameStartsWith("getResponseWithInterceptorChain");
+ }
- @Override
- public String getMethodsInterceptor() {
- return
"org.apache.skywalking.apm.plugin.okhttp.common.EnqueueInterceptor";
- }
+ @Override
+ public String getMethodsInterceptor() {
+ return
"org.apache.skywalking.apm.plugin.okhttp.common.CallInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("enqueue").and(takesArguments(1));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return
"org.apache.skywalking.apm.plugin.okhttp.common.EnqueueInterceptor";
+ }
- @Override
- public boolean isOverrideArgs() {
- return false;
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
}
- }
};
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/AsyncCallInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/AsyncCallInterceptor.java
index 54364f4..20e966e 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/AsyncCallInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/AsyncCallInterceptor.java
@@ -18,23 +18,12 @@
package org.apache.skywalking.apm.plugin.okhttp.common;
-import okhttp3.Headers;
-import okhttp3.HttpUrl;
-import okhttp3.Request;
-import org.apache.skywalking.apm.agent.core.context.CarrierItem;
-import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.tag.Tags;
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
/**
* {@link AsyncCallInterceptor} get the `EnhanceRequiredInfo` instance from
`SkyWalkingDynamicField` and then put it
@@ -45,18 +34,6 @@ import java.lang.reflect.Method;
*/
public class AsyncCallInterceptor implements InstanceConstructorInterceptor,
InstanceMethodsAroundInterceptor {
- private static Field FIELD_HEADERS_OF_REQUEST;
-
- static {
- try {
- final Field field = Request.class.getDeclaredField("headers");
- field.setAccessible(true);
- FIELD_HEADERS_OF_REQUEST = field;
- } catch (Exception ignore) {
- FIELD_HEADERS_OF_REQUEST = null;
- }
- }
-
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
/**
@@ -71,43 +48,23 @@ public class AsyncCallInterceptor implements
InstanceConstructorInterceptor, Ins
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
+ MethodInterceptResult result) throws Throwable {
EnhanceRequiredInfo enhanceRequiredInfo = (EnhanceRequiredInfo)
objInst.getSkyWalkingDynamicField();
- Request request = (Request)
enhanceRequiredInfo.getRealCallEnhance().getSkyWalkingDynamicField();
-
- HttpUrl requestUrl = request.url();
- AbstractSpan span = ContextManager.createExitSpan(requestUrl.uri()
-
.getPath(), requestUrl.host() + ":" + requestUrl.port());
+ ContextManager.createLocalSpan("Async/execute");
ContextManager.continued(enhanceRequiredInfo.getContextSnapshot());
- ContextCarrier contextCarrier = new ContextCarrier();
- ContextManager.inject(contextCarrier);
- span.setComponent(ComponentsDefine.OKHTTP);
- Tags.HTTP.METHOD.set(span, request.method());
- Tags.URL.set(span, requestUrl.uri().toString());
- SpanLayer.asHttp(span);
-
- if (FIELD_HEADERS_OF_REQUEST != null) {
- Headers.Builder headerBuilder = request.headers().newBuilder();
- CarrierItem next = contextCarrier.items();
- while (next.hasNext()) {
- next = next.next();
- headerBuilder.set(next.getHeadKey(), next.getHeadValue());
- }
- FIELD_HEADERS_OF_REQUEST.set(request, headerBuilder.build());
- }
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
+ Object ret) throws Throwable {
ContextManager.stopSpan();
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments,
- Class<?>[] argumentsTypes, Throwable t) {
+ Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/CallInterceptor.java
similarity index 71%
copy from
apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
copy to
apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/CallInterceptor.java
index c944649..90b15a4 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/CallInterceptor.java
@@ -21,6 +21,8 @@ package org.apache.skywalking.apm.plugin.okhttp.common;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Request;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import okhttp3.Response;
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
@@ -29,18 +31,11 @@ import
org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-/**
- * {@link RealCallInterceptor} intercept the synchronous http calls by the
discovery of okhttp.
- */
-public class RealCallInterceptor implements InstanceMethodsAroundInterceptor,
InstanceConstructorInterceptor {
+public class CallInterceptor implements InstanceMethodsAroundInterceptor {
private static Field FIELD_HEADERS_OF_REQUEST;
@@ -55,32 +50,18 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
}
@Override
- public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
- objInst.setSkyWalkingDynamicField(allArguments[1]);
- }
-
- /**
- * Get the {@link Request} from {@link EnhancedInstance}, then create
{@link AbstractSpan} and set host,
- * port, kind, component, url from {@link Request}. Through the reflection
of the way, set the http header
- * of context data into {@link Request#headers}.
- *
- * @param result change this result, if you want to truncate the method.
- */
- @Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
+ MethodInterceptResult result) throws Throwable {
Request request = (Request) objInst.getSkyWalkingDynamicField();
-
- ContextCarrier contextCarrier = new ContextCarrier();
HttpUrl requestUrl = request.url();
AbstractSpan span = ContextManager.createExitSpan(requestUrl.uri()
-
.getPath(), contextCarrier, requestUrl.host() + ":" + requestUrl
- .port());
+ .getPath(), requestUrl.host() + ":" + requestUrl.port());
+ ContextCarrier contextCarrier = new ContextCarrier();
+ ContextManager.inject(contextCarrier);
span.setComponent(ComponentsDefine.OKHTTP);
Tags.HTTP.METHOD.set(span, request.method());
Tags.URL.set(span, requestUrl.uri().toString());
SpanLayer.asHttp(span);
-
if (FIELD_HEADERS_OF_REQUEST != null) {
Headers.Builder headerBuilder = request.headers().newBuilder();
CarrierItem next = contextCarrier.items();
@@ -92,15 +73,9 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
}
}
- /**
- * Get the status code from {@link Response}, when status code greater
than 400, it means there was some errors in
- * the server. Finish the {@link AbstractSpan}.
- *
- * @param ret the method's original return value.
- */
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
+ Object ret) throws Throwable {
Response response = (Response) ret;
if (response != null) {
int statusCode = response.code();
@@ -110,16 +85,13 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode);
}
}
-
ContextManager.stopSpan();
-
return ret;
}
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments,
- Class<?>[] argumentsTypes, Throwable t) {
- AbstractSpan abstractSpan = ContextManager.activeSpan();
- abstractSpan.log(t);
+ Class<?>[] argumentsTypes, Throwable t) {
+ ContextManager.activeSpan().log(t);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnFailureInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnFailureInterceptor.java
index 8b38b4c..7a75f9d 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnFailureInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnFailureInterceptor.java
@@ -29,12 +29,13 @@ public class OnFailureInterceptor implements
InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
- ContextManager.activeSpan().log((Throwable) allArguments[1]);
+ ContextManager.createLocalSpan("Callback/onFailure");
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
+ ContextManager.stopSpan();
return ret;
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
index 62728b3..b1bd3c1 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/OnResponseInterceptor.java
@@ -18,7 +18,6 @@
package org.apache.skywalking.apm.plugin.okhttp.common;
-import okhttp3.Response;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
@@ -34,16 +33,13 @@ public class OnResponseInterceptor implements
InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
- Response response = (Response) allArguments[1];
-
- if (response.code() >= 400) {
- ContextManager.activeSpan().errorOccurred();
- }
+ ContextManager.createLocalSpan("Callback/onResponse");
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
+ ContextManager.stopSpan();
return ret;
}
diff --git
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
index c944649..c305c55 100644
---
a/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/okhttp-common/src/main/java/org/apache/skywalking/apm/plugin/okhttp/common/RealCallInterceptor.java
@@ -18,6 +18,8 @@
package org.apache.skywalking.apm.plugin.okhttp.common;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Request;
@@ -34,9 +36,6 @@ import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceM
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
/**
* {@link RealCallInterceptor} intercept the synchronous http calls by the
discovery of okhttp.
*/
@@ -62,20 +61,19 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
/**
* Get the {@link Request} from {@link EnhancedInstance}, then create
{@link AbstractSpan} and set host,
* port, kind, component, url from {@link Request}. Through the reflection
of the way, set the http header
- * of context data into {@link Request#headers}.
+ * of context data into {@link Request#headers()}.
*
* @param result change this result, if you want to truncate the method.
*/
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
- MethodInterceptResult result) throws Throwable {
+ MethodInterceptResult result) throws Throwable {
Request request = (Request) objInst.getSkyWalkingDynamicField();
ContextCarrier contextCarrier = new ContextCarrier();
HttpUrl requestUrl = request.url();
- AbstractSpan span = ContextManager.createExitSpan(requestUrl.uri()
-
.getPath(), contextCarrier, requestUrl.host() + ":" + requestUrl
- .port());
+ AbstractSpan span =
ContextManager.createExitSpan(requestUrl.uri().getPath(), contextCarrier,
+ requestUrl.host() + ":" + requestUrl.port());
span.setComponent(ComponentsDefine.OKHTTP);
Tags.HTTP.METHOD.set(span, request.method());
Tags.URL.set(span, requestUrl.uri().toString());
@@ -100,7 +98,7 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
*/
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
- Object ret) throws Throwable {
+ Object ret) throws Throwable {
Response response = (Response) ret;
if (response != null) {
int statusCode = response.code();
@@ -118,7 +116,7 @@ public class RealCallInterceptor implements
InstanceMethodsAroundInterceptor, In
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments,
- Class<?>[] argumentsTypes, Throwable t) {
+ Class<?>[] argumentsTypes, Throwable t) {
AbstractSpan abstractSpan = ContextManager.activeSpan();
abstractSpan.log(t);
}
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml
b/apm-sniffer/apm-sdk-plugin/pom.xml
index dfafd19..b33edac 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -112,6 +112,7 @@
<module>httpclient-5.x-plugin</module>
<module>clickhouse-0.3.x-plugin</module>
<module>kylin-jdbc-2.6.x-3.x-4.x-plugin</module>
+ <module>okhttp-2.x-plugin</module>
</modules>
<packaging>pom</packaging>
diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md
b/docs/en/setup/service-agent/java-agent/Plugin-list.md
index e3aa29b..968b968 100644
--- a/docs/en/setup/service-agent/java-agent/Plugin-list.md
+++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md
@@ -126,3 +126,4 @@
- neo4j-4.x
- clickhouse-0.3.x
- kylin-jdbc-2.6.x-3.x-4.x
+- okhttp-2.x
diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md
b/docs/en/setup/service-agent/java-agent/Supported-list.md
index 98d49a9..9f5c980 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -22,7 +22,7 @@ metrics based on the tracing data.
* HTTP Client
* [Feign](https://github.com/OpenFeign/feign) 9.x
* [Netflix Spring Cloud
Feign](https://github.com/spring-cloud/spring-cloud-openfeign) 1.1.x -> 2.x
- * [Okhttp](https://github.com/square/okhttp) 3.x -> 4.x
+ * [Okhttp](https://github.com/square/okhttp) 2.x -> 3.x -> 4.x
* [Apache httpcomponent HttpClient](http://hc.apache.org/) 2.0 -> 3.1, 4.2,
4.3, 5.0, 5.1
* [Spring RestTemplete](https://github.com/spring-projects/spring-framework)
4.x
* [Jetty Client](http://www.eclipse.org/jetty/) 9
diff --git a/pom.xml b/pom.xml
index f90d4af..e7249bd 100755
--- a/pom.xml
+++ b/pom.xml
@@ -391,6 +391,7 @@
<sourceDirectories>
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
<sourceDirectory>${project.build.testSourceDirectory}</sourceDirectory>
+<sourceDirectory>scenarios/okhttp-scenario</sourceDirectory>
</sourceDirectories>
<resourceIncludes>
**/*.properties,
diff --git a/test/plugin/scenarios/okhttp-scenario/config/expectedData.yaml
b/test/plugin/scenarios/okhttp-scenario/config/expectedData.yaml
index fb12e4b..6407771 100644
--- a/test/plugin/scenarios/okhttp-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/okhttp-scenario/config/expectedData.yaml
@@ -56,8 +56,8 @@ segmentItems:
- {key: url, value:
'http://127.0.0.1:8080/okhttp-case/case/receiveContext-0'}
- {key: http.method, value: GET}
refs:
- - {parentEndpoint: /okhttp-case/case/receiveContext-0, networkAddress:
'127.0.0.1:8080',
- refType: CrossProcess, parentSpanId: 0, parentTraceSegmentId: not
null, parentServiceInstance: not
+ - {parentEndpoint: Async/execute, networkAddress: '127.0.0.1:8080',
+ refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not
null, parentServiceInstance: not
null, parentService: okhttp-scenario, traceId: not null}
skipAnalysis: 'false'
- segmentId: not null
@@ -75,15 +75,15 @@ segmentItems:
- {key: url, value:
'http://127.0.0.1:8080/okhttp-case/case/receiveContext-1'}
- {key: http.method, value: GET}
refs:
- - {parentEndpoint: /okhttp-case/case/receiveContext-0, networkAddress:
'127.0.0.1:8080',
- refType: CrossProcess, parentSpanId: 0, parentTraceSegmentId: not
null, parentServiceInstance: not
+ - {parentEndpoint: Async/execute, networkAddress: '127.0.0.1:8080',
+ refType: CrossProcess, parentSpanId: 3, parentTraceSegmentId: not
null, parentServiceInstance: not
null, parentService: okhttp-scenario, traceId: not null}
skipAnalysis: 'false'
- segmentId: not null
spans:
- operationName: /okhttp-case/case/receiveContext-0
- parentSpanId: -1
- spanId: 0
+ parentSpanId: 0
+ spanId: 1
spanLayer: Http
startTime: nq 0
endTime: nq 0
@@ -94,8 +94,37 @@ segmentItems:
tags:
- {key: http.method, value: GET}
- {key: url, value:
'http://127.0.0.1:8080/okhttp-case/case/receiveContext-0'}
- refs:
- - {parentEndpoint: GET:/case/okhttp-case, networkAddress: '', refType:
CrossThread,
- parentSpanId: 1, parentTraceSegmentId: not null,
parentServiceInstance: not
- null, parentService: okhttp-scenario, traceId: not null}
skipAnalysis: 'false'
+ - operationName: /okhttp-case/case/receiveContext-1
+ parentSpanId: 2
+ spanId: 3
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 12
+ isError: false
+ spanType: Exit
+ peer: 127.0.0.1:8080
+ skipAnalysis: false
+ tags:
+ - {key: http.method, value: GET}
+ - {key: url, value:
'http://127.0.0.1:8080/okhttp-case/case/receiveContext-1'}
+ - {operationName: Callback/onResponse, parentSpanId: 0, spanId: 2,
+ spanLayer: Unknown, startTime: nq 0, endTime: nq 0, componentId: 0,
+ isError: false, spanType: Local, peer: '', skipAnalysis: false}
+ - operationName: Async/execute
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Unknown
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 0
+ isError: false
+ spanType: Local
+ peer: ''
+ skipAnalysis: false
+ refs:
+ - {parentEndpoint: 'GET:/case/okhttp-case', networkAddress: '', refType:
CrossThread,
+ parentSpanId: 1, parentTraceSegmentId: not null,
+ parentServiceInstance: not null, parentService: okhttp-scenario,
+ traceId: not null}
diff --git a/test/plugin/scenarios/okhttp2-scenario/bin/startup.sh
b/test/plugin/scenarios/okhttp2-scenario/bin/startup.sh
new file mode 100644
index 0000000..6a7d3b6
--- /dev/null
+++ b/test/plugin/scenarios/okhttp2-scenario/bin/startup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -jar ${agent_opts} ${home}/../libs/okhttp2-scenario.jar &
\ No newline at end of file
diff --git a/test/plugin/scenarios/okhttp-scenario/config/expectedData.yaml
b/test/plugin/scenarios/okhttp2-scenario/config/expectedData.yaml
similarity index 52%
copy from test/plugin/scenarios/okhttp-scenario/config/expectedData.yaml
copy to test/plugin/scenarios/okhttp2-scenario/config/expectedData.yaml
index fb12e4b..4ed87e8 100644
--- a/test/plugin/scenarios/okhttp-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/okhttp2-scenario/config/expectedData.yaml
@@ -14,12 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
segmentItems:
-- serviceName: okhttp-scenario
+- serviceName: okhttp2-scenario
segmentSize: ge 5
segments:
- segmentId: not null
spans:
- - operationName: Async/okhttp-case/case/receiveContext-0
+ - operationName: Async/okhttp2-scenario/case/receiveContext-0
parentSpanId: 0
spanId: 1
startTime: nq 0
@@ -28,7 +28,7 @@ segmentItems:
isError: false
spanType: Local
skipAnalysis: 'false'
- - operationName: GET:/case/okhttp-case
+ - operationName: GET:/case/okhttp2-scenario
parentSpanId: -1
spanId: 0
spanLayer: Http
@@ -38,7 +38,7 @@ segmentItems:
isError: false
spanType: Entry
tags:
- - {key: url, value: 'http://localhost:8080/okhttp-case/case/okhttp-case'}
+ - {key: url, value:
'http://localhost:8080/okhttp2-scenario/case/okhttp2-scenario'}
- {key: http.method, value: GET}
skipAnalysis: 'false'
- segmentId: not null
@@ -53,12 +53,12 @@ segmentItems:
isError: false
spanType: Entry
tags:
- - {key: url, value:
'http://127.0.0.1:8080/okhttp-case/case/receiveContext-0'}
+ - {key: url, value:
'http://127.0.0.1:8080/okhttp2-scenario/case/receiveContext-0'}
- {key: http.method, value: GET}
refs:
- - {parentEndpoint: /okhttp-case/case/receiveContext-0, networkAddress:
'127.0.0.1:8080',
- refType: CrossProcess, parentSpanId: 0, parentTraceSegmentId: not
null, parentServiceInstance: not
- null, parentService: okhttp-scenario, traceId: not null}
+ - {parentEndpoint: Async/execute, networkAddress: '127.0.0.1:8080',
+ refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not
null, parentServiceInstance: not
+ null, parentService: okhttp2-scenario, traceId: not null}
skipAnalysis: 'false'
- segmentId: not null
spans:
@@ -72,18 +72,18 @@ segmentItems:
isError: false
spanType: Entry
tags:
- - {key: url, value:
'http://127.0.0.1:8080/okhttp-case/case/receiveContext-1'}
+ - {key: url, value:
'http://127.0.0.1:8080/okhttp2-scenario/case/receiveContext-1'}
- {key: http.method, value: GET}
refs:
- - {parentEndpoint: /okhttp-case/case/receiveContext-0, networkAddress:
'127.0.0.1:8080',
- refType: CrossProcess, parentSpanId: 0, parentTraceSegmentId: not
null, parentServiceInstance: not
- null, parentService: okhttp-scenario, traceId: not null}
+ - {parentEndpoint: Async/execute, networkAddress: '127.0.0.1:8080',
+ refType: CrossProcess, parentSpanId: 3, parentTraceSegmentId: not
null, parentServiceInstance: not
+ null, parentService: okhttp2-scenario, traceId: not null}
skipAnalysis: 'false'
- segmentId: not null
spans:
- - operationName: /okhttp-case/case/receiveContext-0
- parentSpanId: -1
- spanId: 0
+ - operationName: /okhttp2-scenario/case/receiveContext-0
+ parentSpanId: 0
+ spanId: 1
spanLayer: Http
startTime: nq 0
endTime: nq 0
@@ -93,9 +93,38 @@ segmentItems:
peer: 127.0.0.1:8080
tags:
- {key: http.method, value: GET}
- - {key: url, value:
'http://127.0.0.1:8080/okhttp-case/case/receiveContext-0'}
+ - {key: url, value:
'http://127.0.0.1:8080/okhttp2-scenario/case/receiveContext-0'}
+ - operationName: /okhttp2-scenario/case/receiveContext-1
+ parentSpanId: 2
+ spanId: 3
+ spanLayer: Http
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 12
+ isError: false
+ spanType: Exit
+ peer: 127.0.0.1:8080
+ skipAnalysis: false
+ tags:
+ - {key: http.method, value: GET}
+ - {key: url, value:
'http://127.0.0.1:8080/okhttp2-scenario/case/receiveContext-1'}
+ - {operationName: Callback/onResponse, parentSpanId: 0, spanId: 2,
+ spanLayer: Unknown, startTime: nq 0, endTime: nq 0, componentId: 0,
+ isError: false, spanType: Local, peer: '', skipAnalysis: false}
+ - operationName: Async/execute
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Unknown
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 0
+ isError: false
+ spanType: Local
+ peer: ''
+ skipAnalysis: false
refs:
- - {parentEndpoint: GET:/case/okhttp-case, networkAddress: '', refType:
CrossThread,
- parentSpanId: 1, parentTraceSegmentId: not null,
parentServiceInstance: not
- null, parentService: okhttp-scenario, traceId: not null}
- skipAnalysis: 'false'
+ - {parentEndpoint: 'GET:/case/okhttp2-scenario', networkAddress: '',
refType: CrossThread,
+ parentSpanId: 1, parentTraceSegmentId: not null,
+ parentServiceInstance: not null, parentService: okhttp2-scenario,
+ traceId: not null}
diff --git a/test/plugin/scenarios/okhttp2-scenario/configuration.yml
b/test/plugin/scenarios/okhttp2-scenario/configuration.yml
new file mode 100644
index 0000000..b350fc7
--- /dev/null
+++ b/test/plugin/scenarios/okhttp2-scenario/configuration.yml
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+type: jvm
+entryService: http://localhost:8080/okhttp2-scenario/case/okhttp2-scenario
+healthCheck: http://localhost:8080/okhttp2-scenario/case/healthCheck
+startScript: ./bin/startup.sh
diff --git a/test/plugin/scenarios/okhttp2-scenario/pom.xml
b/test/plugin/scenarios/okhttp2-scenario/pom.xml
new file mode 100644
index 0000000..f572427
--- /dev/null
+++ b/test/plugin/scenarios/okhttp2-scenario/pom.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You 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.
+ ~
+ -->
+<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/xsd/maven-4.0.0.xsd">
+
+ <groupId>org.apache.skywalking.apm.testcase</groupId>
+ <artifactId>okhttp2-scenario</artifactId>
+ <version>1.0.0</version>
+ <packaging>jar</packaging>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <compiler.version>1.8</compiler.version>
+ <test.framework.version>2.7.5</test.framework.version>
+ <spring-boot-version>2.1.6.RELEASE</spring-boot-version>
+ <lombok.version>1.18.20</lombok.version>
+ </properties>
+
+ <name>skywalking-okhttp2-scenario</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot-version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>${test.framework.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-log4j2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>${lombok.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>okhttp2-scenario</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>${compiler.version}</source>
+ <target>${compiler.version}</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>assemble</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+
<descriptor>src/main/assembly/assembly.xml</descriptor>
+ </descriptors>
+ <outputDirectory>./target/</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git
a/test/plugin/scenarios/okhttp2-scenario/src/main/assembly/assembly.xml
b/test/plugin/scenarios/okhttp2-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..e1f8765
--- /dev/null
+++ b/test/plugin/scenarios/okhttp2-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You 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.
+ ~
+ -->
+<assembly
+
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <fileSets>
+ <fileSet>
+ <directory>./bin</directory>
+ <fileMode>0775</fileMode>
+ </fileSet>
+ </fileSets>
+
+ <files>
+ <file>
+ <source>${project.build.directory}/okhttp2-scenario.jar</source>
+ <outputDirectory>./libs</outputDirectory>
+ <fileMode>0775</fileMode>
+ </file>
+ </files>
+</assembly>
diff --git
a/test/plugin/scenarios/okhttp2-scenario/src/main/java/test/apache/skywalking/apm/testcase/okhttp2/Application.java
b/test/plugin/scenarios/okhttp2-scenario/src/main/java/test/apache/skywalking/apm/testcase/okhttp2/Application.java
new file mode 100644
index 0000000..0b4d8b6
--- /dev/null
+++
b/test/plugin/scenarios/okhttp2-scenario/src/main/java/test/apache/skywalking/apm/testcase/okhttp2/Application.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 test.apache.skywalking.apm.testcase.okhttp2;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ try {
+ SpringApplication.run(Application.class, args);
+ } catch (Exception e) {
+ // Never do this
+ }
+ }
+}
diff --git
a/test/plugin/scenarios/okhttp2-scenario/src/main/java/test/apache/skywalking/apm/testcase/okhttp2/controller/CaseController.java
b/test/plugin/scenarios/okhttp2-scenario/src/main/java/test/apache/skywalking/apm/testcase/okhttp2/controller/CaseController.java
new file mode 100644
index 0000000..60aa663
--- /dev/null
+++
b/test/plugin/scenarios/okhttp2-scenario/src/main/java/test/apache/skywalking/apm/testcase/okhttp2/controller/CaseController.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 test.apache.skywalking.apm.testcase.okhttp2.controller;
+
+import com.squareup.okhttp.Callback;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+import java.io.IOException;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/case")
+@Log4j2
+public class CaseController {
+
+ private static final String SUCCESS = "Success";
+
+ @RequestMapping("/receiveContext-1")
+ @ResponseBody
+ public String receiveContextService1() throws InterruptedException {
+ return "receiveContext-1";
+ }
+
+ @RequestMapping("/receiveContext-0")
+ @ResponseBody
+ public String receiveContextService0() throws InterruptedException {
+ return "receiveContext-0";
+ }
+
+ @RequestMapping("/okhttp2-scenario")
+ @ResponseBody
+ public String okHttpScenario() {
+ // Like gateway forward trace header.
+ Request request = new
Request.Builder().url("http://127.0.0.1:8080/okhttp2-scenario/case/receiveContext-0")
+ .build();
+
+ new OkHttpClient().newCall(request).enqueue(new Callback() {
+ @Override
+ public void onFailure(Request request, IOException e) {
+
+ }
+
+ @Override
+ public void onResponse(Response response) throws IOException {
+ Request request = new Request.Builder().url(
+
"http://127.0.0.1:8080/okhttp2-scenario/case/receiveContext-1")
+ .build();
+ new OkHttpClient().newCall(request).execute();
+ }
+
+ });
+
+ return "Success";
+ }
+
+ @RequestMapping("/healthCheck")
+ @ResponseBody
+ public String healthCheck() {
+ // your codes
+ return SUCCESS;
+ }
+
+}
diff --git
a/test/plugin/scenarios/okhttp2-scenario/src/main/resources/application.yaml
b/test/plugin/scenarios/okhttp2-scenario/src/main/resources/application.yaml
new file mode 100644
index 0000000..aeff4b1
--- /dev/null
+++ b/test/plugin/scenarios/okhttp2-scenario/src/main/resources/application.yaml
@@ -0,0 +1,23 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+#
+server:
+ port: 8080
+ servlet:
+ context-path: /okhttp2-scenario
+logging:
+ config: classpath:log4j2.xml
\ No newline at end of file
diff --git
a/test/plugin/scenarios/okhttp2-scenario/src/main/resources/log4j2.xml
b/test/plugin/scenarios/okhttp2-scenario/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..9849ed5
--- /dev/null
+++ b/test/plugin/scenarios/okhttp2-scenario/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You 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.
+ ~
+ -->
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_ERR">
+ <PatternLayout charset="UTF-8" pattern="[%d{yyyy-MM-dd
HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="WARN">
+ <AppenderRef ref="Console"/>
+ </Root>
+ </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/test/plugin/scenarios/okhttp2-scenario/support-version.list
b/test/plugin/scenarios/okhttp2-scenario/support-version.list
new file mode 100644
index 0000000..f758f52
--- /dev/null
+++ b/test/plugin/scenarios/okhttp2-scenario/support-version.list
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# lists your version here (Contains only the last version number of each minor
version.)
+
+2.4.0
+2.5.0
+2.6.0
+2.7.5
\ No newline at end of file