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 ...
随机推荐
- 标准库Allocator的使用(一)
上一篇我们提到了new运算符以及它的工作步骤,其实无非是把两项工作独立出来: 1.申请原始内存 2.执行构造函数 delete也涉及了两个工作: 1.执行析构函数 2.释放原始内存 其实标准库提供了另 ...
- BaseAdapter的使用(笔记)
适配器模式的应用: 1.减少程序耦合性 2.easy扩展 BaseAdapter ListView的显示与缓存机制:须要才显示,显示完就被会受到缓存. BaseAdapter基本结构 --public ...
- Android高级控件(三)—— 使用Google ZXing实现二维码的扫描和生成相关功能体系
Android高级控件(三)-- 使用Google ZXing实现二维码的扫描和生成相关功能体系 摘要 如今的二维码可谓是烂大街了.到处都是二维码.什么都是二维码,扫一扫似乎已经流行到习以为常了,今天 ...
- iOS时间间隔判断
如何计算两个NSDate之间的时间间隔呢? timeIntervalSinceDate: Returns the interval between the receiver and another g ...
- android CheckBox控件的定义及事件监听
http://www.beijibear.com/index.php?aid=336 android CheckBox控件的定义及事件监听,本例实现CheckBox控件的定义及点击事件的监听并显示结果 ...
- GetTickCount()函数的陷阱!
开发中经经常使用GetTickCount()函数来进行间隔时间的推断.如推断某一段代码运行花了多少时间等,使用比較方便. 可是仅仅针对寻常的一些測试.近期开发一个服务程序时,也在代码中用GetTick ...
- 浅谈"壳"(一)
壳,即坚硬的外皮,当壳的厚度与其曲面率半径的比值小于0.5时.称为"薄壳".反之称为"厚壳".由壳演化来的胸甲,盾牌. 在计算机这个注重创意又不失从文化科技中汲 ...
- windows_64下python下载安装Numpy、Scipy、matplotlib模块
本文应用的python3.6.3及其对应的Numpy.Scipy.matplotlib计算模块的cp36版本,其中Numpy是需要MKL版本的Numpy,这是后续安装Scipy的需要(本机系统win7 ...
- busybox下inittab中runlevel解析
Order of scripts run in /etc/rc?.d ================================== 0. Overview. All scripts execu ...
- Docker-Compose 自动创建的网桥与局域网冲突解决方案
环境: 使用docker-compose.yml 部署应用,docker 默认的网络模式是bridge ,默认网段是172.17.0.1/16 ,不巧的是我们局域网也使用的172.22. xx 网段 ...