6

pinpoint插件开发之一:牛刀小试,调整gson插件

 1 year ago
source link: https://blog.51cto.com/zq2599/5260619
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

pinpoint插件开发之一:牛刀小试,调整gson插件

原创

程序员欣宸 2022-04-29 07:19:55 博主文章分类:Java技能 ©著作权

文章标签 json java pinpoint 文章分类 Java 编程语言 阅读数1135

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码): https://github.com/zq2599/blog_demos

  • 从本章开始我们一起来实战pinpoint插件开发,做一些实用的pinpoint插件,本着先易后难的原则,我们从修改现有插件开始吧;
  1. 本次实战的操作环境是win10专业版,安装了Docker Community Edition Version 17.09.0-ce-win33(13620);
  2. 编译环境,请参照 《Docker下,极速体验编译pinpoint1.6.x分支》,我们会用这个容器编译构建修改过的插件,为了复制文件方便,我们启动容器使用以下命令:
docker run --name=ppcompile001 -p 19003:22 -idt -v c:/share:/usr/Downloads bolingcavalry/jdk7-mvn339-pinpoint16x-compile:0.0.1
  • 参数**-v c:/share:/usr/Downloads表示将当前电脑的c:/share目录和容器的/usr/Downloads**目录建立映射,这样我们就能把容器里的文件复制出来了(记得先在c盘根目录下创建share目录);
  1. pinpoint的运行环境,请参照 《Docker下,极速体验pinpoint1.6.3》,启动了三个容器,一个是pinpoint的web server,还有两个是运行着web应用的tomcat,运行环境运行成功后,我们可以在pinpoint的web server上看到web应用的服务调用链,为了复制文件方便,我们将docker-compose.yml文件中的每个容器也加上目录映射参数,整个docker-compose.yml内容如下:
version: '2'
services:
  pinpoint-server: 
    image: bolingcavalry/centos67-hbase126-pinpoint163-server:0.0.1
    container_name: pinpoint-server
    ports:
      - "19001:22"
      - "28080:28080"
    volumes:
      - c:/share:/usr/Downloads
    restart: always
  tomcat001: 
    image: bolingcavalry/centos67-pinpoint163-agent:0.0.1
    container_name: tomcat001
    links: 
      - pinpoint-server:pinpointhost
    ports:
      - "8081:8080"
    environment:
      TOMCAT_SERVER_ID: tomcat001
      PINPOINT_AGENT_ID: ppagent20171105001 
      PINPOINT_APPLICATION_NAME: app20171105001
    volumes:
      - c:/share:/usr/Downloads
    restart: always 
  tomcat002: 
    image: bolingcavalry/centos67-pinpoint163-agent:0.0.1
    container_name: tomcat002
    depends_on:
      - tomcat001
    links: 
      - pinpoint-server:pinpointhost
    ports:
      - "8082:8080"
    environment:
      TOMCAT_SERVER_ID: tomcat002
      PINPOINT_AGENT_ID: ppagent20171105002 
      PINPOINT_APPLICATION_NAME: app20171105002
    volumes:
      - c:/share:/usr/Downloads
    restart: always 
  • 可以看到每个容器的配置中都有volumes参数,对容器和当前电脑的目录做了映射;

pinpoint对Gson类的监控

public String tracegson(HttpServletRequest request, Model model) {
        String name = get(request, "name");
        String age = get(request, "age");

        Student student = new Student();
        student.setName(name);
        student.setAge(Integer.valueOf(age));

        Gson gson = new Gson();

        String parseStr = gson.toJson(student, Student.class);

        logger.info("gson str [{}]", parseStr);

        return String.format("gson str : %s [%s]", parseStr, tag());
    }
  • 上面的代码中用到了Gson类的toJson方法,由于pinpoint1.6.3是带有Gson插件的,所以执行此方法后在pinpoint的调用链跟踪列表中可以看到对toJson方法的调用,如下图,至于如何部署和执行这段代码,请参照 《Docker下,极速体验pinpoint1.6.3》
    pinpoint插件开发之一:牛刀小试,调整gson插件_java

  • 上图底部的红框中是对Gson的toJson方法的监控,可以看到这个节点已经不能展开了,难道gson插件不输出一些参数么?是本来就没有参数?还是参数没有显示?

  • 去pinpoint的github上看看,地址: https://github.com/naver/pinpoint;
    切到1.6.x分支,在plugin目录下可以看见gson插件的工程,如下图红框所示:
    pinpoint插件开发之一:牛刀小试,调整gson插件_json_02

  • 先看看实现这个插件拦截了Gson的toJson方法后做了什么,做的事情都封装在ToJsonInterceptor.java中:

@Override
    public void before(Object target) {
        if (logger.isDebugEnabled()) {
            logger.beforeInterceptor(target, null);
        }

        final Trace trace = traceContext.currentTraceObject();
        if (trace == null) {
            return;
        }

        trace.traceBlockBegin();
    }
  • 上面的代码是Gson的toJson方法执行前做的事情:开启了一次追踪,我们再来看看Gson的toJson方法执行结束后做了什么:
 @Override
    public void after(Object target, Object result, Throwable throwable) {
        if (logger.isDebugEnabled()) {
            logger.afterInterceptor(target, null, result, throwable);
        }

        final Trace trace = traceContext.currentTraceObject();
        if (trace == null) {
            return;
        }

        try {
            SpanEventRecorder recorder = trace.currentSpanEventRecorder();
            recorder.recordServiceType(GsonPlugin.GSON_SERVICE_TYPE);
            recorder.recordApi(descriptor);
            recorder.recordException(throwable);

            if (result != null && result instanceof String) {
                recorder.recordAttribute(GsonPlugin.GSON_ANNOTATION_KEY_JSON_LENGTH, ((String) result).length());
            }
        } finally {
            trace.traceBlockEnd();
        }
    }
  • 注意这一句代码:
recorder.recordAttribute(GsonPlugin.GSON_ANNOTATION_KEY_JSON_LENGTH, ((String) result).length());
  • 这表示toJson方法的返回值如果非空并且是String对象的时候,pinpoint会记录一个参数GsonPlugin.GSON_ANNOTATION_KEY_JSON_LENGTH,这个参数的值是toJson方法返回的字符串的长度;

  • 已经记录了参数,但在pinpoint页面上却没有展示出来,我们去看看这个参数的定义吧:

public static final AnnotationKey GSON_ANNOTATION_KEY_JSON_LENGTH = AnnotationKeyFactory.of(9000, "gson.json.length");
  • GSON_ANNOTATION_KEY_JSON_LENGTH 是通过AnnotationKeyFactory.of方法创建的,我们跟踪这个方法,最终进入DefaultAnnotationKey的构造方法:
DefaultAnnotationKey(int code, String name, AnnotationKeyProperty... properties) {
        this.code = code;
        this.name = name;

        boolean viewInRecordSet = false;
        boolean errorApiMetadata = false;

        for (AnnotationKeyProperty property : properties) {
            switch (property) {
            case VIEW_IN_RECORD_SET:
                viewInRecordSet = true;
                break;
            case ERROR_API_METADATA:
                errorApiMetadata = true;
                break;
            }
        }

        this.viewInRecordSet = viewInRecordSet;
        this.errorApiMetadata = errorApiMetadata;
    }
  • 上述代码表示,如果我们不传入VIEW_IN_RECORD_SET,那么viewInRecordSet就一直为false,这就是导致gson.json.length参数在pinpoint中不显示的原因,要想让gson.json.length显示出来,只要在AnnotationKeyFactory.of方法的入参中加入VIEW_IN_RECORD_SET即可,接下来我们开始动手修改吧;

在编译环境修改源码

  • 在命令行执行以下命令登录到编译环境的容器中:
docker exec -it ppcompile001 /bin/bash
  • 修改这个文件:
/usr/local/work/pinpoint-1.6.x/plugins/gson/src/main/java/com/navercorp/pinpoint/plugin/gson/GsonPlugin.java
  • 找到下面这行代码:
public static final AnnotationKey GSON_ANNOTATION_KEY_JSON_LENGTH = AnnotationKeyFactory.of(9000, "gson.json.length");
  • 改成下面这样,AnnotationKeyFactory.of方法的入参从两个变成三个了:
public static final AnnotationKey GSON_ANNOTATION_KEY_JSON_LENGTH = AnnotationKeyFactory.of(9000, "gson.json.length", com.navercorp.pinpoint.common.trace.AnnotationKeyProperty.VIEW_IN_RECORD_SET);
  • 修改完毕后保存文件,进入pinpoint工程目录/usr/local/work/pinpoint-1.6.x,执行以下命令开始编译:
mvn install -Dmaven.test.skip=true -e
  • 编译完成后进入以下目录:
/usr/local/work/pinpoint-1.6.x/plugins/gson/target
  • 可以见到最新构建的gson插件,如下图黄框所示:

pinpoint插件开发之一:牛刀小试,调整gson插件_java_03

  • 把这个文件复制到**/usr/Downloads目录,由于pinpoint运行环境的三个容器也建立了自己的/usr/Downloadsc:/share**目录的映射,所以它们也能立即访问这个文件了;

替换pinpoint server的gson插件

  • 执行命令docker exec -it pinpoint-server /bin/bash进入pinpoint server容器;
  • 执行以下命令替换原有的gson插件:
rm -f /usr/local/work/tomcat-collector/apache-tomcat-8.0.36/webapps/ROOT/WEB-INF/lib/pinpoint-gson-plugin-1.6.3-SNAPSHOT.jar

cp /usr/Downloads/pinpoint-gson-plugin-1.6.3-SNAPSHOT.jar /usr/local/work/tomcat-collector/apache-tomcat-8.0.36/webapps/ROOT/WEB-INF/lib/

rm -f /usr/local/work/tomcat-web/apache-tomcat-8.0.36/webapps/ROOT/WEB-INF/lib/pinpoint-gson-plugin-1.6.3-SNAPSHOT.jar

cp /usr/Downloads/pinpoint-gson-plugin-1.6.3-SNAPSHOT.jar /usr/local/work/tomcat-web/apache-tomcat-8.0.36/webapps/ROOT/WEB-INF/lib/
  • 以上命令将pinpoint-collector和pinpoint-web两个容器的gson插件先删除,再把我们放在c:/share目录下最新的gson插件复制过去;
  • 重启collector和web两个应用,执行以下命令:
/usr/local/work/tomcat-collector/apache-tomcat-8.0.36/bin/shutdown.sh
/usr/local/work/tomcat-web/apache-tomcat-8.0.36/bin/shutdown.sh
/usr/local/work/tomcat-collector/apache-tomcat-8.0.36/bin/startup.sh
/usr/local/work/tomcat-web/apache-tomcat-8.0.36/bin/startup.sh

替换tomcat001容器的gson插件

  • 执行命令docker exec -it tomcat001 /bin/bash进入tomcat001容器;
  • 执行以下命令替换原有的gson插件:
rm -f /usr/local/work/pinpoint-agent-1.6.3/plugin/pinpoint-gson-plugin-1.6.3-SNAPSHOT.jar
cp /usr/Downloads/pinpoint-gson-plugin-1.6.3-SNAPSHOT.jar /usr/local/work/pinpoint-agent-1.6.3/plugin/
  • 以上命令将pinpoint agent目录下的gson插件先删除,再把我们放在c:/share目录下最新的gson插件复制过去;
  • 重启,由于tomcat是随着容器一起启动的,此处如果用shutdown.sh命令停止tomcat服务会导致容器退出,所以我们直接重启tomcat001容器吧;
  • 执行exit退出容器;
  • 在当前电脑的命令行执行docker restart tomcat001重启容器;

验证新的插件

至此,我们的第一次插件开发实战就结束了,小结本次插件开发过程:

  1. 修改插件源码;
  2. 编译构建成新的包;
  3. 新包替换pingpoint server上的collector和web应用中的旧包;
  4. 重启pinpoint server上的collector和web server;
  5. 新包替换pinpoint agent上的旧包;
  6. 重启agent上的业务的web server;
  • 以上只是修改了原有插件,接下来的实战中,我们一起创建一个全新的插件,实现我们需要的功能;

欢迎关注51CTO博客:程序员欣宸

 学习路上,你不孤单,欣宸原创一路相伴…

  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK