plugin基本结构

一个plugin主要由三部分构成,插件类增强定义(ProfilerPlugin接口实现)、插件描述定义(TraceMetadataProvider接口实现)、增强类拦截器实现(AroundInterceptor接口实现)

举个栗子

1、插件定义

ProfilerPlugin 接口只有一个setup方法,插件加载时会调用setup方法,一般我们会在这个时候对指定的类进行增强。同时一般还会实现TransformTemplateAware接口,通过这个接口可以拿到TransformTemplate对象,对类进行增强主要是通过这个类。

public class OpenSearchPlugin implements ProfilerPlugin, TransformTemplateAware {

    private TransformTemplate transformTemplate;
@Override
public void setup(ProfilerPluginSetupContext context) {
OpenSearchConfig config = new OpenSearchConfig(context.getConfig());
if (!config.isEnable()) {
return;
}
addTransformers();
}
private void addTransformers() {
transformTemplate.transform("com.aliyun.opensearch.CloudsearchClient", new TransformCallback() {
@Override
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer);
InstrumentMethod method = target.getDeclaredMethod("call","java.lang.String","java.util.Map","java.lang.String","boolean","java.lang.StringBuffer");
method.addInterceptor("com.navercorp.pinpoint.plugin.opensearch.interceptor.OpenSearchInterceptor");
return target.toBytecode();
}
});
}
@Override
public void setTransformTemplate(TransformTemplate transformTemplate) {
this.transformTemplate = transformTemplate;
}
}

  上面这个例子,我们对CloudsearchClient类进行了增强,具体增强的是call方法,最后指定了对应的拦截器OpenSearchInterceptor

通过ProfilerPluginSetupContext.getConfig()可以拿到我们在pinpoint.config中的配置。

2、插件描述定义

public class OpenSearchTypeProvider implements TraceMetadataProvider{
@Override
public void setup(TraceMetadataSetupContext context) {
context.addServiceType(OpenSearchConstant.OPEN_SEARCH_SERVICE, AnnotationKeyMatchers.ARGS_MATCHER);
context.addAnnotationKey(OpenSearchConstant.SEARCH_INDEX_NAME);
context.addAnnotationKey(OpenSearchConstant.SEARCH_QUERY);
}
}

这里指定了插件的服务名称为OPEN_SEARCH_SERVICE,增加了两个参数:SEARCH_INDEX_NAME和SEARCH_QUERY,这个主要是在链路详情中显示自定义的参数

这里如果不配置,在web页面上是没办法显示的。

3、拦截器实现

public class OpenSearchInterceptor implements AroundInterceptor {

    private static final String    OPEN_SEARCH = "openSearch";
private final MethodDescriptor descriptor;
private final TraceContext traceContext; public OpenSearchInterceptor(TraceContext traceContext, MethodDescriptor descriptor){
this.descriptor = descriptor;
this.traceContext = traceContext;
} private boolean getWwitch() {
String applicationName = traceContext.getApplicationName();
if (!traceContext.collectSwitch(applicationName, OPEN_SEARCH, null)) {
return false;
}
return true;
} @Override
public void before(Object target, Object[] args) {
if (!getWwitch()) {
return;
} Trace trace = traceContext.currentTraceObject();
if (trace == null) return;
SpanEventRecorder recorder = trace.traceBlockBegin();
recorder.recordServiceType(OpenSearchConstant.OPEN_SEARCH_SERVICE); } @Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
if (!getWwitch()) {
return;
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) return;
try {
// String path = (String) args[0];
Map<String, String> param = (Map<String, String>) args[1];
// String method= (String) args[2];
// Boolean isPb= (Boolean) args[3];
// StringBuffer sb= (StringBuffer) args[4];
SpanEventRecorder recorder = trace.currentSpanEventRecorder();
// String format=param.get("format");
String indexName = param.get("index_name");
String query = param.get("query");
recorder.recordApi(descriptor, new Object[] { indexName });
recorder.recordException(throwable);
recorder.recordAttribute(OpenSearchConstant.SEARCH_INDEX_NAME, indexName);
recorder.recordAttribute(OpenSearchConstant.SEARCH_QUERY, query);
recorder.recordServiceType(OpenSearchConstant.OPEN_SEARCH_SERVICE);
recorder.recordDestinationId(OpenSearchConstant.OPEN_SEARCH_DESTINATION);
// recorder.recordAttribute(AnnotationKey.ARGS0,indexName); if (target instanceof BaseUriGetter) {
String endPoint = ((BaseUriGetter) target)._$PINPOINT$_getBaseURI();
recorder.recordEndPoint(endPoint);
}
} finally {
trace.traceBlockEnd();
}
}
}

拦截器的实现主要是一个before和after方法,对应我们的方法执行前和执行后。

通过SpanEventRecorder可以写入一条链路详情到调用链中。

附上插件类图:

pinpoint插件开发实践的更多相关文章

  1. vue插件开发实践与要点

    其实就跟组件差不多意思,组件也可以实现相关的效果,但要在用到的地方都引用插件就可以全局注册,不需引用 试着撸一个插件,有2个功能,提示和对话框 网上找了个toast插件的代码,改了改,扩展加了个dia ...

  2. PyCharm插件开发实践-PyGetterAndSetter

    背景需求 在面向对象的设计中,典型如Java语言,为了控制对象属性的修改入口,我们常用的做法是把属性设置为private,然后通过getter和setter方法访问.修改该属性. 但是在Pthon语言 ...

  3. 原生Javascript插件开发实践

    前言 之前公司设计的网站比较混乱,很多地方不统一,其中一个就是弹出层,导致这个原因是因为,公司的UI换了好几个人,而他们每个人做出来的都不太一样.最近公司开始整顿这个问题,对于统一的这种东西当然是做成 ...

  4. Fiddler4插件开发实践

    Fiddler4 是一款 巴拉巴拉..... 连接在这:http://www.telerik.com/fiddler 开发文档在这:http://docs.telerik.com/fiddler/Ex ...

  5. 🏆【Java技术专区】「开发实战专题」Lombok插件开发实践必知必会操作!

    前言 在目前众多编程语言中,Java 语言的表现还是抢眼,不论是企业级服务端开发,还是 Andorid 客户端开发,都是作为开发语言的首选,甚至在大数据开发领域,Java 语言也能占有一席之地,如Ha ...

  6. Eclipse插件开发_学习_00_资源帖

    一.官方资料 1.eclipse api 2.GEF Developer's Guide 二. 精选资料 1.开发 Eclipse 插件 2.Eclipse, RCP, Plugin and OSGi ...

  7. Hexo 相册实践

    灵感 想给自已的blog添加一个相册功能.给生活中的点点滴滴留影记录.搜寻网络上给Next主题添加相册功能的基本上没有,只能重头到尾开始一点点的实践.    大致的想法:  1. 相册展示类似于归档一 ...

  8. 适合 JS 新手学习的开源项目——在 GitHub 学编程

    作者:HelloGitHub-小鱼干 这里是 HelloGitHub 的<GitHub 上适合新手的开源项目>系列的最后一篇,系列文章: C++ 篇 Python 篇 Go 篇 Java ...

  9. 【转】.NET(C#):浅谈程序集清单资源和RESX资源 关于单元测试的思考--Asp.Net Core单元测试最佳实践 封装自己的dapper lambda扩展-设计篇 编写自己的dapper lambda扩展-使用篇 正确理解CAP定理 Quartz.NET的使用(附源码) 整理自己的.net工具库 GC的前世与今生 Visual Studio Package 插件开发之自动生

    [转].NET(C#):浅谈程序集清单资源和RESX资源   目录 程序集清单资源 RESX资源文件 使用ResourceReader和ResourceSet解析二进制资源文件 使用ResourceM ...

随机推荐

  1. Snail—UI学习之UITextField

    简单看一下UITextField的属性 - (void)createTextField{ UITextField * textField = [[UITextField alloc] initWith ...

  2. C/C++中字符串与数字之间的转换

    主要有两种方式:C 中能够使用 sprintf 将数字转为字符数组,sscanf 将字符数组转为数字:而在 C++ 中不仅能够使用 C 中的方法,还能够使用 stringstream 实现字符串与数字 ...

  3. php数组操作,内容相同,键值不同,互换

    $title = array("A"=>"创建时间","C"=>"商品信息","D"=& ...

  4. java网络编程(2)InetAddress 类及udp协议

    InetAddress 类 JDK中为开发网络应用程序提供了java.net包,该包下的类和接口差点儿都是为网络编程服务的. InetAddress:用于描写叙述IP地址的对象 InetAddress ...

  5. reveal end of document

     window - Preferences - Run/Debug - Console 将 Console buffer size (characters)设置大一点

  6. [转]python 书籍推荐

    原地址: http://python.jobbole.com/85620/ https://github.com/jobbole/awesome-python-books http://blog.cs ...

  7. windows db2 添加用户权限

    http://www.csharpwin.com/csharpspace/12086r9069.shtml 在windows上DB2数据库安装的时候会创建一个系统管理员 的账户,默认为DB2ADMIN ...

  8. nginx 不能解析php怎么办

    在服务器下源码安装了 mysql php  nginx,结果nginx不支持php.解决方法,在nginx配置文件中添加: ocation ~ .*\.php?$ { fastcgi_pass 127 ...

  9. React antd嵌入百度编辑器(css加载不到等问题,'offsetWidth' of null)

    之前有看过一些类似的文章,以为嵌入不会遇到太多坑 结果...    其他不说,先来描述下跳坑的过程 先定义Ueditor.js类,这个和网上版本类似 import React, { Component ...

  10. EventBus的使用详解,功能为在Fragment,Activity,Service,线程之间传递消息

    最近跟同事用到了EventBus的使用,之前不太了解EventBus,查阅资料发现EventBus还挺好用的,用法比较简单,下面就把我看到的关于EventBus的博客分享给大家,里面介绍了很多的使用详 ...