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 ...
随机推荐
- Python内置模块和第三方模块
1.Python内置模块和第三方模块 内置模块: Python中,安装好了Python后,本身就带有的库,就叫做Python的内置的库. 内置模块,也被称为Python的标准库. Python 2.x ...
- 使用 react-native-tab-navigator 创建 TabBar 组件
1.首先安装好ReactNative的运行环境,安装组件依赖库 使用npm install react-native-tab-navigator --save安装所依赖的第三方库 2.导入 impor ...
- magento安装wordpress
说起来事实上很easy,如今简诉一下安装过程 1.到magento connect界面安装magento扩展,地址:http://www.magentocommerce.com/magento-con ...
- MySql修改root密码、设置IP访问
先登录:mysql -h 192.168.5.116 -P 3306 -u root -p123456 首次登陆无密码命令:mysql -h 192.168.5.116 -P 3306 -u root ...
- PowerShell-将CSV导入SQL Server
$database = 'foxdeploy' $server = '.' $table = 'dbo.powershell_test' Import-CSV .\yourcsv.csv | ForE ...
- jenkins构建java项目找不到命令mvn,java的解决方法
jenkins构建java项目时出现的报错情况: $ mvn clean install FATAL: command execution failed java.io.IOException: er ...
- Spring使用经验之StandardServletMultipartResolver实现文件上传的基本配置
Note:Spring使用版本是4.1.6.RELEASE 1. 在实现了AbstractAnnotationConfigDispatcherServletInitializer的类中重载custom ...
- 将NSArray反向排序
NSArray * array = [NSArray arrayWithObjects:", nil]; NSArray * reverseArray = [[array reverseOb ...
- PHP面试题及答案解析(1)—PHP语法基础
1. strlen( )与 mb_strlen( )的作用分别是什么? strlen和mb_strlen都是用于获取字符串长度.strlen只针对单字节编码字符,也就是说它计算的是字符串的总字节数.如 ...
- Hibernate学习之一级缓存
© 版权声明:本文为博主原创文章,转载请注明出处 Hibernate缓存: - 缓存是为了降低应用程序对物理数据源访问的频次,从而提供应用程序的运行性能的一种策略 - Hibernate缓存是提升和优 ...