skywalking05 - skywalking探针插件开发

本文涉及的产品
应用实时监控服务-应用监控,每月50GB免费额度
应用实时监控服务-用户体验监控,每月100OCU免费额度
简介: skywalking05 - skywalking探针插件开发

skywalking05 - skywalking探针插件开发

探针与toolkit注解的区别

在上一章,我们通过了@Trace, @Tags, @Tag注解,对我们的方法进行了链路追踪. 但是它有这样三点不好:

  1. 代码侵入, 直接写在了我们业务系统的代码里,但是它本身和业务一点都不相关.
  2. 不可复用, 注解都加在具体的方法上,我们无法移植到其他工程中,完成链路追踪.
  3. 限制性大, 只能注解在我们自己写的代码中,不能对其他三方包中的方法进行追踪.

而探针则在这三个问题上,得到了解决.我们接下来的demo,将会以Base64.encodeToString()进行展示.

探针的基本概念

  • Span : 可以理解为一次方法调用\数据库查询\一次RPC访问
  • Trace Segment : 属于Skywalking特有的概念. 在支持多线程的语言中,一个线程中所有的操作归属于一个Span的聚合,这些Span具有同一个SegmentId.
  • ContextCarrier : 跨进程调用链的链接.
  • ContextSnapshot: 跨线程的调用链的链接.

核心对象

插件开发基本绕不过去的类,具体解释暂时懒得打了,建议直接看书的第十章,闲了后补

  1. org.apache.skywalking.apm.agent.core.context.ContextCarrier
  2. org.apache.skywalking.apm.agent.core.context.ContextManager
  3. org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan
  4. org.apache.skywalking.apm.agent.core.context.tag.Tags
  5. org.apache.skywalking.apm.agent.core.context.AsyncSpan

工程结构

插件开发三要素

  • *Instrumentation 定义拦截的方式:
  1. 匹配类名 enhanceClass()
  2. 匹配构造方法 getConstructorsInterceptPoints()
  3. 匹配方法 getInstanceMethodsInterceptPoints()
/**
 * #3,告诉skywalking拦截哪些方法,并指定拦截器
 * ClassEnhancePluginDefine 父类
 * ClassInstanceMethodsEnhancePluginDefine 实例方法
 * ClassStaticMethodsEnhancePluginDefine 静态方法
 */
public class Base64Instrumentation extends ClassInstanceMethodsEnhancePluginDefine {
    private static final String ENHANCE_CLASS = "org.apache.commons.codec.binary.Base64";
    private static final String INTERCEPT_CLASS = "org.dfg.demo.sk.plugin.foo.Base64EncodeInterceptor";
    @Override
    protected ClassMatch enhanceClass() {
        return NameMatch.byName(ENHANCE_CLASS);
    }
    /**
     * 拦截构造器
     *
     * @return
     */
    @Override
    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
        return null;
    }
    /**
     * 拦截方法
     * InstanceMethodsAroundInterceptor 实例方法
     * InstanceConstructorInterceptor 构造方法
     * StaticMethodsAroundInterceptor 静态方法
     *
     * @return
     */
    @Override
    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
        //拦截实例方法
        return new InstanceMethodsInterceptPoint[]{
                new InstanceMethodsInterceptPoint() {
                    @Override
                    public ElementMatcher<MethodDescription> getMethodsMatcher() {
                        //拦截方法,支持多种匹配规则
                        return named("encodeToString")
//                                .and(takesArguments(1))
//                                .and(takesArguments(byte[].class))
                                ;
                    }
                    @Override
                    public String getMethodsInterceptor() {
                        return INTERCEPT_CLASS;
                    }
                    @Override
                    public boolean isOverrideArgs() {
                        return false;
                    }
                }
        };
    }
}
  • *Interceptor 定义拦截器实际方法
  1. 方法执行前 beforeMethod()
  2. 方法执行后 afterMethod()
  3. 方法发生异常 handleMethodException()
/**
 * #4,skywalking拦截到指定方法后回调
 * 在这里面获取调用情况如方法、参数等,并记录span
 */
public class Base64EncodeInterceptor implements InstanceMethodsAroundInterceptor {
    public static final OfficialComponent BASE64 = new OfficialComponent(301, "BASE64");
    @Override
    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                             MethodInterceptResult result) throws Throwable {
        //创建span
        AbstractSpan span = ContextManager.createLocalSpan("base64.encode");
        //设置组件类型
        span.setComponent(BASE64);
        //获取参数
        byte[] param = (byte[]) allArguments[0];
        //记录span tag
        new StringTag("source").set(span, Arrays.toString(param));
        //记录span
        SpanLayer.asHttp(span);
    }
    @Override
    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
                              Object ret) throws Throwable {
        if (ret != null) {
            AbstractSpan span = ContextManager.activeSpan();
            //span.errorOccurred();
            new StringTag("result").set(span, String.valueOf(ret));
        }
        //结束span
        ContextManager.stopSpan();
        return ret;
    }
    @Override
    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
                                      Class<?>[] argumentsTypes, Throwable t) {
        AbstractSpan abstractSpan = ContextManager.activeSpan();
        abstractSpan.log(t);
    }
}

工程仍位于同一个demo中,skywalking-plugin-example

  • *.def 插件说明文件,告诉探针,插件类型\插件定义的类的全类名
foo-plugin=org.dfg.demo.sk.plugin.foo.define.Base64Instrumentation

插件打包

可以替换bytebuddy包路径,在pom.xml的节点下,非必须,只是demo中将打出来的jar包会传输到agent包中的plugin目录中

<plugin>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
        中                </goals>
                        <configuration>
                            <shadedArtifactAttached>false</shadedArtifactAttached>
                            <createDependencyReducedPom>false</createDependencyReducedPom>
                            <createSourcesJar>false</createSourcesJar>
                            <shadeSourcesContent>true</shadeSourcesContent>
                            <relocations>
                                <relocation>
                                    <pattern>${shade.net.bytebuddy.source}</pattern>
                                    <shadedPattern>${shade.net.bytebuddy.target}</shadedPattern>
                                </relocation>
                            </relocations>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

插件复制

如果替换了bytebuddy包路径,则无需手动复制.替换结果:

wanglh@dark:~/IdeaProjects/skywalking-plugin-example/apache-skywalking-apm-bin-es7/agent/plugins$ ls -al
总用量 2616
drwxr-xr-x 2 wanglh wanglh 12288 2月   5 20:58 .
drwxr-xr-x 9 wanglh wanglh  4096 2月   4 21:51 ..
-rw-r--r-- 1 wanglh wanglh 21274 2月   4 17:11 apm-activemq-5.x-plugin-8.3.0.jar
-rw-r--r-- 1 wanglh wanglh 13197 2月   4 17:11 apm-dubbo-plugin-8.3.0.jar
-rw-r--r-- 1 wanglh wanglh 28217 2月   4 17:11 apm-ehcache-2.x-plugin-8.3.0.jar
-rw-r--r-- 1 wanglh wanglh  6999 2月   5 20:58 skywalking-plugin-foo-1.0-SNAPSHOT.jar
wanglh@dark:~/IdeaProjects/skywalking-plugin-example/apache-skywalking-apm-bin-es7/agent/plugins$ ls -al *foo*
-rw-r--r-- 1 wanglh wanglh 6999 2月   5 20:58 skywalking-plugin-foo-1.0-SNAPSHOT.jar
wanglh@dark:~/IdeaProjects/skywalking-plugin-example/apache-skywalking-apm-bin-es7/agent/plugins$

可以观察到foo插件包的时间戳是最新的

运行查看结果

运行工程

与上一章相同的启动方式

访问URL

方式不变,仍为:

curl http://localhost:8081/foo?p=a

查看链路

已经可以看到新增的encode方法的链路

查看Tag

// 入口
    //记录span tag
        new StringTag("source").set(span, Arrays.toString(param));
        //记录span
        SpanLayer.asHttp(span);
    // 出口
        if (ret != null) {
            AbstractSpan span = ContextManager.activeSpan();
            //span.errorOccurred();
            new StringTag("result").set(span, String.valueOf(ret));
        }
        //结束span
        ContextManager.stopSpan();

以上是demo工程中,对该Span添加的Tag.

实际图也可以观察到生效了:

相关实践学习
通过云拨测对指定服务器进行Ping/DNS监测
本实验将通过云拨测对指定服务器进行Ping/DNS监测,评估网站服务质量和用户体验。
目录
相关文章
|
SQL Java Apache
skywalking 搭建(apache-skywalking-apm-es7-7.0.0)
skywalking 搭建(apache-skywalking-apm-es7-7.0.0)
617 0
|
4月前
|
存储 监控 Java
Zipkin/Pinpoint/SkyWalking全面对比
【11月更文挑战第1天】这里重点从探针的性能、Collector的可扩展性、调用链路分析、完整的应用拓扑、对于科技人员使用友好程度(部署安装、埋点接入、使用管理)几个方面来进行对比。
|
前端开发 Java 开发工具
skywalking07 - skywalking如何收集Controller的链路
skywalking07 - skywalking如何收集Controller的链路
151 1
|
存储 监控 前端开发
SpringCloudAliBaba篇之SkyWalking:轻松实现应用性能监控
SpringCloudAliBaba篇之SkyWalking:轻松实现应用性能监控
2062 0
|
关系型数据库 MySQL 数据库
skywalking02 - skywalking安装
skywalking02 - skywalking安装
190 0
|
Java Windows
skywalking03 - skywalking入门使用
skywalking03 - skywalking入门使用
166 0
|
存储 JavaScript Cloud Native
skywalking01 - skywalking介绍
skywalking01 - skywalking介绍
157 0
|
监控 前端开发 数据可视化
Skywalking的安装与使用
Skywalking的安装与使用
700 0
Skywalking的安装与使用
|
SQL 监控 Java
Skywalking的不足
Skywalking的不足 全链路压测监控工具
639 0
|
存储 数据采集 Ubuntu
Skywalking实战
Skywalking实战
705 0