讲透Pinpoint插件开发

什么是Pinpoint插件

Pinpoint插件是pinpoint-agent的组成部分,pinpoint-agent通过对JVM字节码的修改实现对代码动作的采集,而具体的采集过程就是通过pinpoint插件来完成的。

Pinpoint默认插件已有58个(1.8.3版本,见附录),根据插件名可以很快了解该插件针对采集的功能点。

插件会对具体某类技术的“关键代码”进行动作采集,如:jdk-http插件会切入到sun.net.www.protocol.http.HttpURLConnection的connect方法中,这些“关键代码”使得其它所有上层框架组件的行为调用都能被pinpoint采集到。

官方提供的插件使得java的大部分生态应用的行为都能通过简单部署后采集获得,但对于新技术的出现 、企业内部业务的数据、特殊业务需求等情况就需要有针对性的开发新插件来实现

Pinpoint插件结构:

讲透Pinpoint插件开发_第1张图片

Pinpoint 插件由TraceMetadataProvider和ProfilerPlugin的实现组成,前者的实现给agent、collector、web三组件提供ServiceType和AnnotationKey,而后者的实现用于给agent使用,主要用来修改目标类、记录跟踪数据等操作。

那么ServiceType和AnnotationKey的作用是什么呢?其实每个 Span 和 SpanEvent 都包含一个 ServiceType,这个ServiceType表示跟踪方法所属的库,以及跟踪它的Span和spanevent应该如何处理,而且ServiceType是非序列化传输的,为了尽量压缩 Agent 到 Collector 数据包的大小,ServiceType 被设计成不是以序列化字符串的形式发送的,而是以整形数字发送的 (code 字段),这就需要建立一个映射关系,将 code 转换成对应的 ServiceType 实例,这个映射机制就是由 TraceMetadataProvider 负责的

如果要编写一个将被公开共享的插件,就必须联系pinpoint团队来获得分配的ServiceType code(官方已使用的ServiceType code见附录)

因此开发非共享的插件,可使用以下范围code:
讲透Pinpoint插件开发_第2张图片
( 非公开code与组件对应范围表)

再来说说AnnotationKey,Annotation 是包含在 Span 和 SpanEvent 中的更详尽的数据,以键值对的形式存在,键就是AnnotationKey,值是基本类型,String或者byte[]

最后需要注意的是:ServiceType code和AnnotationKey code必须是全局惟一的

插件开发步骤

开发Pinpoint插件主要分为以下四步:

  1. 实现TraceMetadataProvider
  2. 实现ProfilerPlugin
  3. 将TraceMetadataProvider与ProfilerPlugin实现配置到META-INF\services中的并打包插件
  4. 部署插件

插件开发演示

下面以开发一个demo插件为例,演示pinpoint插件的开发过程:

第一步:基于pinpoint源码项目,在“plugins”子模块下新建插件子模块

1、 将pinpoint源码在本地项目中导入并调试通过

讲透Pinpoint插件开发_第3张图片

2、 在Plugins模块下点击右键,New->Module新增子模块:

讲透Pinpoint插件开发_第4张图片

选择Maven类型,进入下一步,输入插件ArtifactId,因为是demo演示,所以这里我们ArtifactId就叫:“pinpoint-demo-plugin”:

讲透Pinpoint插件开发_第5张图片

点击“下一步”->输入“Module_name”->点击“完成”:

讲透Pinpoint插件开发_第6张图片

第二步:编辑pom.xml,引入插件必要的依赖及配置

1、加入父工程依赖关系:


 com.navercorp.pinpoint
 pinpoint
 ../..
 1.8.3

2、加入属性设置,设置编译使用的JDK目录,及编译的版本,由于官方推荐使用的是JDK8因此使用JDK8目录,但编译的版本考虑兼容性等原因,采用1.6:


    1.6
    ${env.JAVA_8_HOME}
    java18

注意:pinpoint项目要成功跑起来,需要按官方要求配置“JAVA_6_HOME、JAVA_7_HOME、JAVA_8_HOME、JAVA_9_HOME”等环境变量

3、设置模块项目基本信息

 pinpoint-demo-plugin 
pinpoint-demo-plugin
jar

4、设置依赖管理:pinpoint-plugin-bom


    
        
            com.navercorp.pinpoint
            pinpoint-plugin-bom
            ${project.version}
            pom
            import
        
    

5、设置项目依赖,可根据情况加入私人插件所需求的第三方依赖,另外插件默认需要依赖pinpoint-bootstrap-core提供基础支持


    
        com.navercorp.pinpoint
        pinpoint-bootstrap-core
        provided
    
    ………

第三步:实现ProfilerPlugin接口和TraceMetadataProvider接口

1、实现ProfilerPlugin接口

该接口只有一个简单的setup方法,该方法有一个参数ProfilerPluginSetupContext,利用参数对象可以获得插件配置、增加应用类型发现器(ApplicationTypeDetector)。ApplicationTypeDetector接口是与TraceMetadataProvider接口配合使用的,TraceMetadataProvider负责定义新的应用类型(后面会说明),ApplicationTypeDetector负责定义告诉pinpoint怎么样通过应用的启动类察觉到当前当前应用的类型

在ProfilerPlugin实现逻辑中,我们除了实现ProfilerPlugin接口以外,还可以同时实现TransformTemplateAware接口,pinpoint会检测到该实现,并为你注入TransformTemplate,TransformTemplate是pinpoint在进行类加载时为开发者提供的JVM字节码增强处理的入口,具体操作是通过调用它的transform方法并实现TransformCallback回调逻辑,pinpoint提供了字节码增强处理时的一些工具类API方便做处理,同时在处理过程中引入了一个叫“拦截器(Interceptor)”的概念,结合工具类API来实现对字节码进行增强。故:TransformTemplate负责字节码增强的管控,Interceptor负责具体的字节码增强逻辑:

讲透Pinpoint插件开发_第7张图片

讲透Pinpoint插件开发_第8张图片

最后,我只还需要编写拦截器的具体处理逻辑,拦截器的实现通常通过实现AroundInterceptor接口完成,这是一种简单的实现方式,可以用来实现我们自己的处理逻辑,类似于Spring AOP机制。而做为pinpoint插件开发,大多情况下会与当前插件采集的应用调用相关,我们可以通过继承SpanEventSimpleAroundInterceptorForPlugin的方式来实现拦截器,该类为抽象类,实现了AroundInterceptor接口并加入了链路跟踪等相关支持,继承此类后我们需要实现doInBeforeTrace与doInAfterTrace方法,这两个方法相比AroundInterceptor接口中的before与after两个方法多出了SpanEventRecorder参数,利用该参数我们可以在拦截器中实现链路跟踪上报等处理逻辑:

讲透Pinpoint插件开发_第9张图片

2、实现TraceMetadataProvider接口

该接口同样只有一个简单的setup方法,该方法有一个参数TraceMetadataSetupContext,利用参数对象可以在插件工作前“声明”应用类型、应用属性,声明的内容将结合ProfilerPlugin实现使用:

讲透Pinpoint插件开发_第10张图片

第四步:定义ProfilerPlugin与TraceMetadataProvider配置

在 “resource/META-INF/services” 目录下加入ProfilerPlguin与TraceMetadataProvider配置文件,注意文件名为固定写法,文件内容分别指向对应插件实现类:

讲透Pinpoint插件开发_第11张图片

第五步:使用maven将插件打成jar包

点击右方maven窗口,选择插件项目 -> Lifecycle -> install

讲透Pinpoint插件开发_第12张图片

注意:pinpoint源码项目是通过“plugins”父项统一打包,如果要单独打包插件,需要将“assembly.xml”复制一份到插件项目根目录下(pom.xml平级)

如何使用Pinpoint插件

打包的插件应放在agent的plugin目录,web和collector的WEB-INF/lib目录。我们只需将插件打好的jar包加入到该目录下的plguin目录中,再将agent按javaagent的部署方式部署到对应采集节点,即可生效

以上插件开发中对demo项目的com.xxx.apm.demo1.DemoTargetClass.test()方法进行了采集,通过pinpoing-web服务可以跟踪到test()方法的执行了:

讲透Pinpoint插件开发_第13张图片

附录

官方插件列表:

pinpoint-cassandra-driver-plugin pinpoint-redis-plugin
pinpoint-json-lib-plugin pinpoint-thrift-plugin
pinpoint-user-plugin pinpoint-okhttp-plugin
pinpoint-google-httpclient-plugin pinpoint-vertx-plugin
pinpoint-jetty-plugin pinpoint-undertow-plugin
pinpoint-spring-boot-plugin pinpoint-kafka-plugin
pinpoint-ibatis-plugin pinpoint-node-js-plugin
pinpoint-mybatis-plugin pinpoint-commons-dbcp2-plugin
pinpoint-log4j-plugin pinpoint-jdk-http-plugin
pinpoint-dubbo-plugin pinpoint-tomcat-plugin
pinpoint-cxf-plugin pinpoint-grpc-plugin
pinpoint-hystrix-plugin pinpoint-spring-plugin
pinpoint-rxjava-plugin pinpoint-logback-plugin
pinpoint-weblogic-plugin pinpoint-activemq-client-plugin
pinpoint-undertow-servlet-plugin pinpoint-jboss-plugin
pinpoint-fastjson-plugin pinpoint-resin-plugin
pinpoint-hbase-plugin pinpoint-php-plugin
pinpoint-jsp-plugin pinpoint-akka-http-plugin
pinpoint-rabbitmq-plugin pinpoint-mongodb-driver-plugin
pinpoint-druid-plugin pinpoint-httpclient3-plugin
pinpoint-openwhisk-plugin pinpoint-ning-asynchttpclient-plugin
pinpoint-httpclient4-plugin pinpoint-resttemplate-plugin
pinpoint-gson-plugin pinpoint-netty-plugin
pinpoint-cubrid-jdbc-driver-plugin pinpoint-mysql-jdbc-driver-plugin
pinpoint-mariadb-jdbc-driver-plugin pinpoint-postgresql-jdbc-driver-plugin
pinpoint-jtds-plugin pinpoint-commons-dbcp-plugin
pinpoint-oracle-jdbc-driver-plugin pinpoint-hikaricp-plugin
pinpoint-arcus-plugin pinpoint-redis-lettuce-plugin
pinpoint-websphere-plugin pinpoint-jackson-plugin

官方ServiceType code:
讲透Pinpoint插件开发_第14张图片

(官方公有code与组件对应表1)

讲透Pinpoint插件开发_第15张图片
(官方公有code与组件对应表2)

讲透Pinpoint插件开发_第16张图片
(官方公有code与组件对应表3)

你可能感兴趣的:(pinpoint,apm,jvm,监控工具,性能监控)