pinpoint插件开发实践
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插件开发实践的更多相关文章
- vue插件开发实践与要点
其实就跟组件差不多意思,组件也可以实现相关的效果,但要在用到的地方都引用插件就可以全局注册,不需引用 试着撸一个插件,有2个功能,提示和对话框 网上找了个toast插件的代码,改了改,扩展加了个dia ...
- PyCharm插件开发实践-PyGetterAndSetter
背景需求 在面向对象的设计中,典型如Java语言,为了控制对象属性的修改入口,我们常用的做法是把属性设置为private,然后通过getter和setter方法访问.修改该属性. 但是在Pthon语言 ...
- 原生Javascript插件开发实践
前言 之前公司设计的网站比较混乱,很多地方不统一,其中一个就是弹出层,导致这个原因是因为,公司的UI换了好几个人,而他们每个人做出来的都不太一样.最近公司开始整顿这个问题,对于统一的这种东西当然是做成 ...
- Fiddler4插件开发实践
Fiddler4 是一款 巴拉巴拉..... 连接在这:http://www.telerik.com/fiddler 开发文档在这:http://docs.telerik.com/fiddler/Ex ...
- 🏆【Java技术专区】「开发实战专题」Lombok插件开发实践必知必会操作!
前言 在目前众多编程语言中,Java 语言的表现还是抢眼,不论是企业级服务端开发,还是 Andorid 客户端开发,都是作为开发语言的首选,甚至在大数据开发领域,Java 语言也能占有一席之地,如Ha ...
- Eclipse插件开发_学习_00_资源帖
一.官方资料 1.eclipse api 2.GEF Developer's Guide 二. 精选资料 1.开发 Eclipse 插件 2.Eclipse, RCP, Plugin and OSGi ...
- Hexo 相册实践
灵感 想给自已的blog添加一个相册功能.给生活中的点点滴滴留影记录.搜寻网络上给Next主题添加相册功能的基本上没有,只能重头到尾开始一点点的实践. 大致的想法: 1. 相册展示类似于归档一 ...
- 适合 JS 新手学习的开源项目——在 GitHub 学编程
作者:HelloGitHub-小鱼干 这里是 HelloGitHub 的<GitHub 上适合新手的开源项目>系列的最后一篇,系列文章: C++ 篇 Python 篇 Go 篇 Java ...
- 【转】.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 ...
随机推荐
- vue-router 响应路由参数的变化
提醒一下,当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用.因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效.不过,这也意味着组件的生命周 ...
- 【BIEE】11_根据显示指标展示不同报表
报表开发过程中,我们经常会需要根据所选择的不同指标,展示不同的报表!例如: 显示指标有:金额与合同数,可以根据显示指标选择的内容进行相应报表数据展示 一.环境准备 create table crm_i ...
- 【Python数据分析】
索引对象的其他功能 ①更换索引 ②对齐 ③删除 一.更换索引 我们已经知道,数据结构一旦声明,index对象就不能改变 事实上,我们重新定义索引之后,我们就能够用现有的数据结构生成一个新的数据机构 p ...
- Android API Guides---RenderScript
RenderScript RenderScript是在Android上的高性能执行计算密集型任务的框架. RenderScript主要面向与数据并行计算的使用.尽管串行计算密集型工作负载能够受益.该R ...
- DICOM医学图像处理:WEB PACS初谈二,图像的传输
背景: 如前一篇专栏博文所述,借助于CGI或FastCGI技术转发浏览器发送过来的用户请求,启动本地的DCMTK和CxImage库响应.然后将处理结果转换成常规图像返回到浏览器来实现Web PACS. ...
- android tooggle button
1 http://stackoverflow.com/questions/9938315/toggle-button-in-iphone-style 2 http://blog.csdn.net/bi ...
- PHP array_walk() 函数
定义和用法 array_walk() 函数对数组中的每个元素应用用户自定义函数.在函数中,数组的键名和键值是参数. <?php function myfunction($value,$key,$ ...
- 简易web服务器(java版)
//直接使用 ServerSocket 监听服务器端口,就能实现web服务器package ThreadPoolTest; import java.io.InputStream; import jav ...
- laravel学习之路2: jwt集成
"tymon/jwt-auth": "^1.0@dev", 执行 composer update 'providers' => [ .... Tymon\ ...
- PHP Memcached 面试题
这里收集了经常被问到的关于memcached的问题 * memcached是怎么工作的? * memcached最大的优势是什么? * memcached和MySQL的query cache相比,有什 ...