SkyWalking自定义链路跟踪(@Trace和apm-customize-enhance-plugin介绍)

场景 在开发过程了,我们除了想知道链路的整体耗时以外,有的时候也想要知道某些方法的执行耗时。为了达到这个目的,我们需要做一些额外的配置。 今天就给大家介绍SkyWalking方法级trace的实现。 实现 SkyWalking方法级trace的实现具体分为侵入式和外部配置两种方式,各有优劣,可根据项目情况自行选择。首选给大家介绍侵入式实现方式。 一、侵入式实现 1、pom.xml依赖
  org.apache.skywalking apm-toolkit-trace ${skywalking.version}  
${skywalking.version} 和你当前使用的SkyWalking版本保持一致。 Methods annotated with @Tag will try to tag the current active span with the given key (Tag#key()) and (Tag#value()), if there is no active span at all, this annotation takes no effect. 根据官方文档的介绍,我们了解到可以使用@Tag注解实现方法级trace,@tag同时也包括key()和value()两个参数。同时必须保证方法在一个激活的span中,否则注解将不会起作用。 了解到基础用法以后,我们再接着往下看。下面的代码块中官方提供了基础的注解用例。
/** * The codes below will generate a span, * and two types of tags, one type tag: keys are `tag1` and `tag2`, values are the passed-in parameters, respectively, the other type tag: keys are `username` and `age`, values are the return value in User, respectively */ @Trace @Tag(key = "tag1", value = "arg[0]") @Tag(key = "tag2", value = "arg[1]") @Tag(key = "username", value = "returnedObj.username") @Tag(key = "age", value = "returnedObj.age") public User methodYouWantToTrace(String param1, String param2) { // ActiveSpan.setOperationName("Customize your own operation name, if this is an entry span, this would be an endpoint name"); // ... }
如上图所示,在指定的方法上标注上@trace标记,表明这是一个方法级trace。如果,通过配置@Tag,额外获取我们想要收集的数据。除了入参以外,还能获取到具体的返回值参数。 基础用法也了解完了,下面就开始我们的实践。 2、注解配置 先在项目中引入依赖,然后再对应的方法上新增上注解。这里我们通过@Tag获取了name,address,token以及traceId参数。
@Trace @Tags({@Tag(key = "name",value = "arg[0]"), @Tag(key = "token",value = "returnedObj.token"), @Tag(key = "address",value = "arg[1]"), @Tag(key = "traceId",value = "returnedObj.traceId")}) public User doSkyWalkingPluginsV2(String name, String address, int id){ CachaUser cachaUser = new CachaUser(); cachaUser.setName(name); cachaUser.setAddress(address); cachaUser.setId(id); String token = TokenUtils.getToken(cachaUser); User user = new User(); user.setAge("18"); user.setName(name); user.setToken(token); user.setTraceId(TraceContext.traceId()); return user; }
配置完成后,启动服务。通过postman远程调用服务,在skywalking服务页面可以看到,我们trace的doSkyWalkingPluginsV2方法也被收集到了,方法耗时也能一目了然。 SkyWalking自定义链路跟踪(@Trace和apm-customize-enhance-plugin介绍) 点击方法查看详情,name,address,token以及traceId参数也都全部被统计收集上来了。 SkyWalking自定义链路跟踪(@Trace和apm-customize-enhance-plugin介绍) 去掉@Trace再试一次,这次只显示了接口链路,没有显示方法级别的trace粒度。 二、非侵入式实现 上面介绍了侵入式实现,侵入式实现需要我们引入pom.xml依赖,同时还需要对指定的方法配置注解。在某些场景下,我们对于监控的项目不方便修改,甚至无法修改的情况下,这个时候就要选择非侵入式方式来实现方法级的trace粒度追踪。 apm-customize-enhance-plugin插件作用:自定义增强任意类里的任意方法,从而实现对任意类里任意方法的监控。 1、移动apm-customize-enhance-plugin.jar 首先,找到skywalking的安装目录${path}\skywalking,${path}对于具体的文件目录 SkyWalking自定义链路跟踪(@Trace和apm-customize-enhance-plugin介绍) 打开\apache-skywalking-apm-bin\agent目录,\optional-plugins\apm-customize-enhance-plugin.jar 移动到\plugin/apm-customize-enhance-plugin.jar 2、编写增强规则 举例,有个业务方法如下:
public class TestService1 { public static void staticMethod(String str0, int count, Map m, List l, Object[] os) { // 业务逻辑 } ... }
针对如上方法,新建 customize_enhance.xml,xml的内容就需要如下配置,这里我们额外配置了name和address属性
        arg[0] arg[1] arg[3].[0] arg[2].['k1'] arg[4].[1] arg[4].[2]      
规则说明: SkyWalking自定义链路跟踪(@Trace和apm-customize-enhance-plugin介绍) 特别需要注意的是method的写法: 基本类型: 基本类型.class ,例如: int.class 非基本类型: 类的完全限定名称 ,例如:java.lang.String 数组:可以写个数组打印一下,就知道格式了,例如:
public static void main(String[] args) { String[] s = new String[]{}; System.out.println(s);   int [] x = new int []{}; System.out.println(x); }
  结果:
[Ljava.lang.String;@1b0375b3 [I@2f7c7260
因此,对于String类型的数组,就可以写成 [Ljava.lang.String;;对于int类型的数组,则写成 [I。 3、配置agent.config中添加配置: 修改\config\agent.config文件,新增plugin.customize.enhance_file=${path}:\customize_enhance.xml,${path}对于具体的文件目录 配置完成后,重新启动SkyWalking,重启服务。通过postman远程调用服务,在skywalking服务页面可以看到,我们trace的doSkyWalkingPlugins方法也被收集到了,方法耗时也能一目了然。 SkyWalking自定义链路跟踪(@Trace和apm-customize-enhance-plugin介绍) 点击方法查看详情,name,address参数也都全部被统计收集上来了。 SkyWalking自定义链路跟踪(@Trace和apm-customize-enhance-plugin介绍) 至此,两种方式实现方法级trace粒度的实现就全部介绍完了。   三、底层实现 @Trace为什么可以自定义监控指定方法 org.skywalking.apm.toolkit.activation.trace.TraceAnnotationActivation 类里: SkyWalking自定义链路跟踪(@Trace和apm-customize-enhance-plugin介绍) 使用TraceAnnotationMethodInterceptor 拦截器
/** * {@link TraceAnnotationMethodInterceptor} create a local span and set the operation name which fetch from * org.apache.skywalking.apm.toolkit.trace.annotation.Trace.operationName. if the fetch value is blank string, and * the operation name will be the method name. * * @author zhangxin */ public class TraceAnnotationMethodInterceptor implements InstanceMethodsAroundInterceptor {   @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { Trace trace = method.getAnnotation(Trace.class); //trace String operationName = trace.operationName(); if (operationName.length() == 0) { operationName = generateOperationName(method); }   ContextManager.createLocalSpan(operationName); // 创建LocalSpan }     private String generateOperationName(Method method) { StringBuilder operationName = new StringBuilder(method.getDeclaringClass().getName() + "." + method.getName() + "("); Class[] parameterTypes = method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { operationName.append(parameterTypes[i].getName()); if (i < (parameterTypes.length - 1)) { operationName.append(","); } } operationName.append(")"); return operationName.toString(); }   @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { ContextManager.stopSpan(); return ret; }   @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } }
参考: https://blog.csdn.net/zxh1991811/article/details/115379470 https://jiandansuifeng.blog.csdn.net/article/details/107149565?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link
上一篇:EntityFramework.Extended扩展用法


下一篇:Laravel Eloquent 数据查询结果中日期的格式化