講透Pinpoint插件開發

什麼是Pinpoint插件

Pinpoint插件是pinpoint-agent的組成部分,pinpoint-agent經過對JVM字節碼的修改實現對代碼動做的採集,而具體的採集過程就是經過pinpoint插件來完成的。php

Pinpoint默認插件已有58個(1.8.3版本,見附錄),根據插件名能夠很快了解該插件針對採集的功能點。java

插件會對具體某類技術的「關鍵代碼」進行動做採集,如:jdk-http插件會切入到sun.net.www.protocol.http.HttpURLConnection的connect方法中,這些「關鍵代碼」使得其它全部上層框架組件的行爲調用都能被pinpoint採集到。node

官方提供的插件使得java的大部分生態應用的行爲都能經過簡單部署後採集得到,但對於新技術的出現 、企業內部業務的數據、特殊業務需求等狀況就須要有針對性的開發新插件來實現mysql

Pinpoint插件結構:

image.png

Pinpoint 插件由TraceMetadataProvider和ProfilerPlugin的實現組成,前者的實現給agent、collector、web三組件提供ServiceType和AnnotationKey,然後者的實現用於給agent使用,主要用來修改目標類、記錄跟蹤數據等操做。 web

那麼ServiceType和AnnotationKey的做用是什麼呢?其實每一個 Span 和 SpanEvent 都包含一個 ServiceType,這個ServiceType表示跟蹤方法所屬的庫,以及跟蹤它的Span和spanevent應該如何處理,並且ServiceType是非序列化傳輸的,爲了儘可能壓縮 Agent 到 Collector 數據包的大小,ServiceType 被設計成不是以序列化字符串的形式發送的,而是以整形數字發送的 (code 字段),這就須要創建一個映射關係,將 code 轉換成對應的 ServiceType 實例,這個映射機制就是由 TraceMetadataProvider 負責的redis

若是要編寫一個將被公開共享的插件,就必須聯繫pinpoint團隊來得到分配的ServiceType code(官方已使用的ServiceType code見附錄)spring

所以開發非共享的插件,可以使用如下範圍code:
image.png
( 非公開code與組件對應範圍表)sql

再來講說AnnotationKey,Annotation 是包含在 Span 和 SpanEvent 中的更詳盡的數據,以鍵值對的形式存在,鍵就是AnnotationKey,值是基本類型,String或者byte[]mongodb

最後須要注意的是:ServiceType code和AnnotationKey code必須是全局唯一的json

插件開發步驟

開發Pinpoint插件主要分爲如下四步:

  1. 實現TraceMetadataProvider
  2. 實現ProfilerPlugin
  3. 將TraceMetadataProvider與ProfilerPlugin實現配置到META-INF\services中的並打包插件
  4. 部署插件

插件開發演示

下面以開發一個demo插件爲例,演示pinpoint插件的開發過程:

第一步:基於pinpoint源碼項目,在「plugins」子模塊下新建插件子模塊

一、 將pinpoint源碼在本地項目中導入並調試經過

image.png

二、 在Plugins模塊下點擊右鍵,New->Module新增子模塊:

image.png

選擇Maven類型,進入下一步,輸入插件ArtifactId,由於是demo演示,因此這裏咱們ArtifactId就叫:「pinpoint-demo-plugin」:

image.png

點擊「下一步」->輸入「Module_name」->點擊「完成」:

image.png

第二步:編輯pom.xml,引入插件必要的依賴及配置

一、加入父工程依賴關係:

<parent>
 <groupId>com.navercorp.pinpoint</groupId>
 <artifactId>pinpoint</artifactId>
 <relativePath>../..</relativePath>
 <version>1.8.3</version>
</parent>

二、加入屬性設置,設置編譯使用的JDK目錄,及編譯的版本,因爲官方推薦使用的是JDK8所以使用JDK8目錄,但編譯的版本考慮兼容性等緣由,採用1.6:

<properties>
    <jdk.version>1.6</jdk.version>
    <jdk.home>${env.JAVA_8_HOME}</jdk.home>
    <sniffer.artifactid>java18</sniffer.artifactid>
</properties>

注意:pinpoint項目要成功跑起來,須要按官方要求配置「JAVA_6_HOME、JAVA_7_HOME、JAVA_8_HOME、JAVA_9_HOME」等環境變量

三、設置模塊項目基本信息

<artifactId> pinpoint-demo-plugin </artifactId>
<name>pinpoint-demo-plugin</name>
<packaging>jar</packaging>

四、設置依賴管理:pinpoint-plugin-bom

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.navercorp.pinpoint</groupId>
            <artifactId>pinpoint-plugin-bom</artifactId>
            <version>${project.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

五、設置項目依賴,可根據狀況加入私人插件所需求的第三方依賴,另外插件默認須要依賴pinpoint-bootstrap-core提供基礎支持

<dependencies>
    <dependency>
        <groupId>com.navercorp.pinpoint</groupId>
        <artifactId>pinpoint-bootstrap-core</artifactId>
        <scope>provided</scope>
    </dependency>
    ………
</dependencies>

第三步:實現ProfilerPlugin接口和TraceMetadataProvider接口

一、實現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負責具體的字節碼加強邏輯:

image.png

image.png

最後,我只還須要編寫攔截器的具體處理邏輯,攔截器的實現一般經過實現AroundInterceptor接口完成,這是一種簡單的實現方式,能夠用來實現咱們本身的處理邏輯,相似於Spring AOP機制。而作爲pinpoint插件開發,大多狀況下會與當前插件採集的應用調用相關,咱們能夠經過繼承SpanEventSimpleAroundInterceptorForPlugin的方式來實現攔截器,該類爲抽象類,實現了AroundInterceptor接口並加入了鏈路跟蹤等相關支持,繼承此類後咱們須要實現doInBeforeTrace與doInAfterTrace方法,這兩個方法相比AroundInterceptor接口中的before與after兩個方法多出了SpanEventRecorder參數,利用該參數咱們能夠在攔截器中實現鏈路跟蹤上報等處理邏輯:

image.png

二、實現TraceMetadataProvider接口

該接口一樣只有一個簡單的setup方法,該方法有一個參數TraceMetadataSetupContext,利用參數對象能夠在插件工做前「聲明」應用類型、應用屬性,聲明的內容將結合ProfilerPlugin實現使用:

image.png

第四步:定義ProfilerPlugin與TraceMetadataProvider配置

在 「resource/META-INF/services」 目錄下加入ProfilerPlguin與TraceMetadataProvider配置文件,注意文件名爲固定寫法,文件內容分別指向對應插件實現類:

image.png

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

點擊右方maven窗口,選擇插件項目 -> Lifecycle -> install

image.png

注意: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()方法的執行了:

image.png

附錄

官方插件列表:

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:
image.png

(官方公有code與組件對應表1)

image.png
(官方公有code與組件對應表2)

image.png(官方公有code與組件對應表3)

相關文章
相關標籤/搜索