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 ...
随机推荐
- docker基本底层原理
docker是怎么工作的 Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket客户端进行访问 DockerServer接收到DockerClie ...
- 11张流程图搞定 Spring Bean 生命周期
在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近把整个流程化成了一个流程图.待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程.注意因为代码比较多,这里的流程图 ...
- Go语言获取Ubuntu所有网卡名
Go语言获取Ubuntu所有网卡名 需求 获取当前机器下所有网卡名,以字符串数组的形式返回 实现demo package main import ( "fmt" "os/ ...
- 8、mysql乱码问题及字符集实战
8.1.mysql插入中文数据乱码案例: mysql建库的字符集为latin1,客户端的字符集为utf8; use lc; 1.查看库的编码: mysql> show create databa ...
- AcWing 342. 道路与航线
#include<bits/stdc++.h> using namespace std; const int N=2e5+5; int h[N],cnt,to[N],nxt[N],vis[ ...
- 深入理解 PHP7 中全新的 zval 容器和引用计数机制
深入理解 PHP7 中全新的 zval 容器和引用计数机制 最近在查阅 PHP7 垃圾回收的资料的时候,网上的一些代码示例在本地环境下运行时出现了不同的结果,使我一度非常迷惑. 仔细一想不难发现问题所 ...
- ctf实验吧天网管理系统
这明显不可能登上的,所以直接看源代码 这里如果不懂得,php中处理哈希值的方式,是只要是0e开头的哈希值,都认为是0,通过输入一个这样的0e开头的字符串,会被php解释成0. 这个可以去在线工具上得到 ...
- bugKu变量1
重点:两个$$,这暗示着第二个$变量的值,作为第一个$的名称. 而且代码审计之后,发现只含有字母. 又暗示在变量中,那么猜想是在全局变量中,而php中全局变量是$GLOBALS.
- centos搭建dns服务器
前言:搭建dns服务器,dns服务器我就不多说什么了,大家都懂,就是域名解析,就将ip装换为域名,域名就可以理解为类似这样的www.baidu.com网址,接下来我就直接上图了.这里面最重要的是修改u ...
- DRF之JWT认证
一.JWT认证 JWT构成 JWT分为三段式:头.体.签名(head.payload.sgin) 头和体是可逆加密的,让服务器可以反解析出user对象,签名是不可逆加密,保证整个token的安全性的. ...