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可以写入一条链路详情到调用链中。

附上插件类图:

最新文章

  1. 更改Windows系统时间同步频率【windows 7,windows 8,win10】
  2. TCP/IP详解 学习七
  3. SQL游标应用
  4. 第十章 Vim程序编辑器学习(下)
  5. C和C++头文件的不同
  6. iOS项目开发中的目录结构
  7. 如何把bootstrap用webpack打包
  8. 基于MapReduce的关系代数运算(2)
  9. android - DefaultHttpClient设置超时.
  10. DirectFB学习笔记四
  11. Ultimus BPM 金融与证券行业应用解决方案
  12. EclipseIDE--使用整理
  13. Spring第一篇【介绍Spring、引入Spring、Spring六大模块】
  14. 聊聊Linux用户态驱动设计
  15. 20165230 《Java程序设计》第1周学习总结
  16. [Swift]LeetCode1036.逃离大迷宫 | Escape a Large Maze
  17. Azkaban日志中文乱码问题解决
  18. pythonのdjango
  19. 探寻TP-Link路由器的登录验证
  20. redis集群(jedis)批量删除同一前缀

热门文章

  1. awk、sed、cut、grep
  2. Eclipse.ini参数设置
  3. rsync断点续传
  4. Write operations are not allowed in read-only mode (FlushMode.MANUAL)
  5. nginx 内置变量大全
  6. 自动化测试工具 - Unified Functional Testing
  7. ConcurrentHashMap的使用和原理
  8. xml初学简单介绍
  9. 织梦DedeCMS自定义表单提交成功后返回当前页面的教程
  10. Agri-Net - poj 1258 (Prim 算法)