Skywalking-02:如何写一个Skywalking trace插件
如何写一个Skywalking trace插件
javaagent 原理
类图

实现
ConsumeMessageConcurrentlyInstrumentation
public class ConsumeMessageConcurrentlyInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
// 需要增强的类
private static final String ENHANCE_CLASS = "com.aliyun.openservices.shade.com.alibaba.rocketmq.client.consumer.listener.MessageListenerConcurrently";
// 需要增强的方法
private static final String CONSUMER_MESSAGE_METHOD = "consumeMessage";
// 增加的方法对应的拦截器
private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.ons.v1.MessageConcurrentlyConsumeInterceptor";
// 构造器不需要拦截
@Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
// 新增一个拦截器
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
// 方法匹配
return named(CONSUMER_MESSAGE_METHOD);
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override
protected ClassMatch enhanceClass() {
// 需要增强的类
return HierarchyMatch.byHierarchyMatch(new String[] {ENHANCE_CLASS});
}
}
AbstractMessageConsumeInterceptor
public abstract class AbstractMessageConsumeInterceptor implements InstanceMethodsAroundInterceptor {
public static final String CONSUMER_OPERATION_NAME_PREFIX = "OnsRocketMQ/";
// 在方法前增强
@Override
public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
// 拿到方法参数,转换成消息列表
List<MessageExt> msgs = (List<MessageExt>) allArguments[0];
// 从消息中中获取TraceId等Context信息
ContextCarrier contextCarrier = getContextCarrierFromMessage(msgs.get(0));
// 创建一个entry span
AbstractSpan span = ContextManager.createEntrySpan(CONSUMER_OPERATION_NAME_PREFIX + msgs.get(0)
.getTopic() + "/Consumer", contextCarrier);
span.setComponent(ComponentsDefine.ROCKET_MQ_CONSUMER);
SpanLayer.asMQ(span);
for (int i = 1; i < msgs.size(); i++) {
ContextManager.extract(getContextCarrierFromMessage(msgs.get(i)));
}
}
// 异常处理
@Override
public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
private ContextCarrier getContextCarrierFromMessage(MessageExt message) {
ContextCarrier contextCarrier = new ContextCarrier();
CarrierItem next = contextCarrier.items();
while (next.hasNext()) {
next = next.next();
next.setHeadValue(message.getUserProperty(next.getHeadKey()));
}
return contextCarrier;
}
}
MessageConcurrentlyConsumeInterceptor
public class MessageConcurrentlyConsumeInterceptor extends AbstractMessageConsumeInterceptor {
// 在方法后处理
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
// 获取消费状态
ConsumeConcurrentlyStatus status = (ConsumeConcurrentlyStatus) ret;
if (status == ConsumeConcurrentlyStatus.RECONSUME_LATER) {
// 消费状态为重试,则设置span出现错误
AbstractSpan activeSpan = ContextManager.activeSpan();
activeSpan.errorOccurred();
Tags.MQ_STATUS.set(activeSpan, status.name());
}
// 停止span
ContextManager.stopSpan();
return ret;
}
}
参考文档
分享并记录所学所见
Skywalking-02:如何写一个Skywalking trace插件的更多相关文章
- 给Ionic写一个cordova(PhoneGap)插件
给Ionic写一个cordova(PhoneGap)插件 之前由javaWeb转html5开发,由于面临新技术,遂在适应的过程中极为挣扎,不过还好~,这个过程也极为短暂:现如今面临一些较为复杂的需求还 ...
- 如何写一个Js上传图片插件。
项目里面需要一个上传图片的插件,找了半天没有找到满意的,算了 不找了,自己写一个吧,顺便复习一下js方面的知识.完成之后效果还不错,当然还要继续优化,源码在最后. 介绍一种常见的js插件的写法 ; ( ...
- 用javascript写一个emoji表情插件
概述 以我们写的这个emoji插件为例,网上已经有一些相关的插件了,但你总感觉有些部分的需求不能被满足(如:可以自行添加新的表情包而不用去改源代码等等) 详细 代码下载:http://www.demo ...
- 写一个Vue loading 插件
什么是vue插件? 从功能上说,插件是为Vue添加全局功能的一种机制,比如给Vue添加一个全局组件,全局指令等: 从代码结构上说,插件就是一个必须拥有install方法的对象,这个方法的接收的第一个参 ...
- 改变滚动条的原始样式: chrome 可以改变, IE只能变相关颜色,firfox好像也不好改。最好是自己写一个或是用插件
相关作者链接地址: https://www.lyblog.net/detail/314.html 问题: 1.我在项目中遇到的问题: 在设置了::-webkit-scrollbar 后,滚动条不见了! ...
- 用原生js来写一个swiper滑块插件
是不是有点印象了,没错,他的最基本的用法就是左右滑动,插件使用者只需要写几行简单的html和js即可实现一个简单滑动效果,不过你完全可以组合各种元素来适应不同的场景. 当然插件我已经写好了,咱 ...
- 玉渊潭赏樱花有感:从无到有写一个jQuery开源插件
“玉渊潭公园樱花节”是每年樱花绽放时,都会在玉渊潭公园樱举办樱花节,游客前往玉渊潭公园,可以欣赏到20个品种2000株樱花.2016玉渊潭樱花节时间:3月中旬-4月中旬观赏最佳,2016年3月23日开 ...
- 纯后端尝试写一个前端slide插件
概述 由于项目组前端人员缺失,又赶上需要在手机端做一个slide效果的页面,所以只能自己硬着头皮上了,写的很简单,请大家不要笑话,只是拿出来分享下,大家先看下完成后的效果,如下: 过程 看了效果图是不 ...
- 怎么给Unity写一个原生的插件
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/50266889 作者:car ...
随机推荐
- PTA4题学习总结
前言: 这是我20多年以来第一次写博客了,还是在学校里那可(牛)爱(逼)的Java老师的安(逼)慰(迫)下,含泪写下第一篇博客,大家应该都明白这种含泪写下的佳(废)作(品)是多么的动人的. 就不开玩笑 ...
- mybatis入“坑”第一步
一.导入坐标 要想通过maven创建一个简单的mybatis项目,首先需要的是要导入相关的坐标.需要导入的坐标如下: <dependencies> <!--mysql驱动坐标--&g ...
- HashMap 中7种遍历方式的性能分析
随着 JDK 1.8 Streams API 的发布,使得 HashMap 拥有了更多的遍历的方式,但应该选择那种遍历方式?反而成了一个问题. 本文先从 HashMap 的遍历方法讲起,然后再从性能. ...
- 学习Qt Charts - Qt Charts的坐标轴
这次来学学Qt chart 的坐标轴 有这么一组数据: 这是深圳市2019年6月份的天气预报(来自中国天气网:深圳),里面有每天的最高温度,把这最高温度做成个数组,如下: int daily_temp ...
- Unity StateMachineBehaviour
在unity animator中单个Animator Clip中点击Add Behaviour增加当执行该动画时的一些状态代码,请看如下 创建完之后基本代码结构如下:(如果想修改默认代码结构,请看示例 ...
- C#获取字符串字符的位数(区分中文和英文长度)
请看以下代码 1 private static int GetStrLength(string str) 2 { 3 if (string.IsNullOrEmpty(str)) return 0; ...
- 多个异步ajax请求指定顺序执行
1.比如2个ajax请求,把第二个ajax请求放在第一个ajax请求success方法里面. 2.ajax请求时添加 async: false,//使用同步的方式,true为异步方式.结果是只有等服务 ...
- Pygame 入门基本指南
最近正在利用 Python 制作一个小游戏,但对于 Pygame 不熟悉,故在学习的过程记录相关知识点 Pygame 中文文档下载:Here Pygame第1-1课:入门 什么是Pygame? Pyg ...
- HTTP:Java实现HTTP请求的三种方式
目前JAVA实现HTTP请求的方法用的最多的有两种: 一种是通过HTTPClient这种第三方的开源框架去实现.HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,H ...
- linux学习之路第七天(压缩和解压类指令详解)
压缩和解压类 1.gzip/gunzip 指令 gzip 指令用于压缩文件, gunzip用于解压的 基本语法 gzip 文件 (功能描述:压缩文件,指令将文件压缩成*.gz文件) gunzip 文件 ...