From e89888668f4e6005e0d3dc14f3851f1770c2bde7 Mon Sep 17 00:00:00 2001 From: guyang Date: Sat, 17 Apr 2021 22:42:57 +0800 Subject: [PATCH] feature: jsonrpc4j plugin (#6743) --- .github/workflows/plugins-test.3.yaml | 1 + CHANGES.md | 1 + .../trace/component/ComponentsDefine.java | 2 + .../jsonrpc4j-1.x-plugin/pom.xml | 57 ++++++++ .../JsonRpcBasicServerInvokeInterceptor.java | 46 ++++++ .../plugin/jsonrpc4j/JsonRpcConstants.java | 25 ++++ .../JsonRpcHttpClientInterceptor.java | 82 +++++++++++ ...ttpClientPrepareConnectionInterceptor.java | 62 ++++++++ .../apm/plugin/jsonrpc4j/JsonRpcPeerInfo.java | 51 +++++++ .../JsonServiceExporterInterceptor.java | 82 +++++++++++ .../JsonRpcBasicServerInstrumentation.java | 67 +++++++++ .../JsonRpcHttpClientInstrumentation.java | 116 +++++++++++++++ .../JsonServiceExporterInstrumentation.java | 67 +++++++++ .../src/main/resources/skywalking-plugin.def | 19 +++ .../jsonrpc4j/JsonRpcHttpClientTests.java | 121 ++++++++++++++++ .../plugin/jsonrpc4j/JsonRpcServerTests.java | 136 ++++++++++++++++++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + .../main/resources/component-libraries.yml | 3 + .../config/expectedData.yaml | 1 + .../jsonrpc4j-1.x-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 91 ++++++++++++ .../jsonrpc4j-1.x-scenario/configuration.yml | 20 +++ .../scenarios/jsonrpc4j-1.x-scenario/pom.xml | 119 +++++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++++ .../apm/testcase/jsonrpc4j/Application.java | 36 +++++ .../jsonrpc4j/controller/CaseController.java | 52 +++++++ .../jsonrpc4j/services/DemoService.java | 27 ++++ .../jsonrpc4j/services/DemoServiceImp.java | 32 +++++ .../src/main/resources/application.yml | 20 +++ .../support-version.list | 20 +++ 31 files changed, 1420 insertions(+) create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcBasicServerInvokeInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcConstants.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientPrepareConnectionInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcPeerInfo.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonServiceExporterInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonRpcBasicServerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonRpcHttpClientInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonServiceExporterInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientTests.java create mode 100644 apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcServerTests.java create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/Application.java create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/controller/CaseController.java create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/services/DemoService.java create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/services/DemoServiceImp.java create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/resources/application.yml create mode 100644 test/plugin/scenarios/jsonrpc4j-1.x-scenario/support-version.list diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index 68be94eb2e..edada49a2b 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -71,6 +71,7 @@ jobs: - xxl-job-2.x-scenario - thrift-scenario - dbcp-2.x-scenario + - jsonrpc4j-1.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 1239be9fe3..d644bf881f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Release Notes. * Add `trace_segment_ref_limit_per_span` configuration mechanism to avoid OOM. * Improve `GlobalIdGenerator` performance. * Add an agent plugin to support elasticsearch7. +* Add `jsonrpc4j` agent plugin. #### OAP-Backend * BugFix: filter invalid Envoy access logs whose socket address is empty. diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index efcb4a1f4d..d004d099a6 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -194,4 +194,6 @@ public class ComponentsDefine { public static final OfficialComponent APACHE_CXF = new OfficialComponent(105, "Apache-CXF"); public static final OfficialComponent DOLPHIN_SCHEDULER = new OfficialComponent(106, "dolphinscheduler"); + + public static final OfficialComponent JSON_RPC = new OfficialComponent(107, "JsonRpc"); } diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml new file mode 100644 index 0000000000..a72fa840b3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml @@ -0,0 +1,57 @@ + + + + + + apm-sdk-plugin + org.apache.skywalking + 8.6.0-SNAPSHOT + + 4.0.0 + + jsonrpc4j-1.x-plugin + + + 1.5.3 + 3.0.1 + + + jar + + + + + com.github.briandilley.jsonrpc4j + jsonrpc4j + ${jsonrpc4j.version} + provided + + + + javax.servlet + javax.servlet-api + ${javax-servlet-api.version} + provided + + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcBasicServerInvokeInterceptor.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcBasicServerInvokeInterceptor.java new file mode 100644 index 0000000000..569dc01fed --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcBasicServerInvokeInterceptor.java @@ -0,0 +1,46 @@ +/* + * 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.jsonrpc4j; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +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; + +public class JsonRpcBasicServerInvokeInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, MethodInterceptResult result) throws Throwable { + Method rpcMethod = (Method) objects[1]; + AbstractSpan span = ContextManager.activeSpan(); + JsonRpcConstants.JSON_RPC_METHOD_TAG.set(span, rpcMethod.getName()); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, Object ret) throws Throwable { + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, Throwable throwable) { + ContextManager.activeSpan().log(throwable); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcConstants.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcConstants.java new file mode 100644 index 0000000000..191c211dea --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcConstants.java @@ -0,0 +1,25 @@ +/* + * 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.jsonrpc4j; + +import org.apache.skywalking.apm.agent.core.context.tag.StringTag; + +public class JsonRpcConstants { + public static final StringTag JSON_RPC_METHOD_TAG = new StringTag(1, "jsonrpc.method"); +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientInterceptor.java new file mode 100644 index 0000000000..8c64b43f7e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientInterceptor.java @@ -0,0 +1,82 @@ +/* + * 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.jsonrpc4j; + +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.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.Method; +import java.net.URL; + +@SuppressWarnings("unused") +public class JsonRpcHttpClientInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] objects) { + URL url = (URL) objects[1]; + JsonRpcPeerInfo clientDto = new JsonRpcPeerInfo(); + int port = url.getPort(); + if (port < 0) { + if (isHttps(url)) { + port = 443; + } else { + port = 80; + } + } + + clientDto.setPort(port); + clientDto.setServiceUrl(url); + objInst.setSkyWalkingDynamicField(clientDto); + } + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, MethodInterceptResult result) throws Throwable { + JsonRpcPeerInfo clientDto = (JsonRpcPeerInfo) objInst.getSkyWalkingDynamicField(); + String methodName = objects[0].toString(); + String operationName = clientDto.getServiceUrl().getPath() + "." + methodName; + AbstractSpan span = ContextManager.createExitSpan(operationName, new ContextCarrier(), clientDto.getServiceUrl().getHost() + ":" + clientDto.getPort()); + span.setComponent(ComponentsDefine.JSON_RPC); + Tags.HTTP.METHOD.set(span, "POST"); + Tags.URL.set(span, clientDto.getServiceUrlString()); + SpanLayer.asRPCFramework(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, Object o) throws Throwable { + ContextManager.stopSpan(); + return o; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, Throwable throwable) { + ContextManager.activeSpan().log(throwable); + } + + private boolean isHttps(URL url) { + return url.getProtocol().equals("https"); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientPrepareConnectionInterceptor.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientPrepareConnectionInterceptor.java new file mode 100644 index 0000000000..b2d49f1d78 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientPrepareConnectionInterceptor.java @@ -0,0 +1,62 @@ +/* + * 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.jsonrpc4j; + +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.trace.AbstractSpan; +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; +import java.net.HttpURLConnection; + +@SuppressWarnings("unused") +public class JsonRpcHttpClientPrepareConnectionInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, MethodInterceptResult result) { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, Object retObj) { + HttpURLConnection connection = (HttpURLConnection) retObj; + AbstractSpan span = ContextManager.activeSpan(); + if (span == null) { + return retObj; + } + + ContextCarrier carrier = new ContextCarrier(); + ContextManager.inject(carrier); + CarrierItem item = carrier.items(); + if (item.hasNext()) { + item = item.next(); + connection.setRequestProperty(item.getHeadKey(), item.getHeadValue()); + } + + return retObj; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, Throwable throwable) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcPeerInfo.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcPeerInfo.java new file mode 100644 index 0000000000..bb59a12fb2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcPeerInfo.java @@ -0,0 +1,51 @@ +/* + * 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.jsonrpc4j; + +import java.net.URL; + +public class JsonRpcPeerInfo { + + private URL serviceUrl; + + private String serviceUrlString; + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + private int port; + + public URL getServiceUrl() { + return serviceUrl; + } + + public void setServiceUrl(URL serviceUrl) { + this.serviceUrl = serviceUrl; + this.serviceUrlString = serviceUrl.toString(); + } + + public String getServiceUrlString() { + return serviceUrlString; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonServiceExporterInterceptor.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonServiceExporterInterceptor.java new file mode 100644 index 0000000000..ebd5add5d6 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonServiceExporterInterceptor.java @@ -0,0 +1,82 @@ +/* + * 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.jsonrpc4j; + +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.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 org.apache.skywalking.apm.agent.core.util.MethodUtil; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; + +public class JsonServiceExporterInterceptor implements InstanceMethodsAroundInterceptor { + + private static boolean IS_SERVLET_GET_STATUS_METHOD_EXIST; + private static final String SERVLET_RESPONSE_CLASS = "javax.servlet.http.HttpServletResponse"; + private static final String GET_STATUS_METHOD = "getStatus"; + + static { + IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist(JsonServiceExporterInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); + } + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, MethodInterceptResult result) throws Throwable { + + HttpServletRequest request = (HttpServletRequest) objects[0]; + ContextCarrier contextCarrier = new ContextCarrier(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + next.setHeadValue(request.getHeader(next.getHeadKey())); + } + + AbstractSpan span = ContextManager.createEntrySpan(request.getRequestURI(), contextCarrier); + Tags.HTTP.METHOD.set(span, request.getMethod()); + Tags.URL.set(span, request.getRequestURL().toString()); + span.setComponent(ComponentsDefine.JSON_RPC); + SpanLayer.asRPCFramework(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, Object ret) throws Throwable { + + HttpServletResponse response = (HttpServletResponse) objects[1]; + AbstractSpan span = ContextManager.activeSpan(); + if (IS_SERVLET_GET_STATUS_METHOD_EXIST) { + Tags.STATUS_CODE.set(span, String.valueOf(response.getStatus())); + } + + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] objects, Class[] classes, Throwable throwable) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonRpcBasicServerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonRpcBasicServerInstrumentation.java new file mode 100644 index 0000000000..606237e819 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonRpcBasicServerInstrumentation.java @@ -0,0 +1,67 @@ +/* + * 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.jsonrpc4j.define; + +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; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public class JsonRpcBasicServerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + public static final String ENHANCE_CLASS = "com.googlecode.jsonrpc4j.JsonRpcBasicServer"; + public static final String INVOKE_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jsonrpc4j.JsonRpcBasicServerInvokeInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("invoke"); + } + + @Override + public String getMethodsInterceptor() { + return INVOKE_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonRpcHttpClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonRpcHttpClientInstrumentation.java new file mode 100644 index 0000000000..212e6b8971 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonRpcHttpClientInstrumentation.java @@ -0,0 +1,116 @@ +/* + * 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.jsonrpc4j.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +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; + +import java.net.URL; + +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; + +@SuppressWarnings("unused") +public class JsonRpcHttpClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + public static final String ENHANCE_CLASS = "com.googlecode.jsonrpc4j.JsonRpcHttpClient"; + + public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jsonrpc4j.JsonRpcHttpClientInterceptor"; + + public static final String PER_CONNECTION_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jsonrpc4j.JsonRpcHttpClientPrepareConnectionInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return ElementMatchers.takesArguments(6).and(ElementMatchers.takesArgument(1, URL.class)); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + }, + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return ElementMatchers.takesArguments(5).and(ElementMatchers.takesArgument(1, URL.class)); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + + return ElementMatchers.named("invoke").and(ElementMatchers.takesArguments(4)) + .and(takesArgumentWithType(2, "java.lang.reflect.Type")); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named("prepareConnection"); + } + + @Override + public String getMethodsInterceptor() { + return PER_CONNECTION_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonServiceExporterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonServiceExporterInstrumentation.java new file mode 100644 index 0000000000..4cee21b6ea --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jsonrpc4j/define/JsonServiceExporterInstrumentation.java @@ -0,0 +1,67 @@ +/* + * 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.jsonrpc4j.define; + +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; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public class JsonServiceExporterInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + public static final String ENHANCE_CLASS = "com.googlecode.jsonrpc4j.spring.JsonServiceExporter"; + public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jsonrpc4j.JsonServiceExporterInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("handleRequest"); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..5fb503472a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.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. + +jsonrpc4j=org.apache.skywalking.apm.plugin.jsonrpc4j.define.JsonRpcHttpClientInstrumentation +jsonrpc4j=org.apache.skywalking.apm.plugin.jsonrpc4j.define.JsonRpcBasicServerInstrumentation +jsonrpc4j=org.apache.skywalking.apm.plugin.jsonrpc4j.define.JsonServiceExporterInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientTests.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientTests.java new file mode 100644 index 0000000000..9296391c28 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcHttpClientTests.java @@ -0,0 +1,121 @@ +/* + * 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.jsonrpc4j; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.googlecode.jsonrpc4j.JsonRpcHttpClient; +import org.apache.skywalking.apm.agent.core.boot.OverrideImplementor; +import org.apache.skywalking.apm.agent.core.context.ContextManagerExtendService; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.context.util.TagValuePair; +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.TracingSegmentRunner; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; + +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class JsonRpcHttpClientTests { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + private MockJsonRpcHttpClient enhancedInstance; + private ObjectMapper objectMapper = new ObjectMapper(); + + private JsonRpcHttpClientInterceptor httpClientInterceptor; + private JsonRpcHttpClientPrepareConnectionInterceptor jsonRpcHttpClientPrepareConnectionInterceptor; + private URL url; + private HttpURLConnection httpURLConnection; + + @Before + public void setUp() throws Exception { + url = new URL("HTTP://localhost:8080/test"); + enhancedInstance = new MockJsonRpcHttpClient(objectMapper, url, new HashMap<>(), false, false); + httpClientInterceptor = new JsonRpcHttpClientInterceptor(); + jsonRpcHttpClientPrepareConnectionInterceptor = new JsonRpcHttpClientPrepareConnectionInterceptor(); + httpURLConnection = (HttpURLConnection) url.openConnection(); + } + + @Test + public void testMethodAround() throws Throwable { + Object[] objects = new Object[]{"OperationKey", url}; + httpClientInterceptor.onConstruct(enhancedInstance, objects); + httpClientInterceptor.beforeMethod(enhancedInstance, null, objects, null, null); + jsonRpcHttpClientPrepareConnectionInterceptor.afterMethod(enhancedInstance, null, null, null, httpURLConnection); + httpClientInterceptor.afterMethod(enhancedInstance, null, objects, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + Assert.assertEquals(1, SegmentHelper.getSpans(traceSegment).size()); + AbstractTracingSpan finishedSpan = SegmentHelper.getSpans(traceSegment).get(0); + + List tags = SpanHelper.getTags(finishedSpan); + assertThat(tags.size(), is(2)); + assertThat(tags.get(0).getValue(), is("POST")); + assertThat(tags.get(1).getValue(), is(url.toString())); + Assert.assertEquals(false, SpanHelper.getErrorOccurred(finishedSpan)); + } + + private class MockJsonRpcHttpClient extends JsonRpcHttpClient implements EnhancedInstance { + + private Object object; + + public MockJsonRpcHttpClient(ObjectMapper mapper, URL serviceUrl, Map headers, boolean gzipRequests, boolean acceptGzipResponses) { + super(mapper, serviceUrl, headers, gzipRequests, acceptGzipResponses); + } + + @Override + public Object getSkyWalkingDynamicField() { + return object; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + object = value; + } + } + + @OverrideImplementor(ContextManagerExtendService.class) + public static class ContextManagerExtendOverrideService extends ContextManagerExtendService { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcServerTests.java b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcServerTests.java new file mode 100644 index 0000000000..e50b7d389b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jsonrpc4j/JsonRpcServerTests.java @@ -0,0 +1,136 @@ +/* + * 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.jsonrpc4j; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.googlecode.jsonrpc4j.JsonRpcBasicServer; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.context.util.TagValuePair; +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.TracingSegmentRunner; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.List; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class JsonRpcServerTests { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + private MockJsonRpcBasicServer mockJsonRpcBasicServer; + + private MockJsonServiceExporterInterceptor mockJsonServiceExporterInterceptor; + + private JsonServiceExporterInterceptor jsonServiceExporterInterceptor; + + private JsonRpcBasicServerInvokeInterceptor jsonRpcBasicServerInvokeInterceptor; + + private ObjectMapper objectMapper = new ObjectMapper(); + + private HttpServletRequest httpServletRequest; + + private HttpServletResponse httpServletResponse; + + @Before + public void setUp() throws Exception { + httpServletRequest = mock(HttpServletRequest.class); + httpServletResponse = mock(HttpServletResponse.class); + when(httpServletRequest.getRequestURI()).thenReturn("/test"); + when(httpServletRequest.getRequestURL()).thenReturn(new StringBuffer("http://localhost:8080")); + when(httpServletResponse.getStatus()).thenReturn(200); + httpServletResponse = mock(HttpServletResponse.class); + jsonRpcBasicServerInvokeInterceptor = new JsonRpcBasicServerInvokeInterceptor(); + jsonServiceExporterInterceptor = new JsonServiceExporterInterceptor(); + mockJsonRpcBasicServer = new MockJsonRpcBasicServer(objectMapper, null); + mockJsonServiceExporterInterceptor = new MockJsonServiceExporterInterceptor(); + } + + @Test + public void testJsonRpcServerMethodAround() throws Throwable { + Object[] objects = new Object[]{httpServletRequest}; + jsonServiceExporterInterceptor.beforeMethod(mockJsonServiceExporterInterceptor, null, objects, null, null); + objects = new Object[]{null, JsonRpcServerTests.class.getMethod("testJsonRpcServerMethodAround")}; + jsonRpcBasicServerInvokeInterceptor.beforeMethod(mockJsonRpcBasicServer, null, objects, null, null); + objects = new Object[]{null, httpServletResponse}; + jsonServiceExporterInterceptor.afterMethod(mockJsonServiceExporterInterceptor, null, objects, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + Assert.assertEquals(1, SegmentHelper.getSpans(traceSegment).size()); + AbstractTracingSpan finishedSpan = SegmentHelper.getSpans(traceSegment).get(0); + + List tags = SpanHelper.getTags(finishedSpan); + assertThat(tags.size(), is(4)); + Assert.assertEquals(false, SpanHelper.getErrorOccurred(finishedSpan)); + } + + private class MockJsonRpcBasicServer extends JsonRpcBasicServer implements EnhancedInstance { + + public MockJsonRpcBasicServer(ObjectMapper mapper, Object handler) { + super(mapper, handler); + } + + @Override + public Object getSkyWalkingDynamicField() { + return null; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + } + } + + private class MockJsonServiceExporterInterceptor extends JsonServiceExporterInterceptor implements EnhancedInstance { + + @Override + public Object getSkyWalkingDynamicField() { + return null; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 8bbca4a930..57464edad0 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -109,6 +109,7 @@ mssql-jtds-1.x-plugin mssql-jdbc-plugin cxf-3.x-plugin + jsonrpc4j-1.x-plugin pom 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 07ee1511e1..c082e232bc 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -114,3 +114,4 @@ - mssql-jtds-1.x - mssql-jdbc - apache-cxf-3.x +- jsonrpc4j diff --git a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml index 892a18a88b..7bfaaf3b3d 100755 --- a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml +++ b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml @@ -350,6 +350,9 @@ Apache-CXF: dolphinscheduler: id: 106 languages: Java +JsonRpc: + id: 107 + languages: Java # .NET/.NET Core components # [3000, 4000) for C#/.NET only diff --git a/test/plugin/scenarios/dubbo-2.7.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/dubbo-2.7.x-scenario/config/expectedData.yaml index a6939e6aaa..898b7feed2 100644 --- a/test/plugin/scenarios/dubbo-2.7.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/dubbo-2.7.x-scenario/config/expectedData.yaml @@ -13,6 +13,7 @@ # 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. + segmentItems: - serviceName: dubbo-2.7.x-scenario segmentSize: ge 3 diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/bin/startup.sh b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..d7548dd340 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-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/jsonrpc4j-1.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..3d4a452381 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/config/expectedData.yaml @@ -0,0 +1,91 @@ +# 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. + +segmentItems: + - serviceName: jsonrpc4j-1.x-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: /jsonrpc4j-1.x-scenario/path/to/demo-service.sayHello + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 107 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - { key: http.method, value: POST } + - { + key: url, + value: 'http://localhost:8080/jsonrpc4j-1.x-scenario/path/to/demo-service', + } + - operationName: /jsonrpc4j-1.x-scenario/case/json-rpc + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - { + key: url, + value: 'http://localhost:8080/jsonrpc4j-1.x-scenario/case/json-rpc', + } + - { key: http.method, value: GET } + - segmentId: not null + spans: + - operationName: /jsonrpc4j-1.x-scenario/path/to/demo-service + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 107 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - { key: http.method, value: POST } + - { + key: url, + value: 'http://localhost:8080/jsonrpc4j-1.x-scenario/path/to/demo-service', + } + - { key: jsonrpc.method, value: sayHello } + - { key: status_code, value: '200' } + refs: + - { + parentEndpoint: /jsonrpc4j-1.x-scenario/case/json-rpc, + networkAddress: 'localhost:8080', + refType: CrossProcess, + parentSpanId: 1, + parentTraceSegmentId: not null, + parentServiceInstance: not null, + parentService: jsonrpc4j-1.x-scenario, + traceId: not null, + } diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/configuration.yml b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/configuration.yml new file mode 100644 index 0000000000..33541449b1 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-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/jsonrpc4j-1.x-scenario/case/json-rpc +healthCheck: http://localhost:8080/jsonrpc4j-1.x-scenario/case/healthCheck +startScript: ./bin/startup.sh diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/pom.xml b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/pom.xml new file mode 100644 index 0000000000..4579d75f1e --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/pom.xml @@ -0,0 +1,119 @@ + + + + + 4.0.0 + + org.apache.skywalking + jsonrpc4j-1.x-scenario + 5.0.0 + jar + + + 8 + 8 + UTF-8 + 1.8 + 2.1.6.RELEASE + 1.5.3 + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.github.briandilley.jsonrpc4j + jsonrpc4j + ${jsonrpc.version} + + + + + jsonrpc4j-1.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + maven-compiler-plugin + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + + + + spring-snapshots + https://repo.spring.io/snapshot + + + spring-milestones + https://repo.spring.io/milestone + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..5cbaa11904 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ./target/jsonrpc4j-1.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/Application.java b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/Application.java new file mode 100644 index 0000000000..d9955df121 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/Application.java @@ -0,0 +1,36 @@ +/* + * 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.testcase.jsonrpc4j; + +import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImplExporter; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public AutoJsonRpcServiceImplExporter serviceImplExporter() { + return new AutoJsonRpcServiceImplExporter(); + } +} diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/controller/CaseController.java b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/controller/CaseController.java new file mode 100644 index 0000000000..ed14c9b012 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/controller/CaseController.java @@ -0,0 +1,52 @@ +/* + * 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.testcase.jsonrpc4j.controller; + +import com.googlecode.jsonrpc4j.JsonRpcHttpClient; +import com.googlecode.jsonrpc4j.ProxyUtil; +import org.apache.skywalking.apm.testcase.jsonrpc4j.services.DemoService; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import java.net.MalformedURLException; +import java.net.URL; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final String SUCCESS = "Success"; + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + return SUCCESS; + } + + @RequestMapping("/json-rpc") + @ResponseBody + public String jsonRpc() throws MalformedURLException { + JsonRpcHttpClient client = new JsonRpcHttpClient( + new URL("http://localhost:8080/jsonrpc4j-1.x-scenario/path/to/demo-service")); + DemoService demoService = ProxyUtil.createClientProxy(getClass().getClassLoader(), DemoService.class, client); + demoService.sayHello(); + return SUCCESS; + } +} diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/services/DemoService.java b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/services/DemoService.java new file mode 100644 index 0000000000..05378fc390 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/services/DemoService.java @@ -0,0 +1,27 @@ +/* + * 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.testcase.jsonrpc4j.services; + +import com.googlecode.jsonrpc4j.JsonRpcService; + +@JsonRpcService("/path/to/demo-service") +public interface DemoService { + + String sayHello(); +} diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/services/DemoServiceImp.java b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/services/DemoServiceImp.java new file mode 100644 index 0000000000..5323cc2e81 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jsonrpc4j/services/DemoServiceImp.java @@ -0,0 +1,32 @@ +/* + * 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.testcase.jsonrpc4j.services; + +import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImpl; +import org.springframework.stereotype.Service; + +@AutoJsonRpcServiceImpl +@Service +public class DemoServiceImp implements DemoService { + + @Override + public String sayHello() { + return "hello"; + } +} diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/resources/application.yml b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/resources/application.yml new file mode 100644 index 0000000000..b756cca3f5 --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/src/main/resources/application.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. + +server: + port: 8080 + servlet: + context-path: /jsonrpc4j-1.x-scenario diff --git a/test/plugin/scenarios/jsonrpc4j-1.x-scenario/support-version.list b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/support-version.list new file mode 100644 index 0000000000..b54a46899f --- /dev/null +++ b/test/plugin/scenarios/jsonrpc4j-1.x-scenario/support-version.list @@ -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. + +1.6 +1.5.3 +1.4.6 +1.3.3 -- GitLab