Tracer 工具类

本文主要对 SOFA Tracer 工具类进行介绍。

虚拟日志上下文工具类

Tracer 提供 DummyContextUtil 类,对虚拟日志(dummy log)上下文进行操作。

说明

使用 DummyContextUtil 创建虚拟日志上下文时,必须及时调用对应的销毁方法进行销毁。建议将对销毁方法的调用写入 finally 方法中。

创建虚拟日志上下文

定义:public static void createDummyLogContext() throws Exception

说明:创建一个虚拟日志上下文,并且将其设置到线程上下文中。如果当前线程上下文中已经有了一个日志上下文,则抛出异常。

清理虚拟日志上下文

定义:public static void clearDummyLogContext() throws Exception

说明:清除当前的虚拟的日志上下文。如果当前线程上下文中的日志上下文不是 DummyLogContext,则抛出异常。

设置全链路压测标记,通过 clearDummyLogContext 类进行调用,如下代码所示:

DummyContextUtil.createDummyLogContext();
DummyContextUtil.addPenetrateAttribute(PenAttrKeyEnum.LOAD_TEST_MARK,"T");
DummyContextUtil.clearDummyLogContext();

Tracer 上下文工具类

此工具类的主要作用是为业务方提供获取 traceId 的统一方法,另外还提供了获取和设置穿透数据的 API,类名为 TracerContextUtil,使用方法如下:

获取当前的 Tracer 上下文中 TraceId

代码示例:

String traceId =TracerContextUtil.getTraceId();
说明

  • 如果当前的 Tracer 上下文为空,此方法返回一个空字符串。

  • 如果当前的 Tracer 上下文不为空,但是 traceId 为空,则返回一个空字符串。

  • 如果当前的 Tracer 上下文不为空,同时 traceId 不为空,则返回 traceId 本身。

说明

获取 TraceId,前提是存在 TracerContext,而 TracerContext 的创建分为两种情形: SOFA MVC 系统:每一次访问时作为入口创建一个 TracerContext,如果想激活 MVC 请求的 Tracer 功能,还需要在 sofa-config 配置文件里配置上 mvc_toolbox_plugin=ACTIVE 来激活 MVC 的插件。 SOFA CORE 系统:作为 RPC 等中间件首次发生调用的时候创建。

在链路中添加自定义 Tag

在个性化业务场景中,您可以通过在业务类中调用 Tracer 类的方式,来设置自定义 tag 及对应的值,示例代码如下:

 public void handlerXxx(Map<String,String> request){
        SofaTraceContext ctx =SofaTraceContextHolder.getSofaTraceContext();
        SofaTracerSpan span = ctx.getCurrentSpan();
        //显式依赖 Tracer,会带来一定侵入性,请做好封装。
        if(span !=null){
            //将参数添加到自定义tag:xxx_phone 中
            span.setTag("xxx_phone", request.get("phone"));
        }
        // 处理业务逻辑
        // ...
    }

有关自定义 Tag 的更多信息,参见 添加自定义业务 Tag

设置穿透数据

代码示例:

TracerContextUtil.putPenetrateAttribute("Hello","World");

说明:

  • 如果当前传入的 key 或者 value 为 null,则抛出 TracerException。

  • 如果当前的 Tracer 的上下文为空,则抛出 TracerException。

  • 当加入该穿透数据,如果整体穿透数据量超过了最大的限制(目前最大的限制为 1024 个字符),则抛出 TracerException。

关于 key 的说明:

由于此接口的 key 是全站共享的,所以使用这个 key 的时候,必须保证不和其他 key 冲突,所以 Tracer 中保留的 key 存在 uid 和 mark 两个字段。

获取 Tracer 中的穿透数据

代码示例:

TracerContextUtil.getPenetrateAttribute("Hello");
说明

  • 如果当前的 Tracer 的上下文不为空,并且 Tracer 上下文中根据 key 取到的穿透数据为 null,则返回一个空字符串。

  • 如果当前的 Tracer 的上下文不为空,并且 Tracer 上下文中根据 key 取到的穿透数据不为 null,则返回穿透数据。

  • 如果 key 为 null,则抛出该异常。

  • 如果当前的 Tracer 的上下文为空,则抛出该异常。

克隆当前线程的 Tracer 日志上下文

如果业务系统有自己的线程池来处理一些事情,那么业务开发人员就可能需要获取当前线程的 Tracer 日志上下文,来设置到子线程里面去。在 Tracer 1.0.15 之前的版本,都是直接通过 API 来获取父线程的 Tracer 上下文,然后设置到子线程里面的。这样,父子线程就共享一份 Tracer 日志上下文,有可能出现在一个线程里修改,却影响了另一个线程的情况。

所以在 Tracer 1.0.15 中,提供一个克隆当前线程的 Tracer 日志上下文的 API。如果有需要往子线程中设置的话,可以采用此 API 来从父线程中复制一份,防止出现相互影响的状况,代码示例如下:

AbstractLogContext abstractLogContext =TracerContextUtil.cloneLogContext();
说明

  • 如果当前线程的 Tracer 日志上下文为空,则返回 null。

  • 如果当前线程的 Tracer 日志上下文不为空,则返回此上下文的一份克隆。

全链路工具类

提供静态方法对全链路压测进行判断,类名为:LoadTestUtil

定义:public static boolean isLoadTestMode()

说明:判断当前是否为全链路压测。如果当前线程上下文中取不到日志上下文,则返回 false。如果能够取到并且压测标记为 T,则返回 true;否则,返回 false。

当全链路压测模式开启时,日志文件会打印在 ${logging.path}/logs/tracelog/shadow/ 目录下,同时在日志文件的透传数据的字段会有mark=T 标识。