Support dubbo 2.7.x (#2365)
* support dubbo 2.7.x * updated * rename package * rename package * fix UT * rename class
This commit is contained in:
parent
0d4774d9a0
commit
4139389168
|
|
@ -0,0 +1,44 @@
|
|||
<?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>6.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>dubbo-2.7.x-conflict-patch</artifactId>
|
||||
|
||||
<name>apm-dubbo-2.7.x-conflict-path</name>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<dubbo.version>2.7.0</dubbo.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo</artifactId>
|
||||
<version>${dubbo.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
* 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.asf.dubbo.patch;
|
||||
|
||||
import org.apache.dubbo.common.bytecode.ClassGenerator;
|
||||
import org.apache.dubbo.common.bytecode.NoSuchPropertyException;
|
||||
import org.apache.dubbo.common.bytecode.Wrapper;
|
||||
import org.apache.dubbo.common.utils.ClassHelper;
|
||||
import org.apache.dubbo.common.utils.ReflectUtils;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.regex.Matcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor;
|
||||
|
||||
public class MakeWrapperInterceptor implements StaticMethodsAroundInterceptor {
|
||||
|
||||
private static final AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0);
|
||||
|
||||
@Override
|
||||
public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
|
||||
MethodInterceptResult result) {
|
||||
Class wrapperClass = (Class<?>)allArguments[0];
|
||||
if (EnhancedInstance.class.isAssignableFrom(wrapperClass)) {
|
||||
result.defineReturnValue(makeWrapper(wrapperClass));
|
||||
}
|
||||
}
|
||||
|
||||
@Override public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
|
||||
Object ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
|
||||
Throwable t) {
|
||||
}
|
||||
|
||||
private static Wrapper makeWrapper(Class<?> c) {
|
||||
if (c.isPrimitive())
|
||||
throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);
|
||||
|
||||
String name = c.getName();
|
||||
ClassLoader cl = ClassHelper.getClassLoader(c);
|
||||
|
||||
StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
|
||||
StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
|
||||
StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ ");
|
||||
|
||||
c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
|
||||
c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
|
||||
c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
|
||||
|
||||
Map<String, Class<?>> pts = new HashMap<String, Class<?>>(); // <property name, property types>
|
||||
Map<String, Method> ms = new LinkedHashMap<String, Method>(); // <method desc, Method instance>
|
||||
List<String> mns = new ArrayList<String>(); // method names.
|
||||
List<String> dmns = new ArrayList<String>(); // declaring method names.
|
||||
|
||||
// get all public field.
|
||||
for (Field f : c.getFields()) {
|
||||
String fn = f.getName();
|
||||
Class<?> ft = f.getType();
|
||||
if (Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers()))
|
||||
continue;
|
||||
|
||||
c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
|
||||
c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");
|
||||
pts.put(fn, ft);
|
||||
}
|
||||
|
||||
Method[] methods = c.getMethods();
|
||||
// get all public method.
|
||||
boolean hasMethod = hasMethods(methods);
|
||||
if (hasMethod) {
|
||||
c3.append(" try{");
|
||||
}
|
||||
for (Method m : methods) {
|
||||
// ignore Object's method
|
||||
// ignore EnhanceInstance's method
|
||||
if (m.getDeclaringClass() == Object.class || "getSkyWalkingDynamicField".equals(m.getName()) || "setSkyWalkingDynamicField".equals(m.getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String mn = m.getName();
|
||||
c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");
|
||||
int len = m.getParameterTypes().length;
|
||||
c3.append(" && ").append(" $3.length == ").append(len);
|
||||
|
||||
boolean override = false;
|
||||
for (Method m2 : methods) {
|
||||
if (m != m2 && m.getName().equals(m2.getName())) {
|
||||
override = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (override) {
|
||||
if (len > 0) {
|
||||
for (int l = 0; l < len; l++) {
|
||||
c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"")
|
||||
.append(m.getParameterTypes()[l].getName()).append("\")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c3.append(" ) { ");
|
||||
|
||||
if (m.getReturnType() == Void.TYPE)
|
||||
c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
|
||||
else
|
||||
c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");
|
||||
|
||||
c3.append(" }");
|
||||
|
||||
mns.add(mn);
|
||||
if (m.getDeclaringClass() == c)
|
||||
dmns.add(mn);
|
||||
ms.put(ReflectUtils.getDesc(m), m);
|
||||
}
|
||||
if (hasMethod) {
|
||||
c3.append(" } catch(Throwable e) { ");
|
||||
c3.append(" throw new java.lang.reflect.InvocationTargetException(e); ");
|
||||
c3.append(" }");
|
||||
}
|
||||
|
||||
c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }");
|
||||
|
||||
// deal with get/set method.
|
||||
Matcher matcher;
|
||||
for (Map.Entry<String, Method> entry : ms.entrySet()) {
|
||||
String md = entry.getKey();
|
||||
Method method = (Method)entry.getValue();
|
||||
if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
|
||||
String pn = propertyName(matcher.group(1));
|
||||
c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
|
||||
pts.put(pn, method.getReturnType());
|
||||
} else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) {
|
||||
String pn = propertyName(matcher.group(1));
|
||||
c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
|
||||
pts.put(pn, method.getReturnType());
|
||||
} else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
|
||||
Class<?> pt = method.getParameterTypes()[0];
|
||||
String pn = propertyName(matcher.group(1));
|
||||
c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }");
|
||||
pts.put(pn, pt);
|
||||
}
|
||||
}
|
||||
c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
|
||||
c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
|
||||
|
||||
// make class
|
||||
long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
|
||||
ClassGenerator cc = ClassGenerator.newInstance(cl);
|
||||
cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() + "_swEnhance" : c.getName() + "$sw$_swEnhance") + id);
|
||||
cc.setSuperClass(Wrapper.class);
|
||||
|
||||
cc.addDefaultConstructor();
|
||||
cc.addField("public static String[] pns;"); // property name array.
|
||||
cc.addField("public static " + Map.class.getName() + " pts;"); // property type map.
|
||||
cc.addField("public static String[] mns;"); // all method name array.
|
||||
cc.addField("public static String[] dmns;"); // declared method name array.
|
||||
for (int i = 0, len = ms.size(); i < len; i++)
|
||||
cc.addField("public static Class[] mts" + i + ";");
|
||||
|
||||
cc.addMethod("public String[] getPropertyNames(){ return pns; }");
|
||||
cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
|
||||
cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }");
|
||||
cc.addMethod("public String[] getMethodNames(){ return mns; }");
|
||||
cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }");
|
||||
cc.addMethod(c1.toString());
|
||||
cc.addMethod(c2.toString());
|
||||
cc.addMethod(c3.toString());
|
||||
|
||||
try {
|
||||
Class<?> wc = cc.toClass();
|
||||
// setup static field.
|
||||
wc.getField("pts").set(null, pts);
|
||||
wc.getField("pns").set(null, pts.keySet().toArray(new String[0]));
|
||||
wc.getField("mns").set(null, mns.toArray(new String[0]));
|
||||
wc.getField("dmns").set(null, dmns.toArray(new String[0]));
|
||||
int ix = 0;
|
||||
for (Method m : ms.values())
|
||||
wc.getField("mts" + ix++).set(null, m.getParameterTypes());
|
||||
return (Wrapper)wc.newInstance();
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
} finally {
|
||||
cc.release();
|
||||
ms.clear();
|
||||
mns.clear();
|
||||
dmns.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static String args(Class<?>[] cs, String name) {
|
||||
int len = cs.length;
|
||||
if (len == 0)
|
||||
return "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i > 0)
|
||||
sb.append(',');
|
||||
sb.append(arg(cs[i], name + "[" + i + "]"));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String propertyName(String pn) {
|
||||
return pn.length() == 1 || Character.isLowerCase(pn.charAt(1)) ? Character.toLowerCase(pn.charAt(0)) + pn.substring(1) : pn;
|
||||
}
|
||||
|
||||
private static boolean hasMethods(Method[] methods) {
|
||||
if (methods == null || methods.length == 0) {
|
||||
return false;
|
||||
}
|
||||
for (Method m : methods) {
|
||||
if (m.getDeclaringClass() != Object.class) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String arg(Class<?> cl, String name) {
|
||||
if (cl.isPrimitive()) {
|
||||
if (cl == Boolean.TYPE)
|
||||
return "((Boolean)" + name + ").booleanValue()";
|
||||
if (cl == Byte.TYPE)
|
||||
return "((Byte)" + name + ").byteValue()";
|
||||
if (cl == Character.TYPE)
|
||||
return "((Character)" + name + ").charValue()";
|
||||
if (cl == Double.TYPE)
|
||||
return "((Number)" + name + ").doubleValue()";
|
||||
if (cl == Float.TYPE)
|
||||
return "((Number)" + name + ").floatValue()";
|
||||
if (cl == Integer.TYPE)
|
||||
return "((Number)" + name + ").intValue()";
|
||||
if (cl == Long.TYPE)
|
||||
return "((Number)" + name + ").longValue()";
|
||||
if (cl == Short.TYPE)
|
||||
return "((Number)" + name + ").shortValue()";
|
||||
throw new RuntimeException("Unknown primitive type: " + cl.getName());
|
||||
}
|
||||
return "(" + ReflectUtils.getName(cl) + ")" + name;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.asf.dubbo.patch;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassStaticMethodsEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
/**
|
||||
* The dubbo conflict plugin resolver the problem about the wrapper class generated by Dubbo core cannot be compiled successfully. As we known,
|
||||
* The wrapper class traverses all the methods. In usual, it works unless this
|
||||
* class has been enhanced by Skywalking. The javasist cannot found the `EnhanceInstance` method when generate.
|
||||
*
|
||||
* The plugin excludes {@link org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance}
|
||||
* methods to ensure the correct compilation of the code.
|
||||
*/
|
||||
public class WrapperInstrumentation extends ClassStaticMethodsEnhancePluginDefine {
|
||||
@Override protected StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
|
||||
return new StaticMethodsInterceptPoint[] {
|
||||
new StaticMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named("makeWrapper");
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return "org.apache.skywalking.apm.plugin.dubbo.patch.MakeWrapperInterceptor";
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override protected ClassMatch enhanceClass() {
|
||||
return byName("org.apache.dubbo.common.bytecode.Wrapper");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# 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.
|
||||
|
||||
dubbo=org.apache.skywalking.apm.plugin.asf.dubbo.patch.WrapperInstrumentation
|
||||
|
|
@ -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.
|
||||
~
|
||||
-->
|
||||
|
||||
<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>6.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-dubbo-2.7.x-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>dubbo-2.7.x-plugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<dubbo.version>2.7.0</dubbo.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo</artifactId>
|
||||
<version>${dubbo.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.asf.dubbo;
|
||||
|
||||
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 DubboInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
private static final String ENHANCE_CLASS = "org.apache.dubbo.monitor.support.MonitorFilter";
|
||||
|
||||
private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.asf.dubbo.DubboInterceptor";
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return NameMatch.byName(ENHANCE_CLASS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named("invoke");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return INTERCEPT_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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.asf.dubbo;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import java.lang.reflect.Method;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
|
||||
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
|
||||
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
|
||||
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.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.network.trace.component.ComponentsDefine;
|
||||
|
||||
/**
|
||||
* {@link DubboInterceptor} define how to enhance class {@link org.apache.dubbo.monitor.support.MonitorFilter#invoke(Invoker,
|
||||
* Invocation)}. the trace context transport to the provider side by {@link RpcContext#attachments}.but all the version
|
||||
* of dubbo framework below 2.8.3 don't support {@link RpcContext#attachments}, we support another way to support it.
|
||||
*
|
||||
*/
|
||||
public class DubboInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
/**
|
||||
* <h2>Consumer:</h2> The serialized trace context data will
|
||||
* inject to the {@link RpcContext#attachments} for transport to provider side.
|
||||
* <p>
|
||||
* <h2>Provider:</h2> The serialized trace context data will extract from
|
||||
* {@link RpcContext#attachments}. current trace segment will ref if the serialize context data is not null.
|
||||
*/
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
|
||||
Invoker invoker = (Invoker)allArguments[0];
|
||||
Invocation invocation = (Invocation)allArguments[1];
|
||||
RpcContext rpcContext = RpcContext.getContext();
|
||||
boolean isConsumer = rpcContext.isConsumerSide();
|
||||
URL requestURL = invoker.getUrl();
|
||||
|
||||
AbstractSpan span;
|
||||
|
||||
final String host = requestURL.getHost();
|
||||
final int port = requestURL.getPort();
|
||||
if (isConsumer) {
|
||||
final ContextCarrier contextCarrier = new ContextCarrier();
|
||||
span = ContextManager.createExitSpan(generateOperationName(requestURL, invocation), contextCarrier, host + ":" + port);
|
||||
//invocation.getAttachments().put("contextData", contextDataStr);
|
||||
//@see https://github.com/alibaba/dubbo/blob/dubbo-2.5.3/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java#L154-L161
|
||||
CarrierItem next = contextCarrier.items();
|
||||
while (next.hasNext()) {
|
||||
next = next.next();
|
||||
rpcContext.getAttachments().put(next.getHeadKey(), next.getHeadValue());
|
||||
}
|
||||
} else {
|
||||
ContextCarrier contextCarrier = new ContextCarrier();
|
||||
CarrierItem next = contextCarrier.items();
|
||||
while (next.hasNext()) {
|
||||
next = next.next();
|
||||
next.setHeadValue(rpcContext.getAttachment(next.getHeadKey()));
|
||||
}
|
||||
|
||||
span = ContextManager.createEntrySpan(generateOperationName(requestURL, invocation), contextCarrier);
|
||||
}
|
||||
|
||||
Tags.URL.set(span, generateRequestURL(requestURL, invocation));
|
||||
span.setComponent(ComponentsDefine.DUBBO);
|
||||
SpanLayer.asRPCFramework(span);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Object ret) throws Throwable {
|
||||
Result result = (Result)ret;
|
||||
if (result != null && result.getException() != null) {
|
||||
dealException(result.getException());
|
||||
}
|
||||
|
||||
ContextManager.stopSpan();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
dealException(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the throwable, which occurs in Dubbo RPC service.
|
||||
*/
|
||||
private void dealException(Throwable throwable) {
|
||||
AbstractSpan span = ContextManager.activeSpan();
|
||||
span.errorOccurred();
|
||||
span.log(throwable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format operation name. e.g. org.apache.skywalking.apm.plugin.test.Test.test(String)
|
||||
*
|
||||
* @return operation name.
|
||||
*/
|
||||
private String generateOperationName(URL requestURL, Invocation invocation) {
|
||||
StringBuilder operationName = new StringBuilder();
|
||||
operationName.append(requestURL.getPath());
|
||||
operationName.append("." + invocation.getMethodName() + "(");
|
||||
for (Class<?> classes : invocation.getParameterTypes()) {
|
||||
operationName.append(classes.getSimpleName() + ",");
|
||||
}
|
||||
|
||||
if (invocation.getParameterTypes().length > 0) {
|
||||
operationName.delete(operationName.length() - 1, operationName.length());
|
||||
}
|
||||
|
||||
operationName.append(")");
|
||||
|
||||
return operationName.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format request url.
|
||||
* e.g. dubbo://127.0.0.1:20880/org.apache.skywalking.apm.plugin.test.Test.test(String).
|
||||
*
|
||||
* @return request url.
|
||||
*/
|
||||
private String generateRequestURL(URL url, Invocation invocation) {
|
||||
StringBuilder requestURL = new StringBuilder();
|
||||
requestURL.append(url.getProtocol() + "://");
|
||||
requestURL.append(url.getHost());
|
||||
requestURL.append(":" + url.getPort() + "/");
|
||||
requestURL.append(generateOperationName(url, invocation));
|
||||
return requestURL.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# 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.
|
||||
|
||||
dubbo=org.apache.skywalking.apm.plugin.asf.dubbo.DubboInstrumentation
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.dubbo;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.OverrideImplementor;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextManagerExtendService;
|
||||
|
||||
/**
|
||||
* @author wusheng
|
||||
*/
|
||||
@OverrideImplementor(ContextManagerExtendService.class)
|
||||
public class ContextManagerExtendOverrideService extends ContextManagerExtendService {
|
||||
}
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* 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.dubbo;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import java.util.List;
|
||||
import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
|
||||
import org.apache.skywalking.apm.agent.core.conf.Config;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextManagerExtendService;
|
||||
import org.apache.skywalking.apm.agent.core.context.SW3CarrierItem;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
|
||||
import org.apache.skywalking.apm.agent.core.context.trace.LogDataEntity;
|
||||
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.context.trace.TraceSegmentRef;
|
||||
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.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
|
||||
import org.apache.skywalking.apm.agent.test.helper.SegmentRefHelper;
|
||||
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.apache.skywalking.apm.plugin.asf.dubbo.DubboInterceptor;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.powermock.api.mockito.PowerMockito.when;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PowerMockRunnerDelegate(TracingSegmentRunner.class)
|
||||
@PrepareForTest({RpcContext.class})
|
||||
public class DubboInterceptorTest {
|
||||
|
||||
@SegmentStoragePoint
|
||||
private SegmentStorage segmentStorage;
|
||||
|
||||
@Rule
|
||||
public AgentServiceRule agentServiceRule = new AgentServiceRule();
|
||||
|
||||
@Mock
|
||||
private EnhancedInstance enhancedInstance;
|
||||
|
||||
private DubboInterceptor dubboInterceptor;
|
||||
|
||||
@Mock
|
||||
private RpcContext rpcContext;
|
||||
@Mock
|
||||
private Invoker invoker;
|
||||
@Mock
|
||||
private Invocation invocation;
|
||||
@Mock
|
||||
private MethodInterceptResult methodInterceptResult;
|
||||
@Mock
|
||||
private Result result;
|
||||
|
||||
private Object[] allArguments;
|
||||
private Class[] argumentTypes;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Config.Agent.ACTIVE_V1_HEADER = true;
|
||||
dubboInterceptor = new DubboInterceptor();
|
||||
|
||||
PowerMockito.mockStatic(RpcContext.class);
|
||||
|
||||
when(invoker.getUrl()).thenReturn(URL.valueOf("dubbo://127.0.0.1:20880/org.apache.skywalking.apm.test.TestDubboService"));
|
||||
when(invocation.getMethodName()).thenReturn("test");
|
||||
when(invocation.getParameterTypes()).thenReturn(new Class[] {String.class});
|
||||
when(invocation.getArguments()).thenReturn(new Object[] {"abc"});
|
||||
PowerMockito.when(RpcContext.getContext()).thenReturn(rpcContext);
|
||||
when(rpcContext.isConsumerSide()).thenReturn(true);
|
||||
allArguments = new Object[] {invoker, invocation};
|
||||
argumentTypes = new Class[] {invoker.getClass(), invocation.getClass()};
|
||||
Config.Agent.SERVICE_NAME = "DubboTestCases-APP";
|
||||
}
|
||||
|
||||
@After
|
||||
public void clear() {
|
||||
Config.Agent.ACTIVE_V1_HEADER = false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceFromPlugin() {
|
||||
PluginBootService service = ServiceManager.INSTANCE.findService(PluginBootService.class);
|
||||
|
||||
Assert.notNull(service);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceOverrideFromPlugin() {
|
||||
ContextManagerExtendService service = ServiceManager.INSTANCE.findService(ContextManagerExtendService.class);
|
||||
|
||||
Assert.isInstanceOf(ContextManagerExtendOverrideService.class, service);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumerWithAttachment() throws Throwable {
|
||||
dubboInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, methodInterceptResult);
|
||||
dubboInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, result);
|
||||
|
||||
assertThat(segmentStorage.getTraceSegments().size(), is(1));
|
||||
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
|
||||
List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
|
||||
assertThat(spans.size(), is(1));
|
||||
assertConsumerSpan(spans.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumerWithException() throws Throwable {
|
||||
dubboInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, methodInterceptResult);
|
||||
dubboInterceptor.handleMethodException(enhancedInstance, null, allArguments, argumentTypes, new RuntimeException());
|
||||
dubboInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, result);
|
||||
assertThat(segmentStorage.getTraceSegments().size(), is(1));
|
||||
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
|
||||
assertConsumerTraceSegmentInErrorCase(traceSegment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumerWithResultHasException() throws Throwable {
|
||||
when(result.getException()).thenReturn(new RuntimeException());
|
||||
|
||||
dubboInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, methodInterceptResult);
|
||||
dubboInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, result);
|
||||
|
||||
assertThat(segmentStorage.getTraceSegments().size(), is(1));
|
||||
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
|
||||
assertConsumerTraceSegmentInErrorCase(traceSegment);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProviderWithAttachment() throws Throwable {
|
||||
when(rpcContext.isConsumerSide()).thenReturn(false);
|
||||
when(rpcContext.getAttachment(SW3CarrierItem.HEADER_NAME)).thenReturn("1.323.4433|3|1|1|#192.168.1.8 :18002|#/portal/|#/testEntrySpan|#AQA*#AQA*Et0We0tQNQA*");
|
||||
|
||||
dubboInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentTypes, methodInterceptResult);
|
||||
dubboInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentTypes, result);
|
||||
assertProvider();
|
||||
}
|
||||
|
||||
private void assertConsumerTraceSegmentInErrorCase(
|
||||
TraceSegment traceSegment) {
|
||||
List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
|
||||
assertThat(spans.size(), is(1));
|
||||
assertConsumerSpan(spans.get(0));
|
||||
AbstractTracingSpan span = spans.get(0);
|
||||
assertThat(SpanHelper.getLogs(span).size(), is(1));
|
||||
assertErrorLog(SpanHelper.getLogs(span).get(0));
|
||||
}
|
||||
|
||||
private void assertErrorLog(LogDataEntity logData) {
|
||||
assertThat(logData.getLogs().size(), is(4));
|
||||
assertThat(logData.getLogs().get(0).getValue(), CoreMatchers.<Object>is("error"));
|
||||
assertThat(logData.getLogs().get(1).getValue(), CoreMatchers.<Object>is(RuntimeException.class.getName()));
|
||||
assertNull(logData.getLogs().get(2).getValue());
|
||||
}
|
||||
|
||||
private void assertProvider() {
|
||||
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
|
||||
assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
|
||||
assertProviderSpan(SegmentHelper.getSpans(traceSegment).get(0));
|
||||
assertTraceSegmentRef(traceSegment.getRefs().get(0));
|
||||
}
|
||||
|
||||
private void assertTraceSegmentRef(TraceSegmentRef actual) {
|
||||
assertThat(SegmentRefHelper.getSpanId(actual), is(3));
|
||||
assertThat(SegmentRefHelper.getEntryServiceInstanceId(actual), is(1));
|
||||
assertThat(SegmentRefHelper.getTraceSegmentId(actual).toString(), is("1.323.4433"));
|
||||
}
|
||||
|
||||
private void assertProviderSpan(AbstractTracingSpan span) {
|
||||
assertCommonsAttribute(span);
|
||||
assertTrue(span.isEntry());
|
||||
}
|
||||
|
||||
private void assertConsumerSpan(AbstractTracingSpan span) {
|
||||
assertCommonsAttribute(span);
|
||||
assertTrue(span.isExit());
|
||||
}
|
||||
|
||||
private void assertCommonsAttribute(AbstractTracingSpan span) {
|
||||
List<TagValuePair> tags = SpanHelper.getTags(span);
|
||||
assertThat(tags.size(), is(1));
|
||||
assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.RPC_FRAMEWORK));
|
||||
assertThat(SpanHelper.getComponentId(span), is(3));
|
||||
assertThat(tags.get(0).getValue(), is("dubbo://127.0.0.1:20880/org.apache.skywalking.apm.test.TestDubboService.test(String)"));
|
||||
assertThat(span.getOperationName(), is("org.apache.skywalking.apm.test.TestDubboService.test(String)"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.dubbo;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.boot.BootService;
|
||||
|
||||
/**
|
||||
* @author wusheng
|
||||
*/
|
||||
public class PluginBootService implements BootService {
|
||||
@Override public void prepare() throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override public void boot() throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onComplete() throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override public void shutdown() throws Throwable {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
#
|
||||
#
|
||||
|
||||
org.apache.skywalking.apm.plugin.dubbo.PluginBootService
|
||||
org.apache.skywalking.apm.plugin.dubbo.ContextManagerExtendOverrideService
|
||||
|
|
@ -67,6 +67,8 @@
|
|||
<module>rabbitmq-5.x-plugin</module>
|
||||
<module>dubbo-conflict-patch</module>
|
||||
<module>canal-1.x-plugin</module>
|
||||
<module>dubbo-2.7.x-plugin</module>
|
||||
<module>dubbo-2.7.x-conflict-patch</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue