如何从源码层面探究Skywalking中@Trace注解的工作机制?

2026-05-28 00:222阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计843个文字,预计阅读时间需要4分钟。

如何从源码层面探究Skywalking中@Trace注解的工作机制?

%E2%80%9CSkywalking%E4%B8%AD@Trace%E6%B3%A8%E8%A7%A3%E7%9A%84%E5%8E%9F%E7%90%86%E5%8F%8A%E5%BA%94%E7%94%A8%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BD%BF%E7%94%A8@Trace%E6%98%AF%E6%94%B6%E9%9B%86%E5%85%B3%E9%94%AE%E4%B8%9A%E5%8A%A1%E8%BF%87%E7%A8%8B%E4%BF%A1%E6%81%AF%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E7%94%A8%E6%B3%95%E4%BB%A5%E5%9C%A8%E9%9C%80%E8%A6%81%E6%94%B6%E9%9B%86%E4%BF%A1%E6%81%AF%E7%9A%84%E6%96%B9%E6%B3%95%E4%B8%8A%E6%B7%BB%E5%8A%A0@Trace%E6%B3%A8%E8%A7%A3%E3%80%82%E2%80%9D

源码角度了解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信息

    如何从源码层面探究Skywalking中@Trace注解的工作机制?

    拦截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的一些方法,记录日志信息。

    ❤️ 感谢大家

    如果你觉得这篇内容对你挺有有帮助的话:

  • 欢迎关注我❤️,点赞
  • 本文共计843个文字,预计阅读时间需要4分钟。

    如何从源码层面探究Skywalking中@Trace注解的工作机制?

    %E2%80%9CSkywalking%E4%B8%AD@Trace%E6%B3%A8%E8%A7%A3%E7%9A%84%E5%8E%9F%E7%90%86%E5%8F%8A%E5%BA%94%E7%94%A8%E6%96%B9%E6%B3%95%EF%BC%8C%E4%BD%BF%E7%94%A8@Trace%E6%98%AF%E6%94%B6%E9%9B%86%E5%85%B3%E9%94%AE%E4%B8%9A%E5%8A%A1%E8%BF%87%E7%A8%8B%E4%BF%A1%E6%81%AF%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E7%94%A8%E6%B3%95%E4%BB%A5%E5%9C%A8%E9%9C%80%E8%A6%81%E6%94%B6%E9%9B%86%E4%BF%A1%E6%81%AF%E7%9A%84%E6%96%B9%E6%B3%95%E4%B8%8A%E6%B7%BB%E5%8A%A0@Trace%E6%B3%A8%E8%A7%A3%E3%80%82%E2%80%9D

    源码角度了解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信息

    如何从源码层面探究Skywalking中@Trace注解的工作机制?

    拦截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的一些方法,记录日志信息。

    ❤️ 感谢大家

    如果你觉得这篇内容对你挺有有帮助的话:

  • 欢迎关注我❤️,点赞