源码角度了解Skywalking之@Trace注解的原理
@Trace要解决的问题是收集一些关键业务的Trace信息,使用方法就是在需要收集Trace信息的方法上添加@Trace注解就可以了。
使用
@Trace(operationName = "default-trace-method")
public void traceMethod() throws Exception {
ActiveSpan.tag("trace-method",
String.valueOf(System.currentTimeMillis()));
ActiveSpan.info("traceMethod info Message");
System.out.println(TraceContext.traceId());
}
使用 @Trace 注释的方法,代理会创建localSpan。span操作名称的值将由operationName() 获取。如果 operationName()的值为空字符串,操作名将设置类名+方法名
方法中设置的tag,日志在Skywalking提供的前台界面中都能看到
实现原理
注解@Trace 的逻辑实现在apm-sniffer模块的apm-toolkit-activation子模块下,和其他插件一样,模块的内容主要包括三部分:
- def文件
- 切入点的定义类
- 对应切入点的拦截器
模块下的类的关系图如下:
@Trace注解的拦截
TraceAnnotationActivation
TraceAnnotationActivation实例方法切入点定义拦截标记Trace注解的方法,对应兰姐器为TraceAnnotationMethodInterceptor兰姐器
TraceAnnotationMethodInterceptor
TraceAnnotationMethodInterceptor的beforeMethod()
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
Trace trace = method.getAnnotation(Trace.class);
String operationName = trace.operationName();
if (operationName.length() == 0 || Config.Plugin.Toolkit.USE_QUALIFIED_NAME_AS_OPERATION_NAME) {
operationName = MethodUtil.generateOperationName(method);
}
ContextManager.createLocalSpan(operationName);
}
- 获取方法的Trace注解的操作名称,如果为空就生成操作名:类名+方法名
- 创建LocalSpan
afterMethod()方法关闭span
handleMethodException()方法中向span中添加错误的log日志
TraceContext.traceId()的拦截
TraceContextActivation定义了拦截TraceContext类的traceId()方法,对应兰姐器为TraceContextInterceptor
TraceContextInterceptor的beforeMethod()方法调用ContextManager.getGlobalTraceId()方法获取traceId来替换原来的traceId
ActiveSpan方法的拦截
ActiveSpan提供为当前活动跨度设置标签的自定义 api
ActiveSpanActivation拦截ActiveSpan的tag()方法,拦截器为ActiveSpanTagInterceptor,拦截器的beforeMethod()方法获取当前span,调用tag()添加tag信息
拦截ActiveSpan的debug()方法,拦截器为ActiveSpanDebugInterceptor,拦截器的beforeMethod()方法获取当前span,调用log()添加当前时间等debug级别日志信息
拦截ActiveSpan的info()方法,拦截器为ActiveSpanInfoInterceptor,拦截器的beforeMethod()方法获取当前span,调用info()添加当前时间等info级别日志信息
拦截ActiveSpan的error()方法,拦截器为ActiveSpanErrorInterceptor,拦截器的beforeMethod()方法获取当前span,调用errorOccurred()标记发生错误
拦截ActiveSpan的error(String errorMsg)方法,拦截器为ActiveSpanErrorMsgInterceptor,拦截器的beforeMethod()方法获取当前span,调用log()记录错误日志
拦截ActiveSpan的error(Throwable throwable)方法,拦截器为ActiveSpanErrorThrowableInteceptor,拦截器的beforeMethod()方法获取当前span,调用log()记录错误日志
总结
这篇文章主要讲了Skywalking的@Trace如何使用和它的原理,以及对TraceContext.traceId()的拦截和对ActiveSpan方法的拦截实现原理。@Trace注解可以让用户自定义需要记录trace信息的方法。TraceAnnotationActivation拦截带有@Trace注解的方法,然后通过TraceAnnotationMethodInterceptor增强拦截,具体就是创建LocalSpan记录Trace信息,TraceContextActivation拦截TraceContext.traceId()方法,拦截器替换之前的traceId
ActiveSpanActivation拦截ActiveSpan的一些方法,记录日志信息。
❤️ 感谢大家
如果你觉得这篇内容对你挺有有帮助的话:
- 欢迎关注我❤️,点赞????????,评论????,转发????
- 关注
盼盼小课堂
,定期为你推送好文,还有群聊不定期抽奖活动,可以畅所欲言,与大神们一起交流,一起学习。 - 有不当之处欢迎批评指正。